您所描述的是 OAuth 的授权代码授予流程。在 Auth Code 流程中,向客户端(在本例中为 MyAPI)提供了一个代码,以便用户永远不会收到 access_token 或 refresh_token,因此不必信任它们。
通过向用户提供这些令牌并允许他们将其存储在本地存储中,您正在规避身份验证代码流的安全优势。除非安全对您来说不是那么大的问题(您信任用户),否则绝对不建议这样做。
正如 cmets 所建议的,您可以使用 cookie 来保持与 MyAPI 的会话。尽管如此,access_token 和refresh_token 应该保留在会话数据中,而不是直接与用户共享。这强制要求只能由 MyAPI 代表用户访问第 3 方 API。
在此问题的公认答案中提供了对 Auth Code 流程的更好解释:What is the difference between the 2 workflows? When to use Authorization Code flow?
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');
}
});
这里,服务器将access_token 保存在用户的会话数据中(req.user)。当用户请求资源时,服务器会尝试验证access_token并返回其解码后的内容。