用角度理解 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 流的主要内容,如果未能解决你的问题,请参考以下文章
需要帮助使用 React-native、Spring Rest Api 和 ADFS 4.0 实施 OpenID 连接/OAuth2 流