question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Can't catch invalid_grant error after refresh token revoke

See original GitHub issue

Core Library

MSAL.js v2 (@azure/msal-browser)

Core Library Version

2.14.1

Wrapper Library

Not Applicable

Wrapper Library Version

none

Description

We have an Azure AD B2C with custom policies configured. By our security policy we are going to revoke all refresh tokens once user changed his password. The expected behavior is like that;

  1. Revoke all refresh tokens for a particular user
  2. Access token is expired for that user
  3. User initiates any request which under the hood is calling acquireTokenSilent
  4. Token endpoint returns invalid_grant error
  5. We catch that error and sign the user out immediately.

Even though Msal.js v2 receives this error under the hood, it doesn’t allow developers to detect it and does a silent renew of the access/refresh token pair.

FYI: I’ve explored the source code a little bit and found that there’s no way to abandon silent request execution in the iframe in case of invalid_grant error. Does it mean that the new feature/flag is required? What do you think? Here is a reference to the code for your information: https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/0e8a18c059bbacbd7f68057d1e760d9e52bdfa02/lib/msal-browser/src/app/ClientApplication.ts#L325

Error Message

Only network error with invalid_grant token endpoint error, which is correct.

Msal Logs

image

MSAL Configuration

Any relevant B2C config from this repository can be used.

Relevant Code Snippets

Any B2C example from this repository can be used

Reproduction Steps

  1. Sign in under any Azure AD B2C user.
  2. Wait for access token expiration (I used minimal access token’s expiration time = 5min).
  3. In Azure Portal click ‘Revoke sessions’ button for the user.
  4. In the web app put a breakpoint on catch clause of for PublicClientApplication.acquireTokenSilent
  5. Initiate a request in the web application which will cause a new token acquisition.

Problems:

  1. Error is not caught (execution flow won’t stop on the breakpoint).
  2. New refresh token/access token received successfully.

Expected Behavior

  1. I wanna be able to catch the invalid_grant (revoked/expired refresh token) exception and sign the user out immediately.

Generally, we are going to revoke all refresh tokens once user’s changed his password. That’s a part of our security policy.

Identity Provider

Azure B2C Custom Policy

Browsers Affected (Select all that apply)

Chrome, Safari

Regression

No response

Source

External (Customer)

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Reactions:1
  • Comments:11 (3 by maintainers)

github_iconTop GitHub Comments

4reactions
lparolaricommented, Feb 7, 2022

I’m facing the same issue. In my case the function acquireTokenSilent returns undefined when the refresh token is expired. Below follows the log (for readability and privacy purposes, I removed some parts of text).

Description

  1. Log in through acquireTokenPopup
  2. Let the refresh token expires (usually after 24 hours)
  3. Call acquireTokenSilent, the promise is fulfilled but the authentication result is undefined

Expected behavior

The promise returned by acquireTokenSilent is rejected.

Actual behavior

It fulfills the promise returned by acquireTokenSilent with undefined.

The request logs instead shows the invalid_grant error with description AADSTS700084: The refresh token was issued to a single page app (SPA), and therefore has a fixed, limited lifetime of 1.00:00:00, which cannot be extended. It is now expired and a new sign in request must be sent by the SPA to the sign in page..

Logs

General

Request URL: https://login.microsoftonline.com/<TENANT-ID>/oauth2/v2.0/token
Request Method: POST
Status Code: 400 Bad Request
Remote Address: <REMOTE-ADDRESS>:443
Referrer Policy: strict-origin-when-cross-origin

Request Headers

Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: it-IT,it;q=0.9,en;q=0.8,de;q=0.7,la;q=0.6,fr;q=0.5,es;q=0.4
Connection: keep-alive
Content-Length: 1808
content-type: application/x-www-form-urlencoded;charset=utf-8
Host: login.microsoftonline.com
Origin: <ORIGIN>
Referer: <REFER>
sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="97", "Chromium";v="97"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "macOS"
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36

Response Header

Access-Control-Allow-Methods: POST, OPTIONS
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: Content-Length,Content-Encoding
Cache-Control: no-store, no-cache
Content-Length: 740
Content-Type: application/json; charset=utf-8
Date: Mon, 07 Feb 2022 08:58:48 GMT
Expires: -1
nel: {"report_to":"network-errors","max_age":86400,"success_fraction":0.001,"failure_fraction":1.0}
P3P: CP="<CP>"
Pragma: no-cache
Referrer-Policy: strict-origin-when-cross-origin
report-to: {"group":"network-errors","max_age":86400,"endpoints":[{"url":"https://identity.nel.measure.office.net/api/report?catId=GW+estsfd+ams1"}]}
Set-Cookie: fpc=<FPC>; expires=Wed, 09-Mar-2022 08:58:48 GMT; path=/; secure; HttpOnly; SameSite=None
Set-Cookie: x-ms-gateway-slice=estsfd; path=/; secure; samesite=none; httponly
Set-Cookie: stsservicecookie=estsfd; path=/; secure; samesite=none; httponly
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
x-ms-clitelem: <TELEM>,
x-ms-ests-server: 2.1.12381.24 - NEULR1 ProdSlices
x-ms-request-id: <REQ-ID>

Request Payload

client_id: <CLIENT-ID>
scope: <SCOPE>
grant_type: refresh_token
client_info: 1
x-client-SKU: msal.js.browser
x-client-VER: 2.21.0
x-client-OS: 
x-client-CPU: 
x-ms-lib-capability: retry-after, h429
x-client-current-telemetry: 5|61,0,,,|,
x-client-last-telemetry: <LAST-TELEMETRY>
client-request-id: <CLIENT-REQUEST-ID>
refresh_token: <REFRESH-TOKEN>
X-AnchorMailbox: <ANCHOR-MAILBOX>

Response

{
  correlation_id: <CORRELATION-ID>
  error: "invalid_grant"
  error_codes: [700084]
  error_description: "AADSTS700084: The refresh token was issued to a single page app (SPA), and therefore has a fixed, limited lifetime of 1.00:00:00, which cannot be extended. It is now expired and a new sign in request must be sent by the SPA to the sign in page. The token was issued on 2022-02-04T14:02:43.2682473Z.\r\nTrace ID: <TRACE-ID>\r\nCorrelation ID: <CORRELATION-ID>\r\nTimestamp: 2022-02-07 08:58:48Z"
  error_uri: "https://login.microsoftonline.com/error?code=700084"
  suberror: "bad_token"
  timestamp: "2022-02-07 08:58:48Z"
  trace_id: <TRACE-ID>
}
1reaction
jasonnuttercommented, Apr 6, 2022

The library receiving a 400 error from the token endpoint when calling acquireTokenSilent is expected and by design. This error should be caught and handled by the library, which will either result in the tokens successfully renewed, or in an interaction required error (if the library is unable to silently renew the refresh token, i.e. the user no longer an active session or third-party cookies are blocked in their browser). Unfortunately, even though we are catching the 400 error, it will still get printed in the console, but that can be ignored (unless if your application is receiving the 400 error in your error handler). Please confirm whether or not your error handler is receiving this error (as opposed to having it just be printed to the console).

I wanna be able to catch the invalid_grant (revoked/expired refresh token) exception and sign the user out immediately.

@Codeluck This would be an enhancement that we do not currently support. You can potentially get the behavior you desire by providing a custom implementation of INetworkModule, where you write logic to detect this scenario and throw a new error that isn’t caught by the library.

Links:

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to interpret and resolve the "Invalid Grant" error for ...
THE "INVALID GRANT" ERROR MAY BE RETURNED FOR THE FOLLOWING REASONS · The user has revoked your access. · The refresh token has...
Read more >
Using Refresh Token Exception { "error" : "invalid_grant" }
In the OAuth2 spec, "invalid_grant" is sort of a catch-all for all errors related to invalid/expired/revoked tokens (auth grant or refresh token).
Read more >
Google OAuth “invalid_grant” nightmare — and how to fix it
The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked, ...
Read more >
Token_failed, Failed to get token: [error: invalid_grant ...
An invalid refresh token can occur if: The token was revoked The grants to the client application were deleted One important detail is...
Read more >
invalid_grant error suddenly happening after 18 months of ...
Hi, The 'invalid_grant' error usually occurs when the authorization code or the refresh token is not valid (is expired, revoked, issued to ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found