asp.net mvc - Prevent multiple logins -


i trying block multiple logins same user in application.
idea update security stamp when user signin , add claim, in every single request comparing stamp cookie 1 in database. how i've implemented that:

        public virtual async task<actionresult> login([bind(include = "email,password,rememberme")] loginviewmodel model, string returnurl)     {         if (!modelstate.isvalid)         {             return view(model);         }          signinstatus result =             await signinmanager.passwordsigninasync(model.email, model.password, model.rememberme, false);         switch (result)         {             case signinstatus.success:                 var user = usermanager.findbyemail(model.email);                 var id = user.id;                 usermanager.updatesecuritystamp(user.id);                 var securitystamp = usermanager.findbyemail(model.email).securitystamp;                 usermanager.addclaim(id, new claim("securitystamp", securitystamp)); 

then in authentication configuration i've added

        app.usecookieauthentication(new cookieauthenticationoptions         {             authenticationtype = defaultauthenticationtypes.applicationcookie,             loginpath = new pathstring("/account/login"),             provider = new cookieauthenticationprovider             {                 onvalidateidentity = ctx =>                 {                     var ret = task.run(() =>                     {                         claim claim = ctx.identity.findfirst("securitystamp");                         if (claim != null)                         {                             var usermanager = new usermanager<applicationuser>(new userstore<applicationuser>(new applicationdbcontext()));                             var user = usermanager.findbyid(ctx.identity.getuserid());                              // invalidate session, if securitystamp has changed                             if (user != null && user.securitystamp != null && user.securitystamp != claim.value)                             {                                 ctx.rejectidentity();                             }                         }                     });                     return ret;                 }             }          }); 

as shows have tried compare claim cookie 1 in database , reject identity if not same.
now, each time user signs in security stamp gets updated value different in user's cookie can't find out why? suspicious maybe new updated security stamp doesn't stored in user's cookie?

the solution more simple have started implementing. idea same: every time user logs in, change security stamp. , invalidate other login sessions. teach users not share password.

i have created new mvc5 application standard vs2013 template , managed implement want do.

login method. need change security stamp before create auth cookie, after cookie set, can't update values:

[httppost] [allowanonymous] [validateantiforgerytoken] public async task<actionresult> login(loginviewmodel model, string returnurl) {     if (!modelstate.isvalid)     {         return view(model);     }       // check if username/password pair match.     var loggedinuser = await usermanager.findasync(model.email, model.password);     if (loggedinuser != null)     {         // change security stamp on correct username/password         await usermanager.updatesecuritystampasync(loggedinuser.id);     }       // sign-in     var result = await signinmanager.passwordsigninasync(model.email, model.password, model.rememberme, shouldlockout: false);     switch (result)     {         case signinstatus.success:             return redirecttolocal(returnurl);         case signinstatus.lockedout:             return view("lockout");         case signinstatus.requiresverification:             return redirecttoaction("sendcode", new { returnurl = returnurl, rememberme = model.rememberme });         case signinstatus.failure:         default:             modelstate.addmodelerror("", "invalid login attempt.");             return view(model);     } } 

this way every login update on user record new security stamp. updating security stamp matter of await usermanager.updatesecuritystampasync(user.id); - simplier imagined.

next step check security stamp on every request. found best hook-in point in startup.auth.cs again overcomplicated. framework need do, need tweak slightly:

app.usecookieauthentication(new cookieauthenticationoptions {     // other stuff     authenticationtype = defaultauthenticationtypes.applicationcookie,     loginpath = new pathstring("/account/login"),     provider = new cookieauthenticationprovider     {         onvalidateidentity = securitystampvalidator.onvalidateidentity<applicationusermanager, applicationuser>(             validateinterval: timespan.fromminutes(0), // <-- note timer set 0             regenerateidentity: (manager, user) => user.generateuseridentityasync(manager))     } });             

the time interval set 0 - means framework on every request compare user's security stamp database. if stamp in cookie not match stamp in database, user's auth-cookie thrown out, asking them logout.

however, note bear request database on every http request user. on large user-base can expensive , can increase checking interval couple minutes - give less requests db, still carry message not sharing login details.


full source in github


more information in blog-post


Comments

Popular posts from this blog

python - pip install -U PySide error -

arrays - C++ error: a brace-enclosed initializer is not allowed here before ‘{’ token -

cytoscape.js - How to add nodes to Dagre layout with Cytoscape -