如何在 Node-Express / Vue Web 应用程序中管理 OAuth?

Posted

技术标签:

【中文标题】如何在 Node-Express / Vue Web 应用程序中管理 OAuth?【英文标题】:How to manage OAuth in Node-Express / Vue web app? 【发布时间】:2021-01-10 21:15:59 【问题描述】:

我对如何在我的应用程序中管理 OAuth 流程感到有些困惑。我可以让它工作,但我不确定最佳实践,并希望找到一些关于该主题的好文章/教程/文档。

我的应用结构如下:

一个 Vue 前端,通过 axios 向后端发出 HTTP 请求 使用 Passport.js 的 Node.js / Express 后端允许本地、Google 和 Facebook 策略

护照是这样配置的:

passport.use(
    new GoogleStrategy(
        
            clientID: process.env.GOOGLE_CLIENT_ID,
            clientSecret: process.env.GOOGLE_CLIENT_SECRET,
            callbackURL: '/api/login/google/callback'
        ,
        async (accesToken, refreshToken, profile, done) => 
            try 
                let user = await User.findOne( googleId: profile.id );
                if (user) 
                    if (
                        user.email != profile.emails[0].value ||
                        user.pic != profile.photos[0].value
                    ) 
                        user.email = profile.emails[0].value;
                        user.pic = profile.photos[0].value;
                        user.save();
                    
                    return done(null, user);
                 else 
                    user = await User.findOne(
                        email: profile.emails[0].value
                    );
                    if (user) done(new UserError('existing-user'));
                    const newUser = await new User(
                        googleId: profile.id,
                        email: profile.emails[0].value,
                        name: profile.displayName,
                        pic: profile.photos[0].value
                    ).save();
                    return done(null, newUser);
                
             catch (e) 
                return done(e);
            
        
    )
);

这些是我的登录组件中的身份验证方法:

methods: 
        async login() 
            await authClient.login(this.credentials);
        ,
        async googleLogin() 
            window.open('/api/login/google', 'loginPopup', 'menubar=on');
            // window.location.href = '/api/login/google';
        ,
        async facebookLogin() 
            window.location.href = '/api/login/facebook';
        ,
        async requestResetToken() 
            await userClient.requestResetToken(
                email: this.emailReset
            );
        
    

我的困惑来自这样一个事实,即为了启动 OAuth 流程,我实际上需要通过链接到 /api/login/google 来离开我的 Vue 应用程序,该应用程序重定向到 Google OAuth 页面。 OAuth 完成后,我不会重定向到我的 Vue 应用程序,而是重定向到 Node 后端(通过 Passport 配置中的回调设置)。

使其工作的一种方法是在弹出窗口中打开该 OAuth 流,通过我的 Vue 应用程序跟踪该窗口的内容,一旦我得到用户对象,我就关闭窗口并在前端。但不知何故,这似乎不太正确。

我是否应该找到一种方法将回调函数重定向到我的 Vue 应用程序并让 Vue 应用程序处理它?有什么好的在线资源和例子可以清楚地理解这一点吗?

感谢您的帮助!

【问题讨论】:

我的情况几乎相同(Angular 而不是 Vue,但这在这方面没有任何改变。)好问题 【参考方案1】:

:) 你好,

对于单页 Web 应用程序,您应该使用 Authorization Code Flow 并在尝试 oauth 后使用 Passport,您应该有一个中间件,可以在失败或成功时重定向您:Passport Documentation:

我的一个很好的例子是Traversy Media - backend app with oAuth

我不认为护照是问题,令牌的流动是你的情况......

【讨论】:

我无法重定向到那里,因为该代码位于我的 Node 后端,它只是一个向 Vue 前端发送数据的 API。我认为授权代码流正是 Passport.js 在幕后所做的,对吧? 是的,我也这么认为。还有重定向,是的在后端......据我了解,后端将在从第 3 方 oauth(google 或 facebook)收到令牌后将令牌发送回您的 VUE 前端。您应该将令牌保存在前端本地存储中并将其发送回......这样应该会完成流程...... @StefanDobre “发回”的问题是成功回调 url 启动了一个新的浏览器选项卡。

以上是关于如何在 Node-Express / Vue Web 应用程序中管理 OAuth?的主要内容,如果未能解决你的问题,请参考以下文章

如何读取通过服务器端 (node-express) 上的 Passport 设置的客户端 (react) cookie?

如何正确关闭 node-express 服务器?

node-express 如何在 URL 查询字符串中传递 DATE 参数以及如何解析它

node-express生成骨架

node-express

node-express处理表单的接口