This project has moved. For the latest updates, please go here.

Force user to re-enter credentials when authentication times out

Aug 8, 2014 at 3:08 PM
Hello,
I am using WsFederationAuthentication to authenticate against Azure AD instance in my MVC.NET application.

What is the proper way for me (using the owin libraries) to detect that my user auth has expired and redirect the user to the login page? Can I control the length of time the token is valid?

Thanks.
Coordinator
Aug 8, 2014 at 3:49 PM
WsFederation tokens sent to you are valid for a certain amount of time. Katana uses that expiration time for the cookie lifetime by default. See WsFederationAuthenticationOptions.UseTokenLifetime. When the cookie expires it will disappear and the user will show as un-authenticated and will go back through your normal login flow.

If you want to control the lifetime manually you can A) disable UseTokenLifetime and then configure the cookie middleware options directly, or B) hook the SecurityTokenValidated event and set the SecurityTokenValidatedNotification.AuthenticationTicket.Properties.IssuedUtc & ExpiresUtc & AllowRefresh. You can also call IOwinContext.Authentication.SignOut("MyCookieAuthType") at any time to remove the auth cookie.
Aug 8, 2014 at 4:10 PM
I'm already hooked into the SecurityTokenValidated event for claims, so I think it makes sense to control the expiration there as well. I'm going to go with the approach you outlined in option B.

Thanks!
Aug 10, 2014 at 12:55 AM
I updated the ExpiresUtc value and the authentication now correctly expires when I need it to. A new problem is that I'm redirected to the authentication page where the cookie or token gets refreshed automatically and then redirects me to the resource I was trying to reach. Nowhere in this flow do I have a chance to re-enter the credentials of the user. I don't have the "Keep me signed in" option checked either.

IsPersistent = false
AllowRefresh = false
Coordinator
Aug 10, 2014 at 1:10 AM
The user has a separate cookie for the WsFed end-point that you do not control. If you want to force the user to sign-out from the WsFed endpoint you need to ask the WsFed middleware to initiate a sign-out flow. Do this by calling IOwinContext.Authentication.SignOut("WsFederation"); This will trigger a sign-out redirect to the WsFed endpoint.
Aug 10, 2014 at 1:31 AM
Can I tell in one of the WsFederationAuthenticationNotifications events that this is a "re-authentication" or do I need to hook somewhere into the MVC.NET authentication pipeline to determine this and call the SignOut() method?
Coordinator
Aug 10, 2014 at 2:08 AM
You would need to call SignOut before your users's application cookie expired, otherwise you have no way of knowing their state.
Aug 11, 2014 at 11:02 PM
I tried using this method in my controller action HttpContext.GetOwinContext().Authentication.SignOut("WsFederation"); but that doesn't seem to do anything.

HttpContext.GetOwinContext().Authentication.SignOut(); works properly, but it takes me through the entire sign-out process and puts me back on my application home page (which is how my "sign on url" is configured, and that's correct). The home page allows anonymous access, so no authentication/authorization is triggered here.

In my head this would work like this:
  1. Destroy the WsFed cookie - use SignOut("WsFederation")
  2. Redirect to action that requires the user to be authenticated which will trigger the authentication flow and put the user on the screen to enter credentials - use MVC RedirectToAction() method.
Coordinator
Aug 16, 2014 at 3:50 PM
Sounds like sign-out is working as expected. You can specify a RedirectUri in the AuthProperties passed to SignOut. The 3rd party server will redirect back to the given address after signing out, so you can specify a secured resource to trigger re-sign-in. Just make sure this address is registered as a valid wreply.
Aug 19, 2014 at 6:28 PM
I tried that first but for some reason it wasn't working. I'll check my wreply config and try one more time.
Oct 12, 2014 at 6:10 AM
I've decided to intercept the call (i use cookies to detect whether it's the first time the user is signing in, or it's a refresh) to RedirectToIdentityProvider and replace it with a call to SignOut() in order to clear all authentication cookies and force the user to sign in again, but while the call succeeds and the user gets redirected to the home page after sign out (like it should).

The WsFederation cookies are still there and on accessing a protected resource, the user is automatically signed in. Am I in the wrong place in the stack to make a call to SignOut()?
                        RedirectToIdentityProvider = notification =>
                        {
                            Trace.WriteLine(String.Format("[RedirectToIdentityProvider]"));
                            var context = notification.OwinContext.Environment["System.Web.Routing.RequestContext"] as RequestContext;
                            if (context != null)
                            {
                                var authCookie = context.HttpContext.Request.Cookies["authenticated-user"];
                                if (authCookie != null && authCookie.Value == "SecurityTokenValidated")
                                {
                                    authCookie.Expires = DateTime.Now.AddDays(-1);//expire the cookie!
                                    context.HttpContext.Response.AppendCookie(authCookie);//send it back to the client
                                    notification.OwinContext.Authentication.SignOut();
                                    
                                    notification.HandleResponse();
                                }
                            }
                            return Task.FromResult(0);
                        },
Oct 14, 2014 at 7:26 PM
I've stumbled upon the Wfresh parameter which is supposed to do what I need it to do (basically force a re-entry of user's credentials) but that seems to be ignored. :(
Nov 4, 2014 at 9:45 PM
I had to switch to oauth2 as was suggested by Pinpoint, which allowed me the use of prompt=login to force the user to be re-authenticated.