Microsoft-identity-web: Should clear session auth cookie if cache is missing account

Created on 18 Feb 2020  路  18Comments  路  Source: AzureAD/microsoft-identity-web

from @onovotny and copied from https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2/issues/240

In the Microsoft.Identity.Web library, the system should automatically clear (RejectPrincipal()) the auth cookie if the corresponding account entry is missing from the token cache. This can happen if the cache expired, if it was a memory cache and the server bounced, etc.

The issue is that the system is now in an inconsistent state, where the user is considered logged-in, but any operations to call API's won't succeed because there's no token cache, no refresh token, etc.

I've worked around this here: https://github.com/dotnet-foundation/membership

In order to do so, I had to make some changes to ITokenAquisition and the MsalAbstractCacheProvider's GetCacheKey method.

ITokenAcquisition needed a method to check for a user's token cache:
https://github.com/dotnet-foundation/membership/blob/97b75e30e50aab76bfa5a21f1ab88bf31ae66da4/Microsoft.Identity.Web/TokenAcquisition.cs#L406-L426

In there, it takes the CookieValidatePrincipalContext to get the incoming ClaimsPrincpal as HtttpContext.User is not yet set at that point. It stores it in the HttpContext.Items via the StoreCookieValidatePrincipalContext extension method (used later by the GetCacheKey method so it can derive the appropriate key):
https://github.com/dotnet-foundation/membership/blob/97b75e30e50aab76bfa5a21f1ab88bf31ae66da4/Microsoft.Identity.Web/TokenCacheProviders/MsalAbstractTokenCacheProvider.cs#L68-L69

Finally, the CookieAuthenticationOptions needs to be configured to check for and reject the incoming principal (this could/should be moved into the main IdentityPlatform AddMsal extension methods):
https://github.com/dotnet-foundation/membership/blob/97b75e30e50aab76bfa5a21f1ab88bf31ae66da4/Membership/Startup.cs#L110-L123

I can submit these changes as PR if you're in agreement with these changes.

enhancement web app

All 18 comments

@jennyf19 are you PR'ing this one?

@onovotny do you recommend we put this into our own solution? WIll this go to PR?

@jrmcdona we are still deciding what is the best thing to do. feel free to provide input.

Any update on this on, is it being PR'd?

hitting the same issue, do we have any update?

@jmprieur can you respond? thx.

Any update here as this seems to be a big blocker for my Blazor server side app atm

@jmprieur fyi

Same here, working on a server-side Blazor project with Microsoft Identity Web - is there an update or does anyone have a sample workflow of how to workaround this issue ?

I had the same issue with blazor in the past but not in the last month.
During development I could bypass this error by starting an inprivate browser session and close all inprivate sessions before starting a new one.

At the moment I don't have this issue and I don't know if this helps in it.
This part of my code it stupid copy/paste without knowing why it works

` // Token acquisition service based on MSAL.NET
// and chosen token cache implementation
services.Configure(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => false;
options.MinimumSameSitePolicy = SameSiteMode.Strict;
// Handling SameSite cookie according to https://docs.microsoft.com/en-us/aspnet/core/security/samesite?view=aspnetcore-3.1
options.HandleSameSiteCookieCompatibility();
});

        services.AddOptions();

        services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
            .AddSignIn(x =>
                {
                    Configuration.Bind("AzureAD", x);
                    x.UseTokenLifetime = true;
                    x.GetClaimsFromUserInfoEndpoint = true;
                    x.Events.OnTokenValidated = async ctx =>
                    {

// do something
};
},
y => { Configuration.Bind("AzureAD", y); });

        // Token acquisition service based on MSAL.NET
        // and chosen token cache implementation
        services.AddWebAppCallsProtectedWebApi(Configuration,
                new[] {Constants.ScopeUserRead})
            .AddInMemoryTokenCaches();

`

Clunky workaround for Blazor Server Apps.

https://github.com/wmgdev/BlazorGraphApi

Any guidance update for Blazor server-side?

Feature request: Request new access token instead of throwing exception

See https://github.com/AzureAD/microsoft-identity-web/issues/588 for details of setup.

It would really help if this (default in-memory cache with API requests) worked after application restarts. It is a really bad dev experience having to clear out the cache before you can test when you have a valid session but no token. Would it be possible to add a feature where if the access token is missing and the identity session is present and valid, then the application gets a new access token instead of throwing an exception. This would help loads

Greetings Damien

@damienbod. Unless I mis-understand, I'm confused. We already have this feature: The authorizeForScopes attribute and the MicrosoftIdentityConsentAndConditionalAccessHandler class.

Did you read this: https://github.com/AzureAD/microsoft-identity-web/wiki/Managing-incremental-consent-and-conditional-access ?

What else would you have in mind? would you think that we don't even need to give a chance to the the developer to handle the exception?

@jmprieur Thanks for your answer :) Now Im confused. At the moment when I run the application for the first time everything works fine. I use in-memory cache. When I stop my application and then start it again, it no longer works and returns an exception. I would like that no exception is thrown and that on the second start with in-memory cache it just works. (ie gets a new access token)

Is this possible? I don't see this configuration in the doc, maybe I missed something.

With the default in-memory implementation, I have to delete the cookies after every start to test. This is in my opinion not good.

I also think that as in-memory is the default, I should be able to test (stop-start, stop-start) without error.

Greetings Damien

This is behaviour we see with Blazor server as well if the connection is lost between the browser and server (eg: connectivity or user refreshes page after a while)

@damienbod. Unless I mis-understand, I'm confused. We already have this feature: The authorizeForScopes attribute and the MicrosoftIdentityConsentAndConditionalAccessHandler class.

Did you read this: https://github.com/AzureAD/microsoft-identity-web/wiki/Managing-incremental-consent-and-conditional-access ?

What else would you have in mind? would you think that we don't even need to give a chance to the the developer to handle the exception?

I just ran into this and fixed it with the ConsentHandler, though it would be nice to be able to handle it in a service instead of every time the service is used in a blazor page. Is there a way to do that now?

@jdaless : the service needs to communicate with the user, and that can only be through the app. Which is why the flow is a bit convoluted

Was this page helpful?
0 / 5 - 0 ratings