使用个人API中的刷新令牌续订访问令牌

时间:2016-12-16 20:45:16

标签: javascript angular jwt

我有一个个人REST API,我从一个有角度的2客户端调用。我目前的身份验证过程如下:

  1. 用户使用电子邮件/密码登录
  2. 服务器验证并将user_data,access_token(JWT)和refresh_token(存储在数据库中的不透明令牌)发送回客户端。
  3. 客户端会在每次请求时发送access_token。
  4. 在我的API上,我有和端点getAccessToken(String email, String refresh_token)验证refresh_token并发出新的access_token。

    我的问题是:使用我的angular2应用程序中的refresh_token,我应该使用什么方法来请求新的access_token在它到期之前或之后。

    我目前正在考虑在每次向API发出http请求之前检查access_token到期时间如下:

    if (!tokenNotExpired("accessToken")) {
        this.classService.getAccessToken().subscribe(
            data => {
                // store new access_token in localStorage, then make request to get resource.
                this.classService.createClass().subscribe(
                    data => {
                        //success
                    }, error => {
                        //error
                    })
            }, error => {
                // Invalid refresh token, redirect to login page.
            });
    } else {
        this.classService.createClass().subscribe(
            data => {
                //success
            }, error => {
                //error
            });
    }
    

    有更好的方法吗?我使用angular2-jwt进行令牌验证。

2 个答案:

答案 0 :(得分:1)

这似乎很好。但是,如果您有许多不同的API调用(例如,不仅createClass()而且还有updateClass()destroyClass()),您可能最终必须在您的许多不同位置执行相同的令牌过期检查源代码,这永远不是一件好事。

如何创建一项服务来处理所有来电的令牌过期/续订?

此服务将作为可观察的工厂。您告诉它应该联系哪个端点以及要发送到端点的数据。该服务将根据您的API请求返回一个observable。如果令牌已过期,它会将您的observable包装在令牌刷新调用中。

这只是一个获得一般想法的伪代码:

class ApiService
{
    constructor (private http: Http){}

    createRequest (endpoint, payload):Observable<any>
    {
        let request = 
        this.http.post(endpoint, payload, {headers:auth}).map(/* ... */);

        if (tokenExpired())
        {
          return this.refreshToken().flatMap( 
            (token) => {return request});
        }
        else
          return request;
    }

    refreshToken():Observable<string>
    {
        /* ... */
    }
}

使用此服务,您无需在其他地方检查令牌过期。只需确保使用该服务构建API调用,即在createClass()方法中。

您甚至可以通过参数来增强createRequest方法,该参数可以关闭授权(例如,对于不需要授权的终端)。另一个参数可用于使用不同的HTTP方法(PUT,GET)创建调用。

答案 1 :(得分:0)

我试图模仿旧的滑动过期时间:

在auth.guard.ts中:

import { Injectable }                 from '@angular/core';
import { Router, CanActivate }        from '@angular/router';
import { tokenNotExpired,
         JwtHelper }                  from 'angular2-jwt';

@Injectable()
export class AuthGuard implements CanActivate {
  private jwtHelper = new JwtHelper();

  constructor(private router: Router) {}


  tokenValid() {
    this.handleSlidingExpiration();
    return tokenNotExpired();
  }

  canActivate() {
    if (tokenNotExpired()) {
      this.handleSlidingExpiration();
      return true;
    }

    this.router.navigate(['/login']);
    return false;
  }

  private handleSlidingExpiration() {
    let token = localStorage.getItem('id_token');
    if (!token) { return; }

    let expirationDate = this.jwtHelper.getTokenExpirationDate(token);
    let dToken = this.jwtHelper.decodeToken(token);
    let refreshLimit = new Date((dToken.iat + (dToken.exp - dToken.iat) / 2) * 1000);

    if(new Date() > refreshLimit) {
      // Here you can make a new side request for the new token and update it in local storage
    }
  }
}