用角度理解 Oauth2 流

Posted

技术标签:

【中文标题】用角度理解 Oauth2 流【英文标题】:Understing Oauth2 flow with angular 【发布时间】:2021-06-29 04:47:57 【问题描述】:

我认为我做错了。

如何授权用户并将访问令牌发送到前端 (Angular) 并发出 api 请求以获取用户的 avatar..etc

在我的应用程序中,我使用 discord oauth2 和 passport-discord。我这样称呼我的后端(nodejs):

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);
    

    )
  

后端:

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!')
    

);

不和谐策略:

    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
                    
                );

            
        )

    ));

我确定我做错了,我找不到正确的方法吗?最佳做法是什么?如何获取令牌并将其与其他 api 调用一起使用?

感谢任何帮助

【问题讨论】:

【参考方案1】:

为什么要单独发送3600s的过期时间?您声明 6h 的令牌到期信息本身就在令牌中。

不要将令牌作为纯 JSON 发送,而是尝试将其添加到标头

res.setHeader('your_token_name', token);

为了访问 Angular 端的标头,您必须从 node.js 中公开它们

res.setHeader('Access-Control-Expose-Headers', 'your_token_name');

您可以将该令牌保存在 Angular 的会话存储中,执行类似的操作

sessionStorage.setItem('token', responseData.headers.get('your_token_name'));

然后,您可以通过添加 HTTP 拦截器在每个请求上将令牌发送到 node.js。

【讨论】:

但是如何访问令牌以便可以在标题中设置它?我是否在不和谐策略中执行此操作?因为这是我唯一可以从 (profile.accessToken) 获取令牌的地方,因为我想将令牌与其他请求一起使用,并且我认为将其存储在数据库中并不安全。我修复了过期时间,谢谢。 您在用户登录时创建令牌并将令牌分配给变量token。这是你的令牌。您可以通过将其命名为您想要的任何名称来在响应标头中进行设置。例如,我将其命名为x-access-token,所以我可能会使用res.setHeader('x-access-token', token) 您不必将令牌存储在数据库中。为了保护 API 并检查每个请求的令牌有效性,只需使用 JWT.verify() 功能。 您不必在每个请求上都发送令牌。它不是那样工作的。用户登录时会生成令牌。您可以通过将其附加到响应标头来将其发送到 Angular。在 Angular 方面,您将该令牌存储在会话存储或本地存储中。 I would prefer session storage 然后,在从 Angular 到节点的每个请求中,您通过手动为每个请求执行该存储令牌附加到 HTTP 请求中,或者使用 HTTP Interceptor 每次 Angular 向您发送请求时都会为您执行此操作节点。然后您可以使用JWT.verify() 来检查令牌的有效性 谢谢,现在更清楚了,尽管我必须阅读更多内容才能完全理解它:)

以上是关于用角度理解 Oauth2 流的主要内容,如果未能解决你的问题,请参考以下文章

了解 OAuth2 客户端凭据流

IT新手之路关于oauth2.0的简单理解

Java 输入/输出——理解Java的IO流

从设计模式角度理解Java IO基本概念

java 流与文件理解

需要帮助使用 React-native、Spring Rest Api 和 ADFS 4.0 实施 OpenID 连接/OAuth2 流