How to get ASP.NET Identity authentication ticket expiry in Razor Page?

天涯浪子 提交于 2020-01-06 07:21:09

问题


I'm using identityserver4 with ASP.NET Identity, with a cookie configured with SlidingExpiration = true and ExpireTimeSpan = 20 minutes. I would like to provide the user with a warning when they are about to timeout so am trying to access the ".expiry" value in the cookie.

So far I have been able to read an expiry time using the Razor code below. However this is failing to read the correct expiry time when the user refreshes their ticket. According to the Microsoft docs SlidingExpiration should provide my user with a new ticket if they refresh the page 10 minutes or more (>= 50% of ExpireTimeSpan) after getting a ticket. It does this fine, but when it does so the code below provides the old expiry time until the user refreshes the page for a second time!

@(DateTime.Parse(((await Context.AuthenticateAsync()).Properties.Items)[".expires"]))

What I want to know is how do I get the correct expiry time on the page generated when the new ticket is provided?


回答1:


The problem here is that the renewal is happening after your page is rendered - the new properties will only be available on subsequent requests.

An option may be to use client side code to poll for the latest expiry time but this would have the effect of being a keep-alive which is possibly not what you'd want.

To mitigate the above you could create your own cookie middleware implementation (all the source code is on github) and customize the sliding expiration logic (CheckForRefresh and RequestRefresh). You may also be able to add the new expiry time to the HttpContext and thus make it available to your controller code earlier.

Source code: https://github.com/aspnet/Security/tree/master/src/Microsoft.AspNetCore.Authentication.Cookies

You only need to create your own version of CookieAuthenticationHandler (less than 500 lines of code) and your own registration helper (check out CookieExtensions):

public static AuthenticationBuilder AddCustomCookie(this AuthenticationBuilder builder, string authenticationScheme, string displayName, Action<CookieAuthenticationOptions> configureOptions)
{
    builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<CookieAuthenticationOptions>, PostConfigureCookieAuthenticationOptions>());
    return builder.AddScheme<CookieAuthenticationOptions, CustomCookieAuthenticationHandler>(authenticationScheme, displayName, configureOptions);
}



回答2:


I've kind of solved my issue, I don't much like this solution as it's quite hacky. It does work though so I'm posting it here in case it is helpful. I'd much appreciate it if anyone can help me understand a better solution, I'll edit this answer or delete it in favour of another if/when that happens.

I get the authentication ticket expiry in much the same way as in my question, then if there is less than 50% of my ExpireTimeSpan setting left I assume it would have renewed (a bit risky maybe but so far it's the best I've managed). I use this to calculate the assumed number of seconds remaining until timeout, then use this value when deciding when to show the user a warning.

At the top of the Razor (partial):

@using Microsoft.AspNetCore.Authentication;

The important bit of my code (feel free to suggest improvements):

secondsRemaining = "@(DateTime.Parse(((await AuthenticationHttpContextExtensions
                                             .AuthenticateAsync(Context))
                                             .Properties
                                             .Items)[".expires"])
                     .Subtract(DateTime.Now)
                     .TotalSeconds)";
// If secondsRemaining is less than half the expiry timespan then assume it will be re-issued
if (secondsRemaining < timeoutSeconds / 2) {
    secondsRemaining = timeoutSeconds;
}


来源:https://stackoverflow.com/questions/57098973/how-to-get-asp-net-identity-authentication-ticket-expiry-in-razor-page

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!