Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing Sliding Expiration in OpenIdConnect with Azure

We have a ASP.Net MVC and have been using OpenIdConnect authentication with Azure AD as the authority. On successful authentication we set the "AuthenticationTicket" Expiry to 8hrs (below i have set to 15 minutes for testing). This 8hrs is fixed, meaning even if user performs activity on the application it won't slide.

But ideally we would want the expiration to slide as a user is active with the system.

Tried setting "SlidingExpiration" to True, even that didn't help. Documentation is not detailed around this topic.

So, How do we implement sliding expiration with OpenIdConnect Authentication?

Below is our code of startup.

namespace TestApp
{
    public partial class Startup
    {
        public void ConfigureAuth(IAppBuilder app)
        {
            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                CookieManager = new SystemWebCookieManager(),
                SlidingExpiration = true,
            });

            app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
                {
                    ClientId = clientId,
                    Authority = Authority,
                    PostLogoutRedirectUri = postLogoutRedirectUri,                    
                    Notifications = new OpenIdConnectAuthenticationNotifications()
                    {
                        //
                        // If there is a code in the OpenID Connect response, redeem it for an access token and refresh token, and store those away.
                        //
                        AuthorizationCodeReceived = (context) =>
                        {

                            context.AuthenticationTicket.Properties.ExpiresUtc = DateTime.UtcNow.AddHours(8);
                            context.AuthenticationTicket.Properties.AllowRefresh = true;
                            context.AuthenticationTicket.Properties.IsPersistent = true;
                            return Task.FromResult(0);
                        },
                        AuthenticationFailed = context =>
                        {
                            context.HandleResponse();
                            context.Response.Redirect("/Home/Error?message=" + context.Exception.Message);
                            return Task.FromResult(0);
                        },  
                    }

                });
        }
    }    
}
like image 915
SridharVenkat Avatar asked Jan 31 '18 19:01

SridharVenkat


1 Answers

Hopefully someone from the ASP.net or Owin team can jump in with a better way to do this, but below is how I got around the exact same problem.

In order for the cookie authentication to take precedence and return a 401 or redirect when the cookie is expired, you need to set the cookie authentication mode to active and the Open Id authentication mode to passive.

app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

        app.UseCookieAuthentication(new CookieAuthenticationOptions()
        {
            AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active,
            SlidingExpiration = true,
            ExpireTimeSpan = TimeSpan.FromMinutes(15),
            CookieSecure = CookieSecureOption.Always,
            LoginPath = Microsoft.Owin.PathString.FromUriComponent("/Logout")
        });
        app.UseOpenIdConnectAuthentication(
            new OpenIdConnectAuthenticationOptions
            {
                ClientId = clientId,
                Authority = authority,
                AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Passive,
                PostLogoutRedirectUri = postLogoutRedirectUri,
            }
            );

After changing from active to passive, I was getting a 401 response when requesting an authorized resource, but refreshing the page would simply log me back in using the token saved from the OpenID call which is not expired when the token expires. To fix this, I set an action in the logout controller (specified with the LoginPath on the cookie options) to sign the user out of both OpenID and Cookie

[Route("Logout")]
    public ActionResult Logout()
    {
        HttpContext.GetOwinContext().Authentication.SignOut(
            OpenIdConnectAuthenticationDefaults.AuthenticationType, CookieAuthenticationDefaults.AuthenticationType);
        return View("~/Views/Index/Logout.cshtml");
    }

Keep in mind, with Open ID set to passive and cookie set to active, all requests will be redirected as unauthorized if they don't contain the cookie (even if they contain a token). Open ID requests will have to specifically call the Open ID handler to be authorized and create the cookie

sources:

https://msdn.microsoft.com/en-us/library/microsoft.owin.security.cookies.cookieauthenticationoptions(v=vs.113).aspx

https://coding.abel.nu/2014/06/understanding-the-owin-external-authentication-pipeline/

like image 120
ToDevAndBeyond Avatar answered Nov 15 '22 20:11

ToDevAndBeyond