I have created an application, but now I am trying to adapt it into a SPA application. The main issue I am facing is with the Authorization process.
While I can successfully register new users, log them in, and retrieve their tokens, I seem to encounter an error when attempting to validate the token in my middleware. I suspect there might be something wrong within step 3 (as steps 1-2 are functioning correctly), however, I have included all steps along with the relevant code for each step.
Could someone please assist me in identifying what I may be doing incorrectly?
1> Registering a new account (storing the account in the DB)
Backend:
router.post("/register", function(req, res){
CreateUser(req.body.username, req.body.password, 0, function(err, nwUser){
if(err){
console.log('error: ');
return res.redirect("register"); //TODO: show the error message in 'err'
}
passport.authenticate("local")(req, res, function(){
console.log('success, going to try to create a token:');
//secret key,TODO: set in variable (or better environment)
const token = jwt.sign(nwUser.toJSON(), "SECRETCODE");
const result = res.json({nwUser, token});
return result;
});
});
});
2> Logging in to an account (if successful, sending an encrypted token to the Client (Angular))
Backend:
router.post('/login',passport.authenticate('local'), function(req, res) {
User.findById(req.user._id, function(err, foundUser){
if(err){
console.log('Error with logging in!');
console.log(err);
return err;
}
const token = jwt.sign(foundUser.toJSON(), "SECRETCODE");
const result = res.json({foundUser, token});
return result;
});
});
3> If a request now requires authorization, the client(Angular) should also send the token with the request and the backend checks if the token is valid (inside the middleware). If so, the data is returned.
How I send the data from Angular:
const headers: HttpHeaders = new HttpHeaders();
headers.append('Authorization', 'Bearer ' + this.authService.getToken());
console.log('token before sending in data-storage: ' + this.authService.getToken());
this.httpClient.get<Category[]>(environment.backendServer + '/categories/',
{observe: 'body', responseType: 'json', headers: headers}).pipe(map(
(categories) => {
console.log(categories);
return categories;
}
)).subscribe(
(categories: Category[]) => {
this.categoryService.setCategories(categories);
}
);
Middleware used on the backend:
middlewareObj.authenticateJWT = function(req, res, next) {
// check header or url parameters or post parameters for token
var token = req.body.token || req.query.token || req.headers['x-access-token'];
//token = undefined????
// decode token
if (token) {
// verifies secret and checks exp
jwt.verify(token, app.get('SECRETCODE'), function(err, decoded) {
if (err) {
return res.json({ success: false, message: 'Failed to authenticate token.' });
} else {
// if everything is good, save to request for use in other routes
req.decoded = decoded;
next();
}
});
} else {
// if there is no token
// return an error
return res.status(403).send({
success: false,
message: 'No token provided.'
});
}
}
So far I have managed to complete steps 1-2, although there may be areas that could be optimized. However, I am currently stuck on step 3...
I am unsure of how to properly send the token from Angular to the backend.