Search code examples
sessionazure-ad-b2caccess-tokenazure-ad-b2c-custom-policyrefresh-token

Prevent refresh token from being used to renew access token after session ends


We've got the following settings configured, based off instructions found at MSFT here and here:

  • Access token lifetime: 60 minutes
  • Refresh token lifetime: 24 hours
  • Refresh token sliding window lifetime: 24 hours
  • Session lifetime: 30 minutes

Within our application, we test the access token lifetime on each page load and, if it is going to expire in the next five minutes and the refresh token hasn't expired, we use the refresh token to ask Azure AD B2C for a new access token.

The problem is that even though the session lifetime is set to 30 minutes, the refresh token still returns a valid access token when it is used. Further, the minimum value for the refresh token is 24 hours.

Is there any way to prevent the refresh token from being used if the session has expired? If we ignore the actual refresh token from Azure AD B2C and change the access token lifespan to 30 minutes, and use that to essentially force the user to be logged out once the 30 minutes expires, would there still be some way for a malicious third-party to use tools like Fiddler to grab the access/refresh tokens Azure AD B2C returns, and use them to keep the user's session active?


Solution

  • Even the session ends, you can still renew access token with the help of refresh token as its lifetime is minimum 24 hrs. To prevent that, you can call invalidateAllRefreshTokens graph query once the session ends.

    I registered one B2C application and added API permissions like below:

    enter image description here

    Now, I generated tokens using authorization code flow via Postman with below parameters:

    POST https://b2ctenant.b2clogin.com/b2ctenant.onmicrosoft.com/B2C_1_SUSI/oauth2/v2.0/token
    grant_type:authorization_code
    client_id:appID
    client_secret:secret
    scope: https://b2ctenant.onmicrosoft.com/xxxx/api.test openid offline_access
    code:code
    redirect_uri: https://jwt.ms
    

    Response:

    enter image description here

    Using the above refresh token, I'm able to generate access token successfully like below:

    POST https://b2ctenant.b2clogin.com/b2ctenant.onmicrosoft.com/B2C_1_SUSI/oauth2/v2.0/token
    grant_type:refresh_token
    client_id: appId
    client_secret: secret
    scope: https://b2ctenant.onmicrosoft.com/xxxx/api.test
    refresh_token:<paste_refresh_token>
    

    Response:

    enter image description here

    To prevent refresh token from being used to renew access token, I ran below query in Graph Explorer for revoking refresh tokens:

    POST https://graph.microsoft.com/beta/users/<user_id>/invalidateAllRefreshTokens
    

    Response:

    enter image description here

    When I tried to renew access token with same refresh token after few minutes, I got error saying token is revoked like below:

    POST https://b2ctenant.b2clogin.com/b2ctenant.onmicrosoft.com/B2C_1_SUSI/oauth2/v2.0/token
    grant_type:refresh_token
    client_id: appId
    client_secret: secret
    scope: https://b2ctenant.onmicrosoft.com/xxxx/api.test
    refresh_token:<paste_refresh_token>
    

    Response:

    enter image description here

    Reference: authentication - Cannot make Azure B2C refersh token become invalid - Stack Overflow by me.