过期后使用刷新令牌获取访问令牌(JWT)

Posted

技术标签:

【中文标题】过期后使用刷新令牌获取访问令牌(JWT)【英文标题】:Getting access token with the refresh token after expiration(JWT) 【发布时间】:2021-10-03 09:26:45 【问题描述】:

我在重新加载页面一段时间后收到 401 错误,我认为这可能是因为访问令牌已过期。如何使用刷新令牌设置新令牌?每次用户访问新页面或刷新页面时,都会运行以下函数。但这似乎不起作用。

export async function currentAccount() 


  if (store.get('refreshToken')) 
    const query = 
      grant_type: 'refresh_token',
      companyId: store.get('lastCompanyId'),
      refresh_token: store.get('refreshToken'),
    
    const queryString = new URLSearchParams(query).toString()
    const actionUrl = `$REACT_APP_SERVER_URL/login?$queryString`
    return apiClient
      .post(actionUrl,  auth: 'basic' )
      .then(async response => 
        if (response) 
          const  access_token: accessToken  = response.data
            store.set('accessToken', accessToken)
          return response.data
        
        return false
      )
      .catch(err => 
        console.log('error', err)
        store.clearAll()
      )
  
  return false

登录设置访问令牌

export async function login(email, password) 
  const query = 
    grant_type: 'password',
    username: email,
    password,
  
  const queryString = new URLSearchParams(query).toString()
  const actionUrl = `$REACT_APP_SERVER_URL/login?$queryString`
  return apiClient
    .post(actionUrl,  auth: 'basic' )
    .then(async response => 
      if (response) 
        const 
          data: 
            access_token: accessToken,
            refresh_token: refreshToken,
          ,
         = response
        const decoded = jsonwebtoken.decode(accessToken)
        response.data.authUser = decoded.authUser
        const  userId, profileId, companyId  = decoded.authUser
        if (accessToken) 
          store.set('accessToken', accessToken)
          store.set('refreshToken', refreshToken)
        
        return response.data
      
      return false
    )
    .catch(err => console.log(err))

saga users.js

export function* LOAD_CURRENT_ACCOUNT() 
  yield put(
    type: 'user/SET_STATE',
    payload: 
      loading: true,
    ,
  )
  const  authProvider  = yield select((state) => state.settings)
  const response = yield call(mapAuthProviders[authProvider].currentAccount)
  if (response) 
    const decoded = jsonwebtoken.decode(response.access_token)
    response.authUser = decoded.authUser
    yield store.set('id', id)
    try 
      const user = yield call(LoadUserProfile)
      if (user) 
        const  company  = user
        yield put(
          type: 'user/SET_STATE',
          payload: 
            ...user,
            preferredDateFormat: user.preferredDateFormat || 'DD/MM/YYYY',
            userId,
            id,
          ,
        )
      
     catch (error) 
    
  else
    store.set('refreshToken', response.refreshToken)
  

  yield put(
    type: 'user/SET_STATE',
    payload: 
      loading: false,
    ,
  )

【问题讨论】:

刷新令牌一般是不会过期的令牌,只能用来生成新的访问令牌(过期了)。因此,您希望生成一个刷新令牌,并在请求访问令牌时将其发送回 api 响应中。还将刷新令牌存储在客户端上的访问令牌旁边,当访问令牌返回 401(已过期)时,使用返回新访问令牌的刷新令牌在您的 api 上调用例如/token 端点。 “如何生成和检查刷新令牌”在 api 中,而不是您的示例代码的一部分。 我已经更新了代码,所以登录函数会生成并设置令牌。我可以在 currentAccount 函数本身中生成新的 access_token 吗? 【参考方案1】:

您可以使用拦截器获取带有刷新令牌的新访问令牌。拦截并检查响应状态码 401,并使用您的刷新令牌获取新的访问令牌并将新的访问令牌添加到标头。

例子:

return apiClient
  .post(actionUrl,  auth: 'basic' )
  .then(async response => 
    if (response)  // check for the status code 401 and make call with refresh token to get new access token and set in the auth header
      const  access_token: accessToken  = response.data
        store.set('accessToken', accessToken)
      return response.data
    
    return false
  );

简单的拦截器示例,

axios.interceptors.request.use(req => 
  req.headers.authorization = 'token';
  return req;
);

401 的拦截器示例

axios.interceptors.response.use(response => response, error => 

    if (error.response.status === 401) 
       // Fetch new access token with your refresh token
       // set the auth header with the new access token fetched
    
 );

有几篇关于拦截器使用的好帖子,用于通过刷新令牌获取新的访问令牌

https://thedutchlab.com/blog/using-axios-interceptors-for-refreshing-your-api-token

https://medium.com/swlh/handling-access-and-refresh-tokens-using-axios-interceptors-3970b601a5da

Automating access token refreshing via interceptors in axios

https://***.com/a/52737325/8370370

【讨论】:

以上是关于过期后使用刷新令牌获取访问令牌(JWT)的主要内容,如果未能解决你的问题,请参考以下文章

使用 Angular 和 JWT 令牌持续登录

在永久存储中跟踪 JWT

jwt 访问令牌和刷新令牌流

访问令牌和刷新令牌流程

JWT, 为啥需要刷新令牌?

腾讯先锋怎么解决token过期