azureasp.net-coreauthenticationazure-active-directoryazure-web-app-service

What is the correct way to set a cookie expiration when using Azure AD to login users to an ASP.NET Core 5 Web Application?


We are creating an ASP.NET Core 5.0 MVC project with authentication being handled with Azure AD, so we need to make API calls with AddMicrosoftIdentityWebApp, which then allows us to inject the GraphServiceClient. I am struggling to either debug or set the cookie expiration time. Ultimately, the cookie expiration needs to be two days in the future.

I have the following code that attempts to expire the OIDC cookie via the ExpireTimeSpan option. However, the cookie is not expiring like it should after one minute. Per the reference below, it appears that there may be a minimum of a 1 hour expiration that is set by Azure.

What is the correct way to set a cookie expiration when using Azure AD to login users to a Web Application? Is this a configuration that needs to be set within the Azure web portal or can we do it programmatically?

Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(options =>
    {
        this.Configuration.GetSection("AzureAD").Bind(options);
    }
    , cookieAuthOptions =>
    {
        cookieAuthOptions.Cookie.Name = "MyWebAppName.Auth";
        cookieAuthOptions.ExpireTimeSpan = TimeSpan.FromMinutes(1);
        cookieAuthOptions.SlidingExpiration = true;
    }
    );

    Services.AddRazorPages().AddMicrosoftIdentityUI();
    Services.AddApplicationInsightsTelemetry();
    Services.AddHttpContextAccessor();
    Services.AddGraphServiceClient(this.Configuration);

Reference: https://yousry.medium.com/the-mystery-of-session-timeout-in-asp-net-core-3-1-5-70bb854fe168

Edit: Bounty debug assistance request

Please show how to set a watch for the cookie in Visual Studio so that I can inspect the cookie expiration time. I attempted to use the method that was mentioned in the reference above without success.


Solution

  • I figured it out after stumbling across the following post:

    https://brokul.dev/authentication-cookie-lifetime-and-sliding-expiration

    There was another post on SO that I found that mentioned there are two types of cookies being set: session and authentication. Unfortunately, I closed the page before figuring this all out, so I am unable to properly cite it.

    Anyways, the problem boiled down the fact that I was missing the authentication cookie's MaxAge property.

    I added some rather verbose comments to point of observer, and unwanted, behavior when experimenting with different configs. I decided that this provides the best user experience while also eliminating correlated and nonce cookies (i.e., cookieAuthOptions.SlidingExpiration = false;).

    I hope others find this useful. It took a lot of trial-and-error as reading to figure out what is going on under the hood.

    .AddMicrosoftIdentityWebApp(authOptions =>
    {
        this.Configuration.Bind("AzureAD", authOptions);
        authOptions.MaxAge = TimeSpan.FromDays(2);
    }
    , sessionOptions =>
    {
        // This appears to be obsolete. Don't use it because you get the following error | OptionsValidationException: Cookie.Expiration is ignored, use ExpireTimeSpan instead.
        //sessionOptions.Cookie.Expiration = TimeSpan.FromMinutes(-1);
    
        // Setting the MaxAge will convert Expiration Date on the cookie from 'Session' to an actual future date and will show the default expiration date that is 14 days in the
        // future. However, note that the session cookie is different from the Authentication cookie, who's MaxAge is set in the AddMicrosoftIdentityWebApp extension method above 
        // with an expiration that is equal to the session cookie's expiration. Additionally, we set the SlidingExpiration to false. These three configurations are considered the
        // safest and most secure. Otherwise, not setting the MaxAge while leaving the SlidingExpiration false results in CORS policy errors on the console after the session
        // cookie has expired. 
        // Reference: https://brokul.dev/authentication-cookie-lifetime-and-sliding-expiration
        sessionOptions.Cookie.MaxAge = sessionOptions.ExpireTimeSpan;
        sessionOptions.Cookie.Name = "SomeProjectName.Auth";
        sessionOptions.ExpireTimeSpan = TimeSpan.FromHours(2);
    
        // Keep this false and never change it to true. The problem with SlidingExpiration enabled is that the authentication cookie could be potentially re-issued infinitely.
        // That's not a good security practice. If a hacker took control of the account, they could use it forever.
        sessionOptions.SlidingExpiration = false;
    });