Search code examples
azure-active-directorymicrosoft-graph-apirefresh-token

Getting invalid grant when refreshing microsoft access oktne


I have create a web app that the user can connect his account with his outlook account, which will allow him to control his calendar using my web application.

I get the user consent and get access token and refresh token, it all works fine. When I refresh the token lets say after 30 minutes I get the new access token.

But after a while, a day I think I start getting this error invalid_grant when I refresh the token, And I have to login again to outlook to get a valid access token.

Does anyone have any idea why does this happen? This only happens the next day by the way I have offline_access in my scope and API permission

Here is the request I am sending

curl --location --request POST 'https://login.microsoftonline.com/common/oauth2/v2.0/token' \
--header 'Origin: http://localhost:4200' \
--header 'Authorization: Bearer ${Access_Token}' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Cookie: fpc=AhDVWlE6NztJuqGq2Z_Q19xuuUk8AQAAAL3-ytsOAAAA; stsservicecookie=estsfd; x-ms-gateway-slice=estsfd' \
--data-urlencode 'client_id=f4c91f15-2a7c-4b57-836d-5b11dbd37981' \
--data-urlencode 'scope=user.read calendars.readwrite offline_access openid profile' \
--data-urlencode 'refresh_token=${Refresh_Token}' \
--data-urlencode 'grant_type=refresh_token'

And here is the error

enter image description here


Solution

  • I tried to reproduce the same in my environment and got below results:

    I registered one Azure AD application and added same API permissions as below:

    enter image description here

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

    POST https://login.microsoftonline.com/common/oauth2/v2.0/token
    grant_type:authorization_code
    client_id:<appID>
    scope: user.read calendars.readwrite offline_access openid profile
    code:code
    redirect_uri: http://localhost:4200
    code_verifier: S256
    

    Response:

    enter image description here

    I am able to fetch access token using this refresh token successfully until 24 hrs like below:

    POST https://login.microsoftonline.com/common/oauth2/v2.0/token
    client_id:<appID>
    scope:user.read calendars.readwrite offline_access openid profile
    refresh_token:<paste_refresh_token_from_above>
    grant_type:refresh_token
    

    Response:

    enter image description here

    When I tried to refresh the token after 24 hrs, I got same error like below:

    POST https://login.microsoftonline.com/common/oauth2/v2.0/token
    client_id:<appID>
    scope:user.read calendars.readwrite offline_access openid profile
    refresh_token:<paste_refresh_token_from_above>
    grant_type:refresh_token
    

    Response:

    enter image description here

    The error usually occurs if you register your redirect URI as SPA as below:

    enter image description here

    As mentioned in this MS Documentation,

    The default lifetime for the refresh tokens is 24 hours for single page apps. Refresh tokens sent to a redirect URI registered as spa expire after 24 hours.

    So, you need to rerun the authorization code flow using an interactive authentication to get a new refresh token every 24 hours.

    Alternatively, you can register new Azure AD application by setting platform of redirect URI to Web and generate tokens with normal authorization code flow where refresh token stays for 90 days.