Auto Logout from Asp.net Identity when user is Inactive - asp.net

I am devoloping Asp.net mvc application with Asp.net Identity framework with a requirement of user should be autologout after 10 mins only when the user is inactive(With out mouse movement/Click).I have tried with code which works as user logsout even when the user is active in the application,Can any one help me out in accomplishing these ASAP.Response would be appreciated
Please find my Starup.cs file code here:
using System;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.Google;
using Owin;
using ADFV2External.Models;
using ADFV2External;
namespace ADFV2ExternalLogin
{
public partial class Startup
{
// For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
public void ConfigureAuth(IAppBuilder app)
{
// Configure the db context, user manager and signin manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
// Enable the application to use a cookie to store information for the signed in user
// and to use a cookie to temporarily store information about a user logging in with a third party login provider
// Configure the sign in cookie
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
CookieSecure = CookieSecureOption.Always,
Provider = new CookieAuthenticationProvider
{
// Enables the application to validate the security stamp when the user logs in.
// This is a security feature which is used when you change a password or add an external login to your account.
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
},
ExpireTimeSpan = TimeSpan.FromMinutes(10)
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
// Enables the application to temporarily store user information when they are verifying the second factor in the two-factor authentication process.
app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5));
// Enables the application to remember the second login verification factor such as phone or email.
// Once you check this option, your second step of verification during the login process will be remembered on the device where you logged in from.
// This is similar to the RememberMe option when you log in.
app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);
// Uncomment the following lines to enable logging in with third party login providers
//app.UseMicrosoftAccountAuthentication(
// clientId: "",
// clientSecret: "");
//app.UseTwitterAuthentication(
// consumerKey: "",
// consumerSecret: "");
//app.UseFacebookAuthentication(
// appId: "",
// appSecret: "");
//app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions()
//{
// ClientId = "",
// ClientSecret = ""
//});
app.UseMicrosoftAccountAuthentication
(
clientId: "f10e6987-f527-4eb2-a7d4-61a9d5175117",
clientSecret: "qedLHH977-:ivxfAZNQ90:_"
);
}
}
}

ExpireTimeSpan based on request/response mechanism. That means, that user will log out if there wouldn't be any HTTP request from user in 10 minutes from last response.
So I see 2 ways to solve your task:
You can initiate HTTP requests from page by mouse/keyboard events;
You can run timer (setTimeout function) on client side with its reset on mouse/keyboard events & send log out request when it stops. ExpireTimeSpan must be disabled.
But there may be trouble when user opens some pages.

Related

Azure Active Directory SSO with MSAL and openID Connect

I was tasked with writing an ASP.NET website that uses Azure Active Directory. I went with the route of OAuth and OpenID Connect. I am not able to use implicit flow and therefore must set the ResponseType to be code.
Using MSAL code samples I got most of it working but the problem is that all the samples are using a response type that returns tokens. I think I need to do it in 2 separate steps, first get the authorization code and then get the id token. I'm not exactly sure how to do this and would much appreciate some guidance here.
I have a startup class that look like this:
public void Configuration(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions { });
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
Authority = authority,
ClientId = clientId,
RedirectUri = redirectUri,
Scope = "openid profile email offline_access user.readbasic.all", // a basic set of permissions for user sign in & profile access
ResponseType = OpenIdConnectResponseType.Code,
ClientSecret = clientSecret,
TokenValidationParameters = new TokenValidationParameters
{
// In a real application you would use ValidateIssuer = true for additional checks and security.
ValidateIssuer = false,
NameClaimType = "name",
},
Notifications = new OpenIdConnectAuthenticationNotifications()
{
AuthorizationCodeReceived = OnAuthorizationCodeReceived,
AuthenticationFailed = OnAuthenticationFailed,
}
});
}
private Task OnAuthenticationFailed(AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> context)
{
// Handle any unexpected errors during sign in
context.OwinContext.Response.Redirect("/Error?message=" + context.Exception.Message);
context.HandleResponse(); // Suppress the exception
return Task.FromResult(0);
}
private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification context)
{
/*
The `MSALPerUserMemoryTokenCache` is created and hooked in the `UserTokenCache` used by `IConfidentialClientApplication`.
At this point, if you inspect `ClaimsPrinciple.Current` you will notice that the Identity is still unauthenticated and it has no claims,
but `MSALPerUserMemoryTokenCache` needs the claims to work properly. Because of this sync problem, we are using the constructor that
receives `ClaimsPrincipal` as argument and we are getting the claims from the object `AuthorizationCodeReceivedNotification context`.
This object contains the property `AuthenticationTicket.Identity`, which is a `ClaimsIdentity`, created from the token received from
Azure AD and has a full set of claims.
*/
IConfidentialClientApplication confidentialClient = GroupManager.Utils.MsalAppBuilder.BuildConfidentialClientApplication(null);
// Upon successful sign in, get & cache a token using MSAL
AuthenticationResult result = await confidentialClient.AcquireTokenByAuthorizationCode(new[] { "openid profile email offline_access user.readbasic.all" }, context.Code).ExecuteAsync();
}
How do I take the information from the result's tokens and create a claims identity for the AuthenticationTicket.Identity and access the user info?
Please note that this is an ASP.NET application. Not MVC and not Core.
If you use MSAL, you don't need to handle the code yourself. MSAL will return the token to you after you log in interactively, please see:Overview of Microsoft Authentication Library (MSAL).
Before that, you need to take a look at Add sign-in to Microsoft to an ASP.NET web app,the workflow is:
Code example please check: https://github.com/AzureAdQuickstarts/AppModelv2-WebApp-OpenIDConnect-DotNet
Update:
Try to enable ID token

OnValidateIdentity in OWIN Cookie authentication not called

I am using the OWIN cookie authentication middleware and have setup a custom OnValidateIdentity-method that should be invoked on all requests that needs to be authenticated.
My setup looks like this:
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "my-cookie",
Provider = new CookieAuthenticationProvider()
{
OnValidateIdentity = async ctx =>
{
// my own validation code
}
}
}
The issue I have is that for some requests, OnValidateIdentity is not called. If I hit the same protected Web API controller multiple times, some of the requests would not invoke the OnValidateIdentity-method.
This leads to issues later in the processing when I need to use GetOwinContext().Authentication.User and the ClaimsPrincipal is not populated.
What could be the reason for this?
Found the issue. The cookie was expired.
This is because I also use the OpenIdConnect-middleware using the same cookie. Turns out that if you don't specify UseTokenLifetime = false in that config, it will use the expiry of the ID token as cookie expiry.

GetExternalLoginInfoAsync() loginInfo return null - but only after a few hours

I'm using Strava as my external login provider (I assume this is not related to Strava, could be google or facebook also) After running for a few hours / days or even weeks GetExternalLoginInfoAsync return null. I've read a bunch of other questions with the same problem, but did not find a solution. I post my entire ConfigureAuth method, just in case I did something wrong with the order.
If you have a strava account you could probably experience the problem here: fartslek.no/Account/Login
public void ConfigureAuth(IAppBuilder app)
{
// Configure the db context, user manager and signin manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
// Enable the application to use a cookie to store information for the signed in user
// and to use a cookie to temporarily store information about a user logging in with a third party login provider
// Configure the sign in cookie
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider
{
// Enables the application to validate the security stamp when the user logs in.
// This is a security feature which is used when you change a password or add an external login to your account.
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
},
CookieManager = new SystemWebCookieManager()
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5));
app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);
app.UseStravaAuthentication( new StravaAuthenticationOptions{
ClientId="XXX",
ClientSecret= "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
});
}
I'm using this https://github.com/Johnny2Shoes/Owin.Security.Strava to get StravaAuth.
When it stop working a azure reset is not enough, but if I do a new deploy everything works for a while.
I'm using Owin 3.0.1 and Mvc 5.2.3
I had the same problem. After googling a little, I've discovered this is a known bug in Owin, because of the way they handle cookies.
This issue was submitted to Katana Team, but it looks they won't fix it at all. There are many workarounds for this, but this was the simplest I could find:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult ExternalLogin(string provider, string returnUrl)
{
ControllerContext.HttpContext.Session.RemoveAll();
// Request a redirect to the external login provider
return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }));
}
See this question for more details about this bug, and let me know if this works well for you.

ASP.NET Identity 2 execute code after cookie authentication

I'm using ASP.NET Identity 2 authentication via OWIN middlewear. I've created a new project using the template so initially started with the default generated code but have changed it a bit (taken out entity framework and wired in my own existing authentication). This is all working.
What I'd now like to do is execute code after a user logs in via a saved cookie. I've had a look at ConfigureAuth in the Startup.Auth.cs file which I've configured as follows:
public void ConfigureAuth(IAppBuilder app) {
// Configure the user manager and signin manager to use a single instance
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
// Enable the application to use a cookie to store information for the signed in user
// and to use a cookie to temporarily store information about a user logging in with a third party login provider
// Configure the sign in cookie
app.UseCookieAuthentication(new CookieAuthenticationOptions {
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider {
OnResponseSignIn = ctx => {
Log.Trace("On Response Sign In.");
},
OnResponseSignedIn = ctx => {
Log.Trace("On Response Signed In.");
},
OnValidateIdentity = async ctx => {
Log.Trace("On Validate Identity.");
}
}
});
}
From this I can see that OnResponseSignIn and OnResponseSignedIn are hit only during actual logins when the user enters their username and password. They are not hit when the user is authenticated via saved cookie.
OnValidateIdentity is hit regardless of whether the user authenticated via username/password or saved cookie and it's hit for every request they make.
What I'd like is to execute code just once after a login via cookie. Does anyone know how to do this? If not, I guess another option is to put code in OnValidateIdentity but in an if statement that will prevent it being run unless its the first call after the cookie authentication. Can anyone think of how to achieve that? All I can think of is to set a variable in Session after the code is first run and check for it's presence to prevent it being re-run?
It can probably be done by using a session variable as a flag, and only do your thing when it is not set.
OnValidateIdentity = async context => {
if (HttpContext.Current.Session["Refreshed"] == null)
{
/** do your thing **/
...
HttpContext.Current.Session["Refreshed"] = new object();
}
}

How should I be handling authentication with Identity 2.0 and WebAPI 2.1 and Owin 2?

I'm using
New browser only clients on the same domain
Identity 2.0
WebAPI 2.1
Owin 2.1
AngularJS front-end for registration, login and data display
In a WebAPI application with an AngularJS front-end.
I'm reading about token authentication but I am very confused now and I cannot find any good examples out there that use my combination. What I would like to know is should I be using cookies or tokens for the authentication. Should I be using a Userfactory or the CreatePerOwinContext?
Here's what I have in my Startup.Auth.cs
public partial class Startup {
public void ConfigureAuth(IAppBuilder app) {
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);
app.UseCookieAuthentication(new CookieAuthenticationOptions {
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/"),
Provider = new CookieAuthenticationProvider {
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5));
// Enables the application to remember the second login verification factor such as phone or email.
// Once you check this option, your second step of verification during the login process will be remembered on the device where you logged in from.
// This is similar to the RememberMe option when you log in.
app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);
}
}
Here's my WebAPI config:
public static class WebApiConfig
{
public static void CustomizeConfig(HttpConfiguration config)
{
config.Formatters.Remove(config.Formatters.XmlFormatter);
var json = config.Formatters.JsonFormatter;
json.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
json.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
json.SerializerSettings.Converters.Add(new IsoDateTimeConverter { DateTimeFormat = "yyyy-MM-ddTHH:mmZ" });
}
I saw some examples using this code but I am not sure how I can call this:
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new ApplicationOAuthProvider(PublicClientId, UserManagerFactory),
AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
AllowInsecureHttp = true
};
Could I just replace the cookie authentication with this?
Not an expert, but in my dabbling I've found that tokens work great for api and from javascript to api, and traditional cookies lean mostly for a ui. Either or both will work depending on what your trying to do.
You can follow something like this link that does cookie for the ui and token for the api http://blog.iteedee.com/2014/03/asp-net-identity-2-0-cookie-token-authentication/
app.CreatePerOwinContext(ApplicationSession.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
// Token Authentication
app.UseOAuthBearerAuthentication(new OAuthBearerOptions());
I think you can set the cookie authentication options authentication type to bearer if you want bearer for both, but you would have to play with it. The token would be in the owincontext under ".AspNet.ExternalBearer".
I also think if you register the Identity 2.0 middleware i think it also registers the oauth middleware stuff so you don't need to register the oauthserver middleware yourself. Thats the OAuthAuthorizationServerOptions code you posted. You dont need it.
if the ui and api are in separate then its a bit harder if you want to do some sort of single sign on from the ui pass to the api. I would recommend looking at opensource identity server or authorization server from thinktecture.
If your set on owin middleware and Identity 2.0 you would need to make sure the token can be read by both application and api and you probably would need to implement ISecureDataFormat. But remember, decryption doesn't mean you can 100% trust a token, it should be signed and verified. Depends on your needs.
Sorry, I guess thats a long ramble... Good luck.

Resources