Refresh Token returning invalid or expired even though I am sending an unused new refresh token

Hello I am using React as a frontend and Laravel as a backend.

Get token is working fine it gives me the requested access token, id token, refresh token, and everything else I need.

export const createToken = async (code, successCallBack = null, errorCallBack = null) => {

  const data = {
    code,
    redirect_uri: process.env.REACT_APP_REDIRECT_URI,
    code_verifier: localStorage.getItem("code_verifier")
  }

  await authClient().post(
    '/auth/token/get', data)
    .then (json => {
      const result = json.data;
      if (result) {
        const data = result.data;

        if (typeof(data.error) !== "undefined") {
          if (errorCallBack) {
            errorCallBack();
          }
        }
        else {
          Cache.setItem('accessToken', data.access_token);
          Cache.setItem('idToken', data.id_token);
          Cache.setItem('refreshToken', data.refresh_token);
          Cache.setItem('tokenType', data.token_type);
          Cache.setItem('expiresIn', data.expires_in);
          if (successCallBack) {
            successCallBack();
          }
        }
      }
  }).catch (e => {
    console.error(e);
    return null;
  })
}

and sends it to the backend with

token?grant_type=authorization_code&redirect_uri=%s&code=%s&code_verifier=%s

But whenever I pass a refresh token that was given by the create token token

export const refreshToken = async (successCallBack = null, errorCallBack = null) => {

  const data = {
    redirect_uri: process.env.REACT_APP_REDIRECT_URI,
    scope: "offline_access openid",
    refresh_token: Cache.getItem("refreshToken"),
  }
  
  const config = {headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/x-www-form-urlencoded',  
  }
}
  await authClient().post(
    '/auth/token/refresh', qs.stringify(data), config)
    .then (json => {
      const result = json.data;
      console.log("Refresh result",result);

      if (result) {
        const data = result.data;

        if (typeof(data.error) !== "undefined") {
          if (errorCallBack) {
            errorCallBack();
          }
        }
        else {
          // Cache.setItem('accessToken', data.access_token);
          // Cache.setItem('idToken', data.id_token);
          // Cache.setItem('refreshToken', data.refresh_token);
          // Cache.setItem('tokenType', data.token_type);
          // Cache.setItem('expiresIn', data.expires_in);
          console.log("refresh data",data);
          if (successCallBack) {
            successCallBack();
          }
        }
      }
  }).catch (e => {
    console.error(e);
    return null;
  })
}

and sends it to the backend with

token?grant_type=refresh_token&redirect_uri=%s&scope=%s&refresh_token=%s

I receive this

Blockquote
{
“data”: {
“error”: “invalid_grant”,
“error_description”: “The refresh token is invalid or expired.”
},
“code”: “REFRESH_TOKEN_SUCCESS”
}

1 Like

Are you sending it back to the same authorization server that issued the refresh token?

I am having exactly the same issues. Also, the expiry date attached to the access_token is different from the expiry date when I check the details with the /introspect endpoint.