Search code examples
c#asp.net-mvcasp.net-identity-2

ASP.NET Identity and validation of a custom claim


I am using ASP.NET Identity with MVC, and I set a sessionId (GuId string) on each logged in user for each one of his devices. The idea is that a user can remove device sessions, and then that device will not be logged in anymore (as it is done in dropbox, and google).

Currently, I set this sessionId as a claim in ASP.NET Identity, so it is passed in the authentication cookie.

For Authenrication I use ASP.NET Identity as the samples: app.UseCookieAuthentication(new CookieAuthenticationOptions{....

My questions:

  1. Is setting my sessionId to the claims the right approach here?

  2. Also, where in the whole authentication process can I validate the claim of that sessionId?

  3. My current idea is to validate this sessionId against a database table for each request. Should I use Request.Sessions to store the sessionId instead, or any other idea here?

Thanks,


Solution

  • Since a user can have multiple valid sessions, you would either need to store these as claims or create your own table to store them. Since claims is already created by Identity, that will be easiest.

    You'd validate this in the OnValidateIdentity method of CookieAuthenticationProvider in Startup.Auth.cs. Currently this calls the OnValidateIdentity method of the SecurityStampValidator so you need to write a wrapper method that first checks your session id and then calls the original security stamp validator. For example you could add these methods to the Startup class:

    private Func<CookieValidateIdentityContext, System.Threading.Tasks.Task> _validate=SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
               validateInterval: TimeSpan.FromMinutes(30),
               regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager));
    private async Task validate(CookieValidateIdentityContext context)
    {
        var usermanager = context.OwinContext.GetUserManager<ApplicationUserManager>();
        var claims = await usermanager.GetClaimsAsync(context.Identity.GetUserId());
    
        //instead of setting to true, add your session validation logic here
        bool sessionIsValid=true;
    
        if (!sessionIsValid) {
            context.RejectIdentity();
            context.OwinContext.Authentication.SignOut(context.Options.AuthenticationType);
        }
    
        await _validate(context);
    }
    

    where _validate is just the original method and validate is your new method that also checks session id. Then your app.UseCookieAuthentication code will reference the new validate method like this:

    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 = validate
    
        }
    });  
    

    To make this work I think you'll need to check the claims from the database every time, but I believe the usermanager.GetClaimsAsync will ultimately do this.