Implicit grant SPA with identity server4 concurrent login

后端 未结 1 1389
无人共我
无人共我 2021-01-17 03:02

how to restrict x amount of login on each client app in specific the SPA client with grant type - implicit

This is out of scope within Identity server

Solut

1条回答
  •  夕颜
    夕颜 (楼主)
    2021-01-17 04:00

    implement profile service overrride activeasync

      public override async Task IsActiveAsync(IsActiveContext context)
        {
            var sub = context.Subject.GetSubjectId();
            var user = await userManager.FindByIdAsync(sub);
    
            //Check existing sessions
            if (context.Caller.Equals("AccessTokenValidation", StringComparison.OrdinalIgnoreCase))
            {
                if (user != null)
                    context.IsActive = !appuser.VerifyRenewToken(sub, context.Client.ClientId);
                else
                    context.IsActive = false;
            }
            else
                context.IsActive = user != null;
        }
    

    startup

    services.AddTransient();
    

    while adding the identity server service to collection under configure services

     .AddProfileService();
    

    Update

    Session.Abandon(); //is only in aspnet prior versions not in core
    Session.Clear();//clears the session doesn't mean that session expired this should be controlled by addSession life time when including service.
    

    I have happened to found a better way i.e. using aspnetuser securitystamp, every time user log-in update the security stamp so that any prior active session/cookies will get invalidated.

    _userManager.UpdateSecurityStampAsync(_userManager.FindByEmailAsync(model.Email).Result).Result
    

    Update (final):

    On sign-in:-

    var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberLogin, false);
                    if (result.Succeeded)
                    {
                //Update security stamp to invalidate existing sessions           
                        var user = _userManager.FindByEmailAsync(model.Email).Result;
                        var test= _userManager.UpdateSecurityStampAsync(user).Result;
                        //Refresh the cookie to update securitystamp on authenticationmanager responsegrant to the current request
                        await _signInManager.RefreshSignInAsync(user);
              }
    

    Profile service implementation :-

    public class ProfileService : ProfileService
    
    {
    public override async Task IsActiveAsync(IsActiveContext context)
            {
                if (context == null) throw new ArgumentNullException(nameof(context));
                if (context.Subject == null) throw new ArgumentNullException(nameof(context.Subject));
    
                context.IsActive = false;
    
                var subject = context.Subject;
                var user = await userManager.FindByIdAsync(context.Subject.GetSubjectId());
    
                if (user != null)
                {
                    var security_stamp_changed = false;
    
                    if (userManager.SupportsUserSecurityStamp)
                    {
                        var security_stamp = (
                            from claim in subject.Claims
                            where claim.Type =="AspNet.Identity.SecurityStamp"
                            select claim.Value
                            ).SingleOrDefault();
    
                        if (security_stamp != null)
                        {
                            var latest_security_stamp = await userManager.GetSecurityStampAsync(user);
                            security_stamp_changed = security_stamp != latest_security_stamp;
                        }
                    }
    
                    context.IsActive =
                        !security_stamp_changed &&
                        !await userManager.IsLockedOutAsync(user);
                }
            }
        }   
    

    *

    Hook in the service collection:-

    *

    services.AddIdentityServer()
        .AddAspNetIdentity()                
             .AddProfileService();
    

    i.e. on every login, the security stamp of the user gets updated and pushed to the cookie, when the token expires, the authorize end point will verify on the security change, If there is any then redirects the user to login. This way we are ensuring there will only be one active session

    0 讨论(0)
提交回复
热议问题