简体   繁体   English

如何使用Angular Http拦截器和RxJS刷新JWT令牌?

[英]How to refresh JWT Tokens using Angular Http Interceptor and RxJS?

I'm using two JWT tokens - Refresh Token (expires after 7 days) and Access Token (expires after 15 min). 我正在使用两个JWT令牌- Refresh Token (7天后过期)和Access Token (15分钟后过期)。 They are stored on httpOnly cookies and can be accessed via server. 它们存储在httpOnly cookies ,可以通过服务器访问。 Refresh methods signs new token and store it on a cookie. 刷新方法对新令牌进行签名并将其存储在cookie中。 I need to check if these tokens are expired after every request like this: 我需要检查每个请求之后这些令牌是否已过期:

 @Injectable() export class AuthInterceptor implements HttpInterceptor { constructor(private authService: AuthService, private cookieService: CookieService) { } intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { const expirationToken = this.cookieService.get('tokenexp'); // access token expiration const expirationTokenRefresh = this.cookieService.get('tokenrefexp'); // refresh expiration // Refresh Token needs to be checked first if (Number(expirationTokenRefresh) < Date.now()) { // new refresh token is stored on cookie this.authService.refreshTokenRefresh(); // this.authService.refreshToken().subscribe(() => { ... }); } // next we check Access Token if (Number(expirationToken) < Date.now()) { // new access token is stored on cookie this.authService.refreshToken(); // this.authService.refreshTokenRefresh().subscribe(() => { ... }); } return next.handle(req.clone({ withCredentials: true })); } } // auth service refreshToken() { return this.http.get(`${BACKEND_URL}/refreshtoken`); } refreshTokenRefresh() { return this.http.get(`${BACKEND_URL}/refreshtokenref`); } 

Here is Express back-end methods: 这是Express后端方法:

 //routes const express = require('express'); const router = express.Router(); router.get('/refreshtoken', user.refreshToken); router.get('/refreshtokenref', user.refreshTokenRefresh); // refresh access token method const jwt = require('jsonwebtoken'); const moment = require('moment'); const User = require('../models/user'); exports.refreshToken = wrap(async(req, res, next) => { const user = await User.findOne({ refresh_token: req.cookies['tokenref'] }); if (user) { const newToken = await jwt.sign( { email: user.email, userId: user._id, role: user.role }, process.env.JWT_Key, { expiresIn: '15m' }); const expiresAt = moment().add(900, 'second'); res.cookie('tokenexp', JSON.stringify(expiresAt.valueOf()), { maxAge: 3000000000, secure: true}); res.cookie('token', newToken, { maxAge: 3000000000, secure: true, httpOnly: true }); res.status(200).json({success: true}); } else { res.status(401).json({success: false, message: 'Sessão expirou.'}); } }); 

How can I make it work using RxJS Observables ? 如何使用RxJS Observables使其工作? I may send one request to refresh a token, and then another request to refresh second token, and finally the original request with updated cookies. 我可能会发送一个请求以刷新令牌,然后发送另一个请求以刷新第二个令牌,最后发送具有更新cookie的原始请求。 In summary, I may need to send requests before my original request. 总而言之,我可能需要先发送请求,然后再发送原始请求。 Also there is problem: AuthInterceptor shouldn't be called after request one or two (tokens). 还有一个问题:请求一两个(令牌)后不应该调用AuthInterceptor

Using mergeMap to sequentially check the validity of token. 使用mergeMap顺序检查令牌的有效性。

return of(Number(expirationTokenRefresh) < Date.now()).pipe(
  mergeMap(expire => expire
    ? this.authService.refreshTokenRefresh()
    : of(Number(expirationToken) < Date.now())
  ),
  mergeMap(expire => expire
    ? this.authService.refreshToken()
    : of(true)
  ),
  mergeMap(ok => next.handle(req.clone({ withCredentials: true })))
)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM