MG91
MG91

Reputation: 193

Understing Oauth2 flow with angular

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

Answers (1)

Package.JSON
Package.JSON

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

Related Questions