Hi,
We will use MSAL on iOS/Xamarin Native (ie not Xamarin Forms).
In our scenario the user signs in via B2C/AAD (Local Account) requesting the access token/refresh token pair to grant access to the API that is authorized via the bearer access token in the api request header.
We will use https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow.
We use local AAD accounts only (ie no Social, no Federation).
A couple of questions.
How to revoke the refresh token on the server (ie B2C AAD)? I am realizing that MSAL provides an operation to remove tokens in the local cache however our security requirement is also to revoke a refresh token on the server (ie B2C AAD).
Even if MSAL would incorporate the token revocation into the library itself (ex. into IPublicClientApplication.RemoveAsync()) I would ask to allow developers to implement a custom revocation. The scenario with the custom revocation my be needed in the situation when there is no the Internet connection when the user signs out, hence a platform custom implementation needed that will take care of triggering token revocation when the Internet becomes available and there is a pending refresh token securely stored on the local device that eventually needs to be invalidated on the server.
Note that a delayed revocation will be platform specific with potential additional requirements in that regard, hence I would not expect MSAL to implement it – we just need an extension point in MSAL to allow developers to take care.
To implement p.2 developers will need to have access to the Refresh token that is currently hidden away (at least on iOS/Android MSAL implementation). I hope that opening Custom Token Cache for mobile developers (https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/issues/1526) will allow to have access to the refresh token at the “custom cache extension point”, however it could be handy if the refresh token made available as a RO property at the AuthenticationResult. I am realizing that AuthenticationResult is generic and there may be flows when there is no refresh token as the result, so for these flows RefreshToken property can just be null.
Thanks and regards
Oleg
Hi Oleg, great questions.
The Refresh Token (RT) is sent in the /token response by AAD every time. By default, an AT lifetime is 1h and an RT lifetime is 3months. By issuing a fresh RT everytime your app contacts AAD, we ensure that the RT remains fresh. It's a rolling window approach to expiration.
When you call pca.RemoveAccountAsync we delete the RT from the cache.
If the tenant admin thinks a user has been compromised, then they are able to invalidate all the refresh tokens that were issued for that user. This needs to be done using the Azure Portal, because it is possible that the RT has been stolen for the user, so deleting it from a device is not sufficient. I am not 100% sure, but I think that if you go to a User and hit "Reset Password" this will invalidate the RT (@jmprieur, @jennyf19 - can you confirm?)
Also programatically, you can use PowerShell to revoke an RT, if you think it has been compromised. See this SO question for details.

@bgavrilMS I'm not sure about doing the password reset workaround, as in b2c, that will be a different authority, so a new token in the cache, which won't be related to the su_si token.
Maybe @valnav or @ktsakas can weigh in here?
The password reset workaround definitely will not help. The requirement is to remove the related single refresh token on B2C AAD when the user signs out. It is horribly unfriendly to the user to reset their password via the back door automatically on each logout (not sure even if it is possible to reset the password without a manual administrator action on the portal).
Another potential workaround listed in this regard in forums was to invalidate ALL refresh tokens for the given user via the Graph API. Although technically it could be implemented as
This workaround is not good either - we wouldn't want to logout users on ALL devices if they signout on one device.
Reading further, I don't believe that currently B2C AAD has OAuth 2 revoke endpoint as per the standard (https://tools.ietf.org/html/rfc7009 )to kill a refresh token.
I voted here https://feedback.azure.com/forums/169401-azure-active-directory/suggestions/30985849-token-revocation-endpoint, however this was open for 2 years with no response from Microsoft.
@olegbaev Sorry for the trouble -- you are correct in that AAD B2C does not support the token revocation endpoint you've specified (and thank you for upvoting the associated topic).
The approach you mentioned in your previous reply (calling the Graph API to revoke all the refresh tokens for a given user) is currently the only built-in mechanism to invalidate refresh tokens. Otherwise, managing the single device's cache would have to be your approach.
If you are using custom policies, we may also be able to help by wiring your refresh token redemption logic to call an external system like a REST API as part of the /token call, but this would additionally require you to build an API to store some state around whether or not the token should be considered revoked.
Just for my understanding -- is the concern here around revoking the individual refresh token in case it was copied/extracted from the cache before it was removed?
hi @jaraya-MSFT , thanks for the response. I feel that the token revocation endpoint is needed for AAD B2C. Many OAuth2 IdPs (including http://docs.identityserver.io/en/latest/endpoints/revocation.html) have a similar capability.
Answering your last question the requirement there is - when the user signs out and the token is deleted from the local cache it is expected that the previous login credentials are not longer valid.
Obviously a short leaving access token can't be invalidate _immediately_ (however it is short living anyway). However it is not ideal to allow the IdP to accept a refresh token for months after the signout.
Of course the refresh token should not be in the wrong hands in the first place.
We build solutions to prevent this anyway, however "defence in depth" assumes "multiple defence lines" hence killing an unnecessary refresh token would assist.
@jmprieur can you provide more details on why this is closed? Are you closing this because it's not a feature B2C wishes to implement, or is this an outstanding issue being tracked elsewhere?
The points @olegbaev makes are valid IMO and requiring applications to implement a separate call to different API to terminate the refresh tokens is not an ideal UX.
@stewartadam : this is not a library related enhancement, but a B2C service enhancement, tracked by the B2C team.
@jaraya-MSFT
Has the issue been resolved? 🤔
If not where We can track it?
Most helpful comment
hi @jaraya-MSFT , thanks for the response. I feel that the token revocation endpoint is needed for AAD B2C. Many OAuth2 IdPs (including http://docs.identityserver.io/en/latest/endpoints/revocation.html) have a similar capability.
Answering your last question the requirement there is - when the user signs out and the token is deleted from the local cache it is expected that the previous login credentials are not longer valid.
Obviously a short leaving access token can't be invalidate _immediately_ (however it is short living anyway). However it is not ideal to allow the IdP to accept a refresh token for months after the signout.
Of course the refresh token should not be in the wrong hands in the first place.
We build solutions to prevent this anyway, however "defence in depth" assumes "multiple defence lines" hence killing an unnecessary refresh token would assist.