Reputation: 193
I think I am doing this wrong.
How can I authorize a user and send the access token to the frontend (Angular) and also make api requests to fetch the user's avatar..etc
In my application, I use discord oauth2 with passport-discord. I call my backend (nodejs) like like this:
login() {
this.commonService.showLoadingOverlay();
return this.http.get('/auth/login/').subscribe((data: any) => {
const token = data.token;
this.token = token;
if (token) {
this.userInfo = data.user;
this.userId = data.user.user_id;
this.discordId = data.user.discord_id;
this.authStatusListener.next(true);
this.isAuthenticated = true;
const expiresInDuration = data.expiresIn;
const now = new Date();
const expirationDate = new Date(now.getTime() + expiresInDuration * 10000);
this.saveAuthData(token, expirationDate, this.userId, this.userInfo);
this.setAuthTimer(expiresInDuration);
this.commonService.hideLoadingOverlay();
this.router.navigate(['/']);
}
}, error => {
this.commonService.hideLoadingOverlay();
this.router.navigate(['/'])
const message = 'Not logged in...'
this.commonService.showErrorMessage(message);
}
)
}
Backend:
router.get('/login', (req, res) => {
if (req.user) {
const token = jwt.sign({ userId: req.user.user_id, discordId: req.user.discord_id },
process.env.COOKIE_SECRET,
{ expiresIn: '6h' });
res.status(200).json({
token: token,
expiresIn: 3600,
user: req.user
});
} else {
res.send('not logged in!')
}
});
Discord Strategy:
passport.use(new DiscordStrategy({
clientID: process.env.DISCORD_CLIENT,
clientSecret: process.env.DISCORD_SECRET,
callbackURL: process.env.DISCORD_REDIRECT,
scope: scopes
},
function (accessToken, refreshToken, profile, done) {
const currentQuery = 'SELECT user_id, discord_id FROM users WHERE discord_id= $1';
const currentUserValues = [profile.id];
db.query(currentQuery, currentUserValues, (err, res) => {
if (err) {
console.log(err);
} else if (!err && res.rows[0]) {
const currentUser = res.rows[0];
done(null, currentUser); //send to serilize
} else if (!err && !res.rows[0]) {
const newUserQuery = 'INSERT INTO users (discord_id, discord_email) VALUES ($1,$2) ON CONFLICT DO NOTHING RETURNING user_id'
const newUserValues = [profile.id, profile.email]
db.query(newUserQuery, newUserValues, (err, res) => {
if (err) {
console.log(err);
} else {
const newUser = res.rows[0];
done(null, newUser); //send to serilize
}
});
}
})
}));
I am certain that I am doing it wrong and I am unable to find the right way to do it? What's the best practice? how do I get the token and use it with other api calls?
any help is appreciated
Upvotes: 0
Views: 225
Reputation: 301
Why are you sending the expiration time of 3600s separately? That information of token expiry that you are declaring 6h is itself in the token.
Instead of sending the token as a plain JSON, try adding it to the header
res.setHeader('your_token_name', token);
In order to access the headers on Angular side, you have to expose them from the node.js
res.setHeader('Access-Control-Expose-Headers', 'your_token_name');
You can save that token in the session storage on the Angular doing something like this
sessionStorage.setItem('token', responseData.headers.get('your_token_name'));
Then, you can send the token to the node.js on each request by adding an HTTP Interceptor.
Upvotes: 1