Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Question] Token expiration #1593

Closed
2 of 8 tasks
TanguyPa opened this issue Jan 12, 2022 · 5 comments
Closed
2 of 8 tasks

[Question] Token expiration #1593

TanguyPa opened this issue Jan 12, 2022 · 5 comments

Comments

@TanguyPa
Copy link

TanguyPa commented Jan 12, 2022

Which version of Microsoft Identity Web are you using?
1.18.0

Where is the issue?

  • Web app
    • Sign-in users
    • Sign-in users and call web APIs
  • Web API
    • Protected web APIs (validating tokens)
    • Protected web APIs (validating scopes)
    • Protected web APIs call downstream web APIs
  • Token cache serialization
    • In-memory caches
    • Session caches
    • Distributed caches
  • Other (please describe)

Is this a new or an existing app?
c. This is a new app or an experiment.

Repro

var authCookieExpirationInDays = 14;
var configGraphAPI = configuration.GetSection("GraphAPI");
var initialScopes = configGraphAPI.GetValue<string>("Scopes")?.Split(' ');
var baseUrl = configGraphAPI.GetValue<string>("BaseUrl");
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(options =>
    {
        configuration.Bind("AzureAd", options);
        options.UseTokenLifetime = true;
        options.Events.OnTicketReceived = context =>
                {
                    context.Properties.IsPersistent = true;
                    context.Properties.ExpiresUtc = DateTimeOffset.UtcNow.AddDays(authCookieExpirationInDays);
                    return Task.FromResult(0);
                };                   
    }, cookiesOption =>
    {
        cookiesOption.Cookie.Name = authCookieName;
        cookiesOption.SlidingExpiration = true;                  
    })
    .EnableTokenAcquisitionToCallDownstreamApi(options => configuration.Bind("AzureAd", options), initialScopes)
    .AddMicrosoftGraph(configGraphAPI)
    .AddDistributedTokenCaches();

services.AddDistributedSqlServerCache(options =>
{
    options.ConnectionString = configuration.GetConnectionString("TokenCacheDatabase");
    options.SchemaName = configuration.GetValue<string>("DatabaseSettings:SchemaName");
    options.TableName = configuration.GetValue<string>("DatabaseSettings:TableName");
});

services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
    options.SlidingExpiration = TimeSpan.FromDays(authCookieExpirationInDays);
});

I use these attributes for the controller

[Authorize]
[AuthorizeForScopes(ScopeKeySection = "GraphAPI:Scopes")]

ASP MVC Core 5.0

Expected behavior

I would like the id token to be valid for 14 days (and refreshed after 7 via the SlidingExpiration attribute) so that a user can leave a page open for a long time without risking the loss of his data after submitting a form.

Actual behavior
The user is forced to reconnect after ~20 min without having been active on a page. If the request is an ajax request, a CORS error is returned because an attempt is made to redirect to the identity provider.
If the request is a post via a classic form, the form data is lost.

Additional context / logs / screenshots / link to code
It seems that the expiration of the id token from the distributedcache is ~1h :
"iat": 1641970662,
"nbf": 1641970662,
"exp": 1641974562,
The access token is valid ~1h-1h30 and the refresh token 90 days ?

Can the expiration of the id token be the cause of this redirection to the identity provider? If yes, is it possible to ask the identity provider for an id token with a higher expiration time?

@TanguyPa TanguyPa changed the title [Question] Expiration of token [Question] Token expiration Jan 12, 2022
@TanguyPa
Copy link
Author

TanguyPa commented Jan 17, 2022

The problem is probably related to the line :

options.UseTokenLifetime = true;

I think this is the reason why the cookie lifetime is not used.
But it doesn't work the way I want it to.
The cookie is set with an expiration time of 14 days in the browser, but after more than 20 minutes on the same page, I am redirected to the identity provider after submitting a form.
This seems to me to be the default expiration time defined by a session cookie (yet the cookie is a persistent cookie).

Another question,, what are the differences between these two properties ?
context.Properties.ExpiresUtc in OnTicketReceived and cookiesOption.ExpireTimeSpan in CookieAuthenticationOptions

@jennyf19
Copy link
Collaborator

@TanguyPa is this still repro-ing in the latest version 2.15.5?

context.Properties.ExpiresUtc is a property of the AuthenticationTicket object which is used to store the authentication information for a user. It specifies the date and time when the authentication ticket expires.

cookiesOption.ExpireTimeSpan is a property of the CookieAuthenticationOptions object which is used to configure the cookie middleware for authentication. It specifies the amount of time for which the authentication cookie should be valid.

basically, context.Properties.ExpiresUtc is used to set the expiration time for the authentication ticket, while cookiesOption.ExpireTimeSpan is used to set the expiration time for the authentication cookie.

@TanguyPa
Copy link
Author

TanguyPa commented Jan 9, 2024

Hello,
I haven't had a chance to try again, but I posted the issue initially because I had a global problem using the libin an ASP MVC application.
In some applications, users have to leave a page open where they fill a form and come back later to submit it.
This causes a problem, because between the time the user opens the page and the time the form is submitted, the authentication token has expired.
When this happens, the user is redirected to the auth page after submitting the form, and is then redirected back to the page from which they originally submitted the form.

The problem is that the form data are lost and the POST request sent too.

Have you ever had users encounter similar problems, and do you have any recommendations?

Currently, to avoid these problems, I've set up middleware that saves the request in a cache before the user is redirected to be authenticated and then the request is re-executed once the user re-authenticates.

@TanguyPa
Copy link
Author

I don't really understand the current behavior.
Using Microsoft Graph, I end up with 3 tokens, the id token, the access token and the refresh token.
It seems that the refresh token is never used.
When the id token expires, I'm automatically redirected to the identity provider.
Wouldn't the expected behavior be for the token id to be renewed silently from the refresh token without being redirected?

@TanguyPa
Copy link
Author

I solved the problem by taking a closer look at the various logs.
My problem was linked to the fact that I use IIS to host my application, the application pool is restarted more or less randomly.
This causes the data protection to expire, and when the cookie is reused, the server is no longer able to unprotect the authentication ticket.
Solved by saving the data protection key in SQL.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants