Search code examples
identityserver4asp.net-core-1.1

Is user has active session on IDMsrv?


How to verify IDM does it have an active session for the user signing in?

details - If user'A' has a active session on IDM from browser 'X', When the same user 'A' try to login using browser 'Y', expected behavior identify that user has active session and invalidate the browser'X' session.

Background-

IDM with aspnetIdentity Client with Implicit grant (30 sec identitytoken life, does kept renewing access token silently without going to login page, expected to hit some method on the IDM then I can verify user has access or not)!!


Solution

  • Brock has already mentioned about it, It should be at the time of login and logout

    It make sense,why its not in Idm. but its definitely possible to provide this as an enhanced feature at least in the coming versions.

    Profile Service, IsActive method is the one hit by authorize and tokenvalidation end point.

    so at the time of login persist session, then when the above code hits do the check as per business requirement.

    as long as the session is active ( cookie life time) the silent authentication will be passed with the application logic. so this can be controlled by cookie lifetime as well.

    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;
        }
    

    signin

     public async Task<IActionResult> Login(LoginInputModel model)
        {
            if (ModelState.IsValid)
            {
    
                // To enable password failures to trigger account lockout, set lockoutOnFailure: true
                var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberLogin, false);
                if (result.Succeeded)
                {
    
                    //Update security stamp to invalidate existing sessions 
                    //TODO: This didn't invalidate the existing cookie from another client
                    //var test= _userManager.UpdateSecurityStampAsync(_userManager.FindByEmailAsync(model.Email).Result).Result;
    
    
                    appUser.PersistSession(new UserSession
                    {
                        CreatedOn = DateTimeOffset.Now,
                        DeviceUniqueId = GetDeviceId(),
                        UserId = _userManager.FindByNameAsync(model.Email).Result.Id,
                        SId = httpContext.HttpContext.Session.Id, 
                        ClientId= httpContext.HttpContext.Request.QueryString.Value.GetClientIdFromQuery(),
                        ExpiresOn = DateTimeOffset.Now.AddMinutes(appSettings.SessionTimeOut)
                    });                    
                    _logger.LogInformation(1, "User logged in.");
                    return RedirectToLocal(model.ReturnUrl);
                }
    

    This method has a few drawback when IIS gets restarted and if user has not signed out properly.

    there may be a better options this is not the best fit.!

    Update: refer here duplicate/similar question

    idmsrv endpoints are missing security change check

    Issue raised

    Should be like this @tibold