如何将 oauth2 令牌发送到客户端并存储它们?

get*_*cah 5 javascript rest servlets oauth-2.0

我有一个应用程序,我想使用第三方 API(例如 Google、Facebook 等)登录。客户端前端只是一个将与我的服务器交互的 JavaScript SPA。服务器本质上只需要存储 3rd partyClientIDClientSecret.

要登录,客户端会将用户链接到MyAPI/login。然后,MyAPI 会将用户重定向到第 3 方登录页面以及ClientID. MyAPI/callback身份验证后,第 3 方将使用查询参数将用户重定向回code。MyAPI 会将其与和 一起发送code回第 3 方 API 。3rd 方 API 最终将返回一个and 。ClientIDClientSecretaccess_tokenrefresh_token

我的问题是我应该如何将令牌发送回客户端应用程序?而且,一旦客户端拥有令牌,我应该如何存储它们?

在此输入图像描述

Dan*_*ank 3

您所描述的是OAuth的授权代码授予流程。在身份验证代码流程中,向客户端(在本例中为 MyAPI)提供代码,以便用户永远不会收到或access_tokenrefresh_token因此不必信任他们。

通过向用户提供这些令牌并允许他们将其存储在本地存储中,您就规避了身份验证代码流的安全优势。绝对不建议这样做,除非安全性对您来说不是一个大问题(您信任用户)。

正如评论所建议的,您可以使用 cookie 来保持与 MyAPI 的会话。尽管如此,access_tokenrefresh_token仍应保留在会话数据中,而不是直接与用户共享。这强制要求仅由 MyAPI 代表用户对第 3 方 API 进行访问。

此问题的已接受答案中提供了对身份验证代码流程的更好解释:这两个工作流程有何区别?何时使用授权码流程?

MyAPI 的不完整 Express.js 示例:

// imports
const express = require('express');
const session = require('express-session');
const passport = require('passport');
const jwt = require('jsonwebtoken');

// setup passport (an authentication middleware) and use it with the session provided by express-session
passport.serializeUser((user, done) => {
  done(null, user);
});
passport.deserializeUser((obj, done) => {
  done(null, obj);
});
passport.use(new SomeStrategy(...strategyOptions));
const app = express();
app.use(passport.initialize());
app.use(passport.session());

// route handlers
app.get('/login', passport.authenticate('SOME_STRATEGY'), () => {});
app.get('/callback', passport.authenticate('SOME_STRATEGY'), { failureRedirect: '/badlogin' }, (req, res) => res.send(200));
app.get('/resource', (req, res) => {
  const accessToken = req.user.access_token; // req.user has the session information including the access token
  try {
    // verify the access token with the 3rd party auth's public key (NOT THE SAME AS DECODING IT!) 
    const decodedAccessToken = jwt.verify(accessToken, thirdPartAuthPublicKey);
    return res.send(200).send(decodedAccessToken);
  } catch (err) {
    return res.send(401).send('unauthenticated');
  }
});
Run Code Online (Sandbox Code Playgroud)

这里,服务器保存access_token用户的会话数据( req.user)。当用户请求资源时,服务器尝试验证access_token并返回其解码后的内容。