Exemplo n.º 1
0
        public async Task <IActionResult> Callback()
        {
            // read external identity from the temporary cookie
            var result = await HttpContext.AuthenticateAsync(IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme);

            if (result?.Succeeded != true)
            {
                throw new Exception("External authentication error");
            }

            // lookup our user and external provider info
            var(user, provider, providerUserId, claims) = FindUserFromExternalProvider(result);
            if (user == null)
            {
                // this might be where you might initiate a custom workflow for user registration
                // in this sample we don't show how that would be done, as our sample implementation
                // simply auto-provisions new external user
                user = AutoProvisionUser(provider, providerUserId, claims);
            }

            // this allows us to collect any additonal claims or properties
            // for the specific prtotocols used and store them in the local auth cookie.
            // this is typically used to store data needed for signout from those protocols.
            var additionalLocalClaims = new List <Claim>();
            var localSignInProps      = new AuthenticationProperties();

            ProcessLoginCallbackForOidc(result, additionalLocalClaims, localSignInProps);
            ProcessLoginCallbackForWsFed(result, additionalLocalClaims, localSignInProps);
            ProcessLoginCallbackForSaml2p(result, additionalLocalClaims, localSignInProps);

            // issue authentication cookie for user
            await _events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.SubjectId, user.Username));


            // issue authentication cookie for user
            var isuser = new IdentityServerUser(user.SubjectId)
            {
                DisplayName      = user.Username,
                IdentityProvider = provider,
                AdditionalClaims = additionalLocalClaims
            };
            await HttpContext.SignInAsync(isuser, localSignInProps);

            // delete temporary cookie used during external authentication
            await HttpContext.SignOutAsync(IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme);

            // retrieve return URL
            var returnUrl = result.Properties.Items["returnUrl"] ?? "~/";

            // check if external login is in the context of an OIDC request
            var context = await _interaction.GetAuthorizationContextAsync(returnUrl);

            if (context != null)
            {
                if (await _clientStore.IsPkceClientAsync(context.Client.ClientId))
                {
                    // if the client is PKCE then we assume it's native, so this change in how to
                    // return the response is for better UX for the end user.
                    return(View("Redirect", new RedirectViewModel {
                        RedirectUrl = returnUrl
                    }));
                }
            }

            return(Redirect(returnUrl));
        }
Exemplo n.º 2
0
        public async Task <IActionResult> Callback()
        {
            // read external identity from the temporary cookie
            var result = await HttpContext.AuthenticateAsync(IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme);

            if (result?.Succeeded != true)
            {
                throw new Exception("External authentication error");
            }
            var tokens      = result.Properties.GetTokens();
            var accessToken = tokens.Where(t => t.Name == "access_token").FirstOrDefault();

            // lookup our user and external provider info
            var(user, provider, providerUserId, claims) = FindUserFromExternalProvider(result);
            if (user == null)
            {
                // this might be where you might initiate a custom workflow for user registration
                // in this sample we don't show how that would be done, as our sample implementation
                // simply auto-provisions new external user
                //user = AutoProvisionUser(provider, providerUserId, claims);
                return(RedirectToAction("Connect"));
            }

            // this allows us to collect any additonal claims or properties
            // for the specific prtotocols used and store them in the local auth cookie.
            // this is typically used to store data needed for signout from those protocols.
            var additionalLocalClaims = new List <Claim>();
            var localSignInProps      = new AuthenticationProperties();

            ProcessLoginCallbackForOidc(result, additionalLocalClaims, localSignInProps);
            ProcessLoginCallbackForWsFed(result, additionalLocalClaims, localSignInProps);
            ProcessLoginCallbackForSaml2p(result, additionalLocalClaims, localSignInProps);

            if (provider == "Microsoft" && accessToken != null)
            {
                HttpClient client = new HttpClient();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                client.DefaultRequestHeaders.Add("Authorization", $"Bearer {accessToken.Value}");
                var info = await client.GetAsync($"https://graph.microsoft.com/v1.0/users/{providerUserId}?$select=businessPhones,displayName,givenName,id,jobTitle,mail,mobilePhone,preferredLanguage,surname,userPrincipalName,department");

                var content = await info.Content.ReadAsAsync <dynamic>();

                if (content != null)
                {
                    try
                    {
                        string jobTitle = content.jobTitle;
                        additionalLocalClaims.Add(new Claim("jobTitle", jobTitle));
                        if (jobTitle == "uèitel")
                        {
                            await _userManager.AddToRoleAsync(user, Constants.TeacherRole);
                        }
                        else
                        {
                            await _userManager.RemoveFromRoleAsync(user, Constants.TeacherRole);
                        }
                        if (jobTitle == "student")
                        {
                            await _userManager.AddToRoleAsync(user, Constants.StudentRole);
                        }
                        else
                        {
                            await _userManager.RemoveFromRoleAsync(user, Constants.StudentRole);
                        }
                        if (jobTitle == "vedení školy")
                        {
                            await _userManager.AddToRoleAsync(user, Constants.ManagerRole);

                            await _userManager.AddToRoleAsync(user, Constants.TeacherRole);
                        }
                        else
                        {
                            await _userManager.RemoveFromRoleAsync(user, Constants.ManagerRole);
                        }
                    }
                    catch { }
                    try
                    {
                        var oldClaims = await _userManager.GetClaimsAsync(user);

                        var oldDepartmentClaim = oldClaims.Where(c => c.Type == "department").SingleOrDefault();
                        ;
                        if (oldDepartmentClaim != null)
                        {
                            await _userManager.RemoveClaimAsync(user, oldDepartmentClaim);
                        }
                        string department = content.department;
                        await _userManager.AddClaimAsync(user, new Claim("department", department));

                        additionalLocalClaims.Add(new Claim("department", department));
                    }
                    catch { }
                }
            }

            foreach (var claim in claims)
            {
                additionalLocalClaims.Add(claim);
            }

            var roles = await _userManager.GetRolesAsync(user);

            foreach (var role in roles)
            {
                additionalLocalClaims.Add(new Claim("role", role));
                var r = await _roleManager.FindByNameAsync(role);

                var claimsInRole = await _roleManager.GetClaimsAsync(r);

                foreach (var cl in claimsInRole)
                {
                    additionalLocalClaims.Add(new Claim(cl.Type, cl.Value));
                }
            }

            IList <Claim> userClaims = await _userManager.GetClaimsAsync(user);

            foreach (var uc in userClaims)
            {
                additionalLocalClaims.Add(new Claim(uc.Type, uc.Value));
            }

            // issue authentication cookie for user
            await _events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.Id, user.UserName));

            var isuser = new IdentityServerUser(user.Id)
            {
                DisplayName      = user.UserName,
                IdentityProvider = provider,
                AdditionalClaims = additionalLocalClaims
            };

            await HttpContext.SignInAsync(isuser, localSignInProps);

            // delete temporary cookie used during external authentication
            await HttpContext.SignOutAsync(IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme);

            // retrieve return URL
            var returnUrl = result.Properties.Items["returnUrl"] ?? "~/";

            // check if external login is in the context of an OIDC request
            var context = await _interaction.GetAuthorizationContextAsync(returnUrl);

            if (context != null)
            {
                if (context.IsNativeClient())
                {
                    // The client is native, so this change in how to
                    // return the response is for better UX for the end user.
                    return(this.LoadingPage("Redirect", returnUrl));
                }
            }

            return(Redirect(returnUrl));
        }
Exemplo n.º 3
0
        public async Task <IActionResult> Login(LoginInputModel model, string button)
        {
            // check if we are in the context of an authorization request
            var context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl);

            // the user clicked the "cancel" button
            if (button != "login")
            {
                if (context != null)
                {
                    // if the user cancels, send a result back into IdentityServer as if they
                    // denied the consent (even if this client does not require consent).
                    // this will send back an access denied OIDC error response to the client.
                    await _interaction.GrantConsentAsync(context, ConsentResponse.Denied);

                    // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null
                    if (await _clientStore.IsPkceClientAsync(context.ClientId))
                    {
                        // if the client is PKCE then we assume it's native, so this change in how to
                        // return the response is for better UX for the end user.
                        return(this.LoadingPage("Redirect", model.ReturnUrl));
                    }

                    return(Redirect(model.ReturnUrl));
                }
                else
                {
                    // since we don't have a valid context, then we just go back to the home page
                    return(Redirect("~/"));
                }
            }

            if (ModelState.IsValid)
            {
                // validate username/password against in-memory store
                if (_users.ValidateCredentials(model.Username, model.Password))
                {
                    var user = _users.FindByUsername(model.Username);
                    await _events.RaiseAsync(new UserLoginSuccessEvent(user.Username, user.SubjectId, user.Username, clientId : context?.ClientId));

                    // only set explicit expiration here if user chooses "remember me".
                    // otherwise we rely upon expiration configured in cookie middleware.
                    AuthenticationProperties props = null;
                    if (AccountOptions.AllowRememberLogin && model.RememberLogin)
                    {
                        props = new AuthenticationProperties
                        {
                            IsPersistent = true,
                            ExpiresUtc   = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration)
                        };
                    }
                    ;

                    // issue authentication cookie with subject ID and username
                    var isuser = new IdentityServerUser(user.SubjectId)
                    {
                        DisplayName = user.Username
                    };

                    await HttpContext.SignInAsync(isuser, props);

                    if (context != null)
                    {
                        if (await _clientStore.IsPkceClientAsync(context.ClientId))
                        {
                            // if the client is PKCE then we assume it's native, so this change in how to
                            // return the response is for better UX for the end user.
                            return(this.LoadingPage("Redirect", model.ReturnUrl));
                        }

                        // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null
                        return(Redirect(model.ReturnUrl));
                    }

                    // request for a local page
                    if (Url.IsLocalUrl(model.ReturnUrl))
                    {
                        return(Redirect(model.ReturnUrl));
                    }
                    else if (string.IsNullOrEmpty(model.ReturnUrl))
                    {
                        return(Redirect("~/"));
                    }
                    else
                    {
                        // user might have clicked on a malicious link - should be logged
                        throw new Exception("invalid return URL");
                    }
                }

                await _events.RaiseAsync(new UserLoginFailureEvent(model.Username, "invalid credentials", clientId : context?.ClientId));

                ModelState.AddModelError(string.Empty, AccountOptions.InvalidCredentialsErrorMessage);
            }

            // something went wrong, show form with error
            var vm = await BuildLoginViewModelAsync(model);

            return(View(vm));
        }
Exemplo n.º 4
0
        public async Task <IActionResult> Login([FromBody] SessionCreateForm form)
        {
            // El form está comlpeto? --------------------
            if (form == null)
            {
                return(new BadRequestResult());
            }

            if (string.IsNullOrEmpty(form.UsernameOrEmail))
            {
                ModelState.AddModelError(nameof(form.UsernameOrEmail), "Required");
            }

            if (string.IsNullOrEmpty(form.Password))
            {
                ModelState.AddModelError(nameof(form.Password), "Required");
            }

            if (!ModelState.IsValid)
            {
                return(ValidationError());
            }

            // La IP tiene permiso de intentar login? --------------------
            var attemptRateResult = await LoginAttemptLimitingService.Check(RequestInfoService.RemoteIp, LoginAttemptStore);

            if (!attemptRateResult.IsApproved)
            {
                ModelState.AddModelError("", attemptRateResult.ErrorMessage);
                return(ValidationError());
            }

            LoginAttempt attempt = new LoginAttempt(this.RequestInfoService.RemoteIp, DateTime.UtcNow);

            // La credencial existe? --------------------
            string failedLoginMsg = "Invalid email and password combination.";

            Credential credential = null;
            bool       isEmail    = form.UsernameOrEmail.IsEmail();

            if (isEmail)
            {
                credential = await CredentialStore.GetByEmail(form.UsernameOrEmail);
            }
            else
            {
                credential = await CredentialStore.Get(form.UsernameOrEmail);
            }


            if (credential == null)
            {
                ModelState.AddModelError("", failedLoginMsg);
                await LoginAttemptStore.Create(attempt);

                return(ValidationError());
            }

            // La contraseña es correcta?
            string newCalculatedHash = HashingUtil.GenerateHash(form.Password, credential.PasswordSalt);

            if (newCalculatedHash != credential.PasswordHash)
            {
                ModelState.AddModelError("", failedLoginMsg);
                await LoginAttemptStore.Create(attempt);

                return(ValidationError());
            }

            // El usuario está penalizado?
            CredentialPenalty activePenalty = await CredentialPenaltyStore.Get(credential.CredentialId, DateTime.UtcNow);

            if (activePenalty != null)
            {
                string validationMsg = null;

                if (activePenalty.EndDate.HasValue)
                {
                    validationMsg = string.Format("User temporarily banned, until [{0}]. Reason: '{1}'", activePenalty.EndDate.Value.ToString(), activePenalty.Reason);
                }
                else
                {
                    validationMsg = string.Format("User permanently banned. Reason: '{0}'", activePenalty.Reason);
                }

                ModelState.AddModelError("", validationMsg);
                await LoginAttemptStore.Create(attempt);

                return(ValidationError());
            }

            var agent = RequestInfoService.UserAgent;

            // La credencial ya tiene una sesión activa?
            Session session =
                await this.SessionStore.Get(
                    credential.CredentialId,
                    agent.DeviceClass,
                    agent.DeviceName,
                    agent.AgentName,
                    agent.AgentVersion);

            if (session != null)
            {
                session.LastActiveDate = DateTime.UtcNow;

                if (session.AllowSelfRenewal)
                {
                    session.ExpirationDate = session.LastActiveDate.AddDays(1);
                }

                await SessionStore.Update(session);
            }
            else
            {
                // Crea la sesión
                session = new Session();
                session.CredentialId     = credential.CredentialId;
                session.LoginDate        = DateTime.UtcNow;
                session.ExpirationDate   = DateTime.UtcNow.AddDays(1);
                session.LastActiveDate   = session.LoginDate;
                session.AllowSelfRenewal = form.IsRememberLogin;
                session.Device           = new UserDevice(agent.DeviceClass, agent.DeviceName);
                session.Agent            = new UserAgent(agent.AgentName, agent.AgentVersion);

                await SessionStore.Create(session);
            }

            // Autentifica
            // check if we are in the context of an authorization request
            var context = await _interaction.GetAuthorizationContextAsync(form.ReturnUrl);

            await _events.RaiseAsync(new UserLoginSuccessEvent(credential.DisplayName, credential.CredentialId, credential.DisplayName, clientId : context?.ClientId));

            // only set explicit expiration here if user chooses "remember me".
            // otherwise we rely upon expiration configured in cookie middleware.
            AuthenticationProperties props = null;

            if (form.IsRememberLogin)
            {
                props = new AuthenticationProperties
                {
                    IsPersistent = true,
                    ExpiresUtc   = DateTimeOffset.UtcNow.Add(TimeSpan.FromHours(8))
                };
            }
            ;

            // issue authentication cookie with subject ID and username
            var isuser = new IdentityServerUser(credential.CredentialId)
            {
                DisplayName = credential.DisplayName
            };

            await HttpContext.SignInAsync(isuser, props);

            // Devuelve el recurso Session
            return(Element <Session>(session));
        }
Exemplo n.º 5
0
        public async Task <IActionResult> Callback()
        {
            // read external identity from the temporary cookie
            var result = await HttpContext.AuthenticateAsync(IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme);

            if (result?.Succeeded != true)
            {
                throw new Exception("External authentication error");
            }

            var externalUser = result.Principal;

            string FullName  = externalUser.FindFirst(ClaimTypes.Name)?.Value ?? " ";
            string GivenName = externalUser.FindFirst(ClaimTypes.GivenName)?.Value ?? " ";
            string Surname   = externalUser.FindFirst(ClaimTypes.Surname)?.Value ?? " ";
            string Email     = externalUser.FindFirst(ClaimTypes.Email)?.Value;

            // lookup our user and external provider info
            var(user, provider, providerUserId, claims) = FindUserFromExternalProvider(result);
            if (user == null)
            {
                var newUser = new User
                {
                    Name           = GivenName,
                    Username       = Email,
                    Password       = "",
                    Profile        = "Everyone",
                    Email          = Email,
                    Provider       = provider,
                    UserProviderId = providerUserId
                };

                _userRepository.Add(newUser);

                user = newUser;
            }
            else
            {
                user.UserProviderId = providerUserId;
                user.Provider       = provider;

                _userRepository.Update(user);
                _userRepository.Save();
            }

            // this allows us to collect any additonal claims or properties
            // for the specific prtotocols used and store them in the local auth cookie.
            // this is typically used to store data needed for signout from those protocols.
            var additionalLocalClaims = new List <Claim>();
            var localSignInProps      = new AuthenticationProperties();

            ProcessLoginCallbackForOidc(result, additionalLocalClaims, localSignInProps);
            ProcessLoginCallbackForWsFed(result, additionalLocalClaims, localSignInProps);
            ProcessLoginCallbackForSaml2p(result, additionalLocalClaims, localSignInProps);

            // issue authentication cookie for user
            await _events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.UsersId.ToString(), user.Username));


            var isuser = new IdentityServerUser(user.UsersId.ToString())
            {
                DisplayName      = user.Username,
                IdentityProvider = provider,
                AdditionalClaims = additionalLocalClaims
            };
            await HttpContext.SignInAsync(isuser, localSignInProps);

            // delete temporary cookie used during external authentication
            await HttpContext.SignOutAsync(IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme);

            // retrieve return URL
            var returnUrl = result.Properties.Items["returnUrl"] ?? "~/";

            // check if external login is in the context of an OIDC request
            var context = await _interaction.GetAuthorizationContextAsync(returnUrl);

            if (context != null)
            {
                if (await _clientStore.IsPkceClientAsync(context.Client.ClientId))
                {
                    // if the client is PKCE then we assume it's native, so this change in how to
                    // return the response is for better UX for the end user.
                    return(View("Redirect", new RedirectViewModel {
                        RedirectUrl = returnUrl
                    }));
                }
            }

            return(Redirect(returnUrl));
        }
Exemplo n.º 6
0
        public async Task <IActionResult> Login(LoginInputModel model, string button)
        {
            var context = await _interactionService.GetAuthorizationContextAsync(model.ReturnUrl);

            if (button != "login")
            {
                if (context == null)
                {
                    return(Redirect("~/"));
                }

                await _interactionService.DenyAuthorizationAsync(context, AuthorizationError.AccessDenied);

                return(context.IsNativeClient() ? this.LoadingPage("Redirect", model.ReturnUrl) : Redirect(model.ReturnUrl));
            }

            if (ModelState.IsValid)
            {
                var result = await _signInManager.PasswordSignInAsync(model.Username, model.Password, model.RememberLogin, true);

                if (result.Succeeded)
                {
                    var user = await _userManager.FindByNameAsync(model.Username);

                    await _eventService.RaiseAsync(new UserLoginSuccessEvent(user.UserName, user.Id, user.UserName, clientId : context?.Client.ClientId));

                    AuthenticationProperties properties = null;

                    if (AccountOptions.AllowRememberLogin && model.RememberLogin)
                    {
                        properties = new AuthenticationProperties
                        {
                            ExpiresUtc   = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration),
                            IsPersistent = true
                        };
                    }

                    var issuer = new IdentityServerUser(user.Id)
                    {
                        DisplayName = user.UserName
                    };

                    await HttpContext.SignInAsync(issuer, properties);

                    if (context != null)
                    {
                        return(context.IsNativeClient() ? this.LoadingPage("Redirect", model.ReturnUrl) : Redirect(model.ReturnUrl));
                    }

                    if (Url.IsLocalUrl(model.ReturnUrl))
                    {
                        return(Redirect(model.ReturnUrl));
                    }

                    if (string.IsNullOrEmpty(model.ReturnUrl))
                    {
                        return(Redirect("~/"));
                    }

                    throw new Exception("InvalidReturnUrl");
                }

                await _eventService.RaiseAsync(new UserLoginFailureEvent(model.Username, "InvalidCredentials", clientId : context?.Client.ClientId));

                ModelState.AddModelError(string.Empty, AccountOptions.InvalidCredentialsErrorMessage);
            }

            var vm = await BuildLoginViewModelAsync(model);

            return(View(vm));
        }
        public async Task <IActionResult> ExternalLoginCallback()
        {
            // read external identity from the temporary cookie
            var result = await HttpContext.AuthenticateAsync(IdentityConstants.ExternalScheme);

            if (result?.Succeeded != true)
            {
                throw new Exception("External authentication error");
            }

            // lookup our user and external provider info
            var(user, provider, providerUserId, claims) = await FindUserFromExternalProviderAsync(result);

            if (user == null)
            {
                // this might be where you might initiate a custom workflow for user registration
                // in this sample we don't show how that would be done, as our sample implementation
                // simply auto-provisions new external user
                user = await AutoProvisionUserAsync(provider, providerUserId, claims);
            }

            // this allows us to collect any additonal claims or properties
            // for the specific prtotocols used and store them in the local auth cookie.
            // this is typically used to store data needed for signout from those protocols.
            var additionalLocalClaims = new List <Claim>();
            var localSignInProps      = new AuthenticationProperties();

            ProcessLoginCallbackForOidc(result, additionalLocalClaims, localSignInProps);
            ProcessLoginCallbackForWsFed(result, additionalLocalClaims, localSignInProps);
            ProcessLoginCallbackForSaml2p(result, additionalLocalClaims, localSignInProps);

            // issue authentication cookie for user
            // we must issue the cookie maually, and can't use the SignInManager because
            // it doesn't expose an API to issue additional claims from the login workflow
            var principal = await _signInManager.CreateUserPrincipalAsync(user);

            additionalLocalClaims.AddRange(principal.Claims);
            var name = principal.FindFirst(JwtClaimTypes.Name)?.Value ?? user.Id.ToString();
            await _events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.Id.ToString(), name));

            //await HttpContext.SignInAsync(user.Id.ToString(), name, provider, localSignInProps, additionalLocalClaims.ToArray());

            var isuser = new IdentityServerUser(user.Id.ToString())
            {
                DisplayName      = name,
                IdentityProvider = provider,
                AdditionalClaims = additionalLocalClaims
            };

            await HttpContext.SignInAsync(isuser, localSignInProps);


            // delete temporary cookie used during external authentication
            await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);

            // validate return URL and redirect back to authorization endpoint or a local page
            var returnUrl = result.Properties.Items["returnUrl"];

            if (_interaction.IsValidReturnUrl(returnUrl) || Url.IsLocalUrl(returnUrl))
            {
                return(Redirect(returnUrl));
            }

            return(Redirect("~/"));
        }
Exemplo n.º 8
0
        public async Task <IActionResult> Callback()
        {
            // read external identity from the temporary cookie
            var result = await HttpContext.AuthenticateAsync(IdentityConstants.ExternalScheme);

            if (result?.Succeeded != true)
            {
                throw new Exception("External authentication error");
            }

            if (_logger.IsEnabled(LogLevel.Debug))
            {
                var externalClaims = result.Principal.Claims.Select(c => $"{c.Type}: {c.Value}");
                _logger.LogDebug("External claims: {@claims}", externalClaims);
            }

            // lookup our user and external provider info
            var(user, provider, providerUserId, claims) = await FindUserFromExternalProvider(result);

            if (user == null)
            {
                // this might be where you might initiate a custom workflow for user registration
                // in this sample we don't show how that would be done, as our sample implementation
                // simply auto-provisions new external user
                user = await AutoProvisionUser(provider, providerUserId, claims);
            }

            // this allows us to collect any additional claims or properties
            // for the specific protocols used and store them in the local auth cookie.
            // this is typically used to store data needed for signout from those protocols.
            var additionalLocalClaims = new List <Claim>();
            var localSignInProps      = new AuthenticationProperties();

            ProcessLoginCallback(result, additionalLocalClaims, localSignInProps);

            var principal = await _signInManager.CreateUserPrincipalAsync(user);

            additionalLocalClaims.AddRange(principal.Claims);

            var name = principal.FindFirst(JwtClaimTypes.Name)?.Value ?? user.Id;
            await _events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.Id, name));

            var isuser = new IdentityServerUser(user.Id)
            {
                DisplayName = user.UserName
            };

            await HttpContext.SignInAsync(isuser, localSignInProps);

            // delete temporary cookie used during external authentication
            await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);

            // validate return URL and redirect back to authorization endpoint or a local page
            var returnUrl = result.Properties.Items["returnUrl"];

            if (_interaction.IsValidReturnUrl(returnUrl) || Url.IsLocalUrl(returnUrl))
            {
                return(Redirect(returnUrl));
            }

            return(Redirect("~/"));
        }
Exemplo n.º 9
0
        public async Task <IActionResult> Callback()
        {
            // read external identity from the temporary cookie
            var result = await HttpContext.AuthenticateAsync(IdentityConstants.ExternalScheme);

            if (result?.Succeeded != true)
            {
                throw new Exception("External authentication error");
            }

            if (_logger.IsEnabled(LogLevel.Debug))
            {
                var externalClaims = result.Principal.Claims.Select(c => $"{c.Type}: {c.Value}");
                _logger.LogDebug("External claims: {@claims}", externalClaims);
            }

            var info = await _signInManager.GetExternalLoginInfoAsync();


            // lookup our user and external provider info
            var(user, authProvider, providerUserId, claims) = await FindUserFromExternalProviderAsync(result);

            if (user == null)
            {
                // TODO: Enable support for custom workflows
                user = await AutoProvisionUserAsync(authProvider, providerUserId, result);
            }
            else
            {
                await authProvider.UpdateUserAsync(user, result);
            }

            var additionalLocalClaims = new List <Claim>();
            var localSignInProps      = new AuthenticationProperties();

            ProcessLoginCallbackForOidc(result, additionalLocalClaims, localSignInProps);
            //ProcessLoginCallbackForWsFed(result, additionalLocalClaims, localSignInProps);
            //ProcessLoginCallbackForSaml2p(result, additionalLocalClaims, localSignInProps);

            // issue authentication cookie for user
            // we must issue the cookie maually, and can't use the SignInManager because
            // it doesn't expose an API to issue additional claims from the login workflow
            var principal = await _signInManager.CreateUserPrincipalAsync(user);

            additionalLocalClaims.AddRange(principal.Claims);

            var isuser = new IdentityServerUser(user.Id.ToString())
            {
                IdentityProvider = authProvider.Scheme,
                AdditionalClaims = additionalLocalClaims
            };

            await HttpContext.SignInAsync(isuser, localSignInProps);

            // delete temporary cookie used during external authentication
            await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);

            // retrieve return URL
            var returnUrl = result.Properties.Items["returnUrl"] ?? "~/";

            // check if external login is in the context of an OIDC request
            var context = await _interaction.GetAuthorizationContextAsync(returnUrl);

            await _userManager.UpdateAsync(user);

            await _events.RaiseAsync(new UserLoginSuccessEvent(authProvider.Scheme, providerUserId, user.Id.ToString(), user.Email, true, context?.ClientId));


            if (context != null)
            {
                var client = await _clientStore.FindClientByIdAsync(context.ClientId);

                if (client.RequirePkce)
                {
                    // if the client is PKCE then we assume it's native, so this change in how to
                    // return the response is for better UX for the end user.
                    return(View("Redirect", new RedirectViewModel()
                    {
                        RedirectUrl = returnUrl
                    }));
                }
            }

            return(Redirect(returnUrl));
        }
Exemplo n.º 10
0
        public async Task <IResponseOutput> Login(LoginInput input)
        {
            if (!ModelState.IsValid)
            {
                return(ResponseOutput.NotOk(ModelState.Values.First().Errors[0].ErrorMessage));
            }

            var sw = new Stopwatch();

            sw.Start();

            var context = await _interaction.GetAuthorizationContextAsync(input.ReturnUrl);

            var user = await _userRepository.Select.Where(a => a.UserName == input.UserName)
                       .ToOneAsync(a => new { a.Id, a.Password, a.NickName });

            if (user == null)
            {
                return(ResponseOutput.NotOk("", 1));
            }

            var password = MD5Encrypt.Encrypt32(input.Password);

            if (user.Password != password)
            {
                return(ResponseOutput.NotOk("", 2));
            }


            AuthenticationProperties props = null;

            if (input.RememberLogin)
            {
                props = new AuthenticationProperties
                {
                    IsPersistent = true,
                    ExpiresUtc   = DateTimeOffset.UtcNow.Add(TimeSpan.FromDays(1))
                };
            }
            ;

            var identityServerUser = new IdentityServerUser(user.Id.ToString())
            {
                DisplayName = input.UserName
            };

            await HttpContext.SignInAsync(identityServerUser, props);

            sw.Stop();

            //写登录日志
            var loginLogEntity = new LoginLogEntity()
            {
                CreatedUserId       = user.Id,
                NickName            = user.NickName,
                CreatedUserName     = input.UserName,
                ElapsedMilliseconds = sw.ElapsedMilliseconds,
                Status = true
            };

            await AddLoginLog(loginLogEntity);

            return(ResponseOutput.Ok());
        }
Exemplo n.º 11
0
        public async Task <IActionResult> Login(LoginInputModel model)
        {
            // check if we are in the context of an authorization request
            var context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl);

            if (ModelState.IsValid)
            {
                AuthenticationProperties props        = null;
                IdentityServerUser       isuser       = null;
                UserLoginSuccessEvent    successEvent = null;
                bool   isValid = false;
                string errMsg  = null;

                // 测试用户
                var testUser = OAuthConfig.GetTestUsers().Find(t => t.Username == model.Username && t.Password == model.Password);
                if (testUser != null)
                {
                    successEvent = new UserLoginSuccessEvent(testUser.Username, testUser.SubjectId, testUser.Username, clientId: context?.Client.ClientId);
                    // issue authentication cookie with subject ID and username
                    isuser = new IdentityServerUser(testUser.SubjectId)
                    {
                        DisplayName      = testUser.Username,
                        AdditionalClaims =
                        {
                            new Claim(UserClaimEnum.UserId.ToString(),   testUser.SubjectId),
                            new Claim(UserClaimEnum.UserName.ToString(), testUser.Username)
                        }
                    };
                    isValid = true;
                }
                else
                {
                    //E登账号
                    var edUser = _edApiService.GetEdUser(model.Username, model.Password, out string msg);
                    errMsg = msg;
                    if (edUser != null)
                    {
                        successEvent = new UserLoginSuccessEvent(edUser.LoginName, edUser.ID.ToString(), edUser.EmployeeName, clientId: context?.Client.ClientId);
                        // issue authentication cookie with subject ID and username
                        isuser = new IdentityServerUser(edUser.ID.ToString())
                        {
                            DisplayName      = edUser.EmployeeName,
                            AdditionalClaims =
                            {
                                new Claim(UserClaimEnum.UserId.ToString(),   edUser.ID.ToString()),
                                new Claim(UserClaimEnum.UserName.ToString(), edUser.EmployeeName.ToString())
                            }
                        };
                        isValid = true;
                    }
                }

                if (isValid)
                {
                    //身份认证通过
                    await _events.RaiseAsync(successEvent);

                    // only set explicit expiration here if user chooses "remember me".
                    // otherwise we rely upon expiration configured in cookie middleware.
                    if (AccountOptions.AllowRememberLogin && model.RememberLogin)
                    {
                        props = new AuthenticationProperties
                        {
                            IsPersistent = true,
                            ExpiresUtc   = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration)
                        };
                    }
                    ;
                    await HttpContext.SignInAsync(isuser, props);

                    if (context != null)
                    {
                        if (context.IsNativeClient())
                        {
                            // The client is native, so this change in how to
                            // return the response is for better UX for the end user.
                            return(this.LoadingPage("Redirect", model.ReturnUrl));
                        }
                        // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null
                        return(Redirect(model.ReturnUrl));
                    }
                    // request for a local page
                    if (Url.IsLocalUrl(model.ReturnUrl))
                    {
                        return(Redirect(model.ReturnUrl));
                    }
                    else if (string.IsNullOrEmpty(model.ReturnUrl))
                    {
                        return(Redirect("~/"));
                    }
                    else
                    {
                        // user might have clicked on a malicious link - should be logged
                        throw new Exception("无效的返回URL");
                    }
                }

                await _events.RaiseAsync(new UserLoginFailureEvent(model.Username, "无效的证书", clientId : context?.Client.ClientId));

                ModelState.AddModelError(string.Empty, errMsg ?? AccountOptions.InvalidCredentialsErrorMessage);
            }

            // something went wrong, show form with error
            var vm = await BuildLoginViewModelAsync(model);

            return(View(vm));
        }
Exemplo n.º 12
0
        public async Task <IActionResult> Callback()
        {
            // read external identity from the temporary cookie
            var result = await HttpContext.AuthenticateAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme);

            if (result?.Succeeded != true)
            {
                _logger.Exception(result.Failure);
                string errMsg = "External authentication error - " + result.Failure.Message;
                errMsg += (result.Failure.InnerException != null) ? (" - " + result.Failure.InnerException.Message) : string.Empty;

                throw new HttpRequestException(
                          CDCavell.ClassLibrary.Web.Html.StatusCodes.ToString(401),
                          new Exception(errMsg),
                          HttpStatusCode.Unauthorized
                          );
            }

            if (_logger.IsEnabled(LogLevel.Debug))
            {
                var externalClaims = result.Principal.Claims.Select(c => $"{c.Type}: {c.Value}");
                _logger.Debug($"External claims: {externalClaims}");
            }

            // lookup our user and external provider info
            var(user, provider, providerUserId, claims) = await FindUserFromExternalProviderAsync(result);

            if (user == null)
            {
                // this might be where you might initiate a custom workflow for user registration
                // in this sample we don't show how that would be done, as our sample implementation
                // simply auto-provisions new external user
                user = await AutoProvisionUserAsync(provider, providerUserId, claims);
            }

            // validate email address
            if (!user.EmailConfirmed)
            {
                // delete temporary cookie used during external authentication
                await HttpContext.SignOutAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme);

                TempData["Email"] = user.Email;
                return(RedirectToAction("Index", "Registration"));
            }

            if (user.TwoFactorEnabled)
            {
                TwoFactorValidateModel model = new TwoFactorValidateModel();
                model.Email          = user.Email;
                model.Provider       = provider;
                model.ProviderUserId = providerUserId;
                model.ReturnUrl      = result.Properties.Items["returnUrl"];

                // if the external system sent a session id claim, copy it over
                // so we can use it for single sign-out
                var sid = result.Principal.Claims.FirstOrDefault(x => x.Type == JwtClaimTypes.SessionId);
                if (sid != null)
                {
                    model.SessionId = sid.Value;
                }

                // if the external provider issued an id_token, we'll keep it for signout
                var idToken = result.Properties.GetTokenValue("id_token");
                if (idToken != null)
                {
                    model.AuthenticationToken = idToken;
                }

                TempData["TwoFactorValidateModel"] = JsonConvert.SerializeObject(model);
                return(RedirectToAction("Validate", "TwoFactor"));
            }

            // this allows us to collect any additional claims or properties
            // for the specific protocols used and store them in the local auth cookie.
            // this is typically used to store data needed for signout from those protocols.
            var additionalLocalClaims = new List <Claim>();
            var localSignInProps      = new AuthenticationProperties();

            ProcessLoginCallback(result, additionalLocalClaims, localSignInProps);

            // issue authentication cookie for user
            // we must issue the cookie maually, and can't use the SignInManager because
            // it doesn't expose an API to issue additional claims from the login workflow
            var principal = await _signInManager.CreateUserPrincipalAsync(user);

            additionalLocalClaims.AddRange(principal.Claims);
            var name = user.FullName; //principal.FindFirst(JwtClaimTypes.Name)?.Value ?? user.Id;

            var isuser = new IdentityServerUser(user.Id)
            {
                DisplayName      = name,
                IdentityProvider = provider,
                AdditionalClaims = additionalLocalClaims
            };

            await HttpContext.SignInAsync(isuser, localSignInProps);

            // delete temporary cookie used during external authentication
            await HttpContext.SignOutAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme);

            // retrieve return URL
            var returnUrl = result.Properties.Items["returnUrl"] ?? "~/";

            // check if external login is in the context of an OIDC request
            var context = await _interaction.GetAuthorizationContextAsync(returnUrl);

            await _events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.Id, name, true, context?.Client.ClientId));

            if (context != null)
            {
                if (context.IsNativeClient())
                {
                    // The client is native, so this change in how to
                    // return the response is for better UX for the end user.
                    return(this.LoadingPage("Redirect", returnUrl));
                }
            }

            return(Redirect(returnUrl));
        }
Exemplo n.º 13
0
        public async Task <IActionResult> Callback(string code, string state, string session_state)
        {
            // Get the return url for the frontend from the cookies.
            string returnUrl = HttpContext.Request.Cookies["returnUrl"];

            HttpContext.Response.Cookies.Delete("returnUrl");

            //Request an accesstoken and idtoken from the authority.
            RestClient  client  = new RestClient(config.FfhictOIDC.Authority + "/connect/token");
            RestRequest request = new RestRequest(Method.POST);

            request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
            request.AddParameter("grant_type", "authorization_code");
            request.AddParameter("code", code);
            request.AddParameter("redirect_uri", config.FfhictOIDC.RedirectUri);
            request.AddParameter("client_id", config.FfhictOIDC.ClientId);
            request.AddParameter("client_secret", config.FfhictOIDC.ClientSecret);
            IRestResponse response = client.Execute(request);

            if (response.StatusCode != HttpStatusCode.OK)
            {
                return(BadRequest("Could not validate the identity server authentication."));
            }

            // Parse the content to get the access token.
            ExternalConnectToken fhictToken = JsonConvert.DeserializeObject <ExternalConnectToken>(response.Content);

            if (string.IsNullOrWhiteSpace(fhictToken.AccessToken))
            {
                throw new Exception("The FHICT didn't return a correct response. Is the FHICT server accessible?",
                                    new Exception(
                                        "Content:\n" + response.Content + "\n\nError:\n" + response.ErrorMessage,
                                        response.ErrorException));
            }

            JwtSecurityToken jwt = new JwtSecurityToken(fhictToken.AccessToken);
            string           idp = (string)jwt.Payload.FirstOrDefault(c => c.Key.Equals("idp"))
                                   .Value;
            string iss = (string)jwt.Payload.FirstOrDefault(c => c.Key.Equals("iss"))
                         .Value;

            ExternalResult result = new ExternalResult
            {
                Schema    = iss,
                Claims    = jwt.Claims,
                ReturnUrl = returnUrl,
                IdToken   = fhictToken.IdToken
            };

            // lookup our user and external provider info
            (IdentityUser user, string provider, string providerUserId, IEnumerable <Claim> claims) =
                await FindUserFromExternalProvider(result);

            if (user == null)
            {
                //Retrieve more user information from the external source.
                // Get User information
                RestClient  informationClient  = new RestClient($"{iss}/connect/userinfo");
                RestRequest informationRequest = new RestRequest(Method.GET);
                informationRequest.AddHeader("Authorization", $"Bearer {fhictToken.AccessToken}");
                IRestResponse    informationResponse = informationClient.Execute(informationRequest);
                ExternalUserInfo userinfo            =
                    JsonConvert.DeserializeObject <ExternalUserInfo>(informationResponse.Content);

                List <Claim> claimsList = claims.ToList();
                claimsList.Add(new Claim("email", userinfo.PreferredUsername));
                claimsList.Add(new Claim("idp", idp));
                claimsList.Add(new Claim("name", userinfo.Name));
                IdentityUser toInsertuser = new IdentityUser
                {
                    ProviderId        = provider,
                    ExternalSubjectId = providerUserId,
                    Email             = userinfo.Email,
                    Firstname         = userinfo.GivenName,
                    Lastname          = userinfo.FamilyName,
                    Name               = userinfo.Name,
                    Username           = userinfo.PreferredUsername,
                    ExternalProfileUrl = userinfo.Profile
                };

                // simply auto-provisions new external user
                user = await identityUserService.AutoProvisionUser(toInsertuser);
            }

            // this allows us to collect any additional claims or properties
            // for the specific protocols used and store them in the local auth cookie.
            // this is typically used to store data needed for signout from those protocols.
            List <Claim>             additionalLocalClaims = new List <Claim>();
            AuthenticationProperties localSignInProps      = new AuthenticationProperties();

            ProcessLoginCallbackForOidc(result, additionalLocalClaims, localSignInProps);

            // issue authentication cookie for user
            IdentityServerUser isuser = new IdentityServerUser(user.SubjectId)
            {
                DisplayName      = user.Name,
                IdentityProvider = provider,
                AdditionalClaims = additionalLocalClaims
            };

            await HttpContext.SignInAsync(isuser, localSignInProps)
            .ConfigureAwait(false);

            // delete temporary cookie used during external authentication
            await HttpContext.SignOutAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme)
            .ConfigureAwait(false);

            // check if external login is in the context of an OIDC request
            AuthorizationRequest context = await interaction.GetAuthorizationContextAsync(returnUrl)
                                           .ConfigureAwait(false);

            await events.RaiseAsync(new UserLoginSuccessEvent(provider,
                                                              providerUserId,
                                                              user.SubjectId,
                                                              user.Username,
                                                              true,
                                                              context?.ClientId))
            .ConfigureAwait(false);

            if (context != null)
            {
                if (await clientStore.IsPkceClientAsync(context.ClientId)
                    .ConfigureAwait(false))
                {
                    // if the client is PKCE then we assume it's native, so this change in how to
                    // return the response is for better UX for the end user.
                    return(this.LoadingPage("Redirect", returnUrl));
                }
            }

            return(Redirect(returnUrl));
        }
Exemplo n.º 14
0
        public async Task <IActionResult> OnGetCallbackAsync(string returnUrl = null, string remoteError = null)
        {
            returnUrl ??= this.Url.Content("~/");

            if (remoteError != null)
            {
                this._logger.LogError($"External login error: {remoteError}");

                return(this.LoginError(returnUrl, string.Format(LoginErrorConstants.ExternalRemoteError, remoteError)));
            }

            // read external identity from the temporary cookie
            var result = await this.HttpContext.AuthenticateAsync(IdentityConstants.ExternalScheme);

            if (result?.Succeeded != true)
            {
                this._logger.LogError($"External login error");

                return(this.LoginError(returnUrl));
            }

            if (this._logger.IsEnabled(LogLevel.Debug))
            {
                this._logger.LogDebug("External claims: {@claims}", result.Principal.Claims.Select(c => $"{c.Type}: {c.Value}"));
            }

            var info = await this._signInManager.GetExternalLoginInfoAsync();

            if (info == null)
            {
                this._logger.LogError($"Configured external login information before the authentication is missing");

                return(this.LoginError(returnUrl));
            }

            var userId = info.Principal.Identity.Name;

            var user = await this._userManager.FindByLoginAsync(info.LoginProvider, info.ProviderKey);

            if (user == null)
            {
                if (string.IsNullOrWhiteSpace(userId))
                {
                    this._logger.LogError($"External login with provider {info.LoginProvider} is success but the user principal name is missing");

                    return(this.LoginError(returnUrl));
                }

                // Check for email claim in external authentication principal
                if (info.Principal.HasClaim(c => c.Type == ClaimTypes.Email))
                {
                    user = await this._userManager.FindByEmailAsync(info.Principal.FindFirstValue(ClaimTypes.Email));
                }

                if (user == null || !user.IsActive)
                {
                    return(this.UserNotRegistered(returnUrl, userId));
                }

                // Map user to user logins
                var identityResult = await this._userManager.AddLoginAsync(user, new UserLoginInfo(info.LoginProvider, info.ProviderKey, info.ProviderDisplayName));

                if (!identityResult.Succeeded)
                {
                    this._logger.LogError($"External login with provider {info.LoginProvider} is success but mapping the user to userlogins is failed");

                    return(this.LoginError(returnUrl));
                }
            }

            if (!user.IsActive)
            {
                return(this.UserNotRegistered(returnUrl, userId));
            }

            // this allows us to collect any additonal claims or properties
            // for the specific prtotocols used and store them in the local auth cookie.
            // this is typically used to store data needed for signout from those protocols.
            var additionalLocalClaims = new List <Claim>();
            var localSignInProps      = new AuthenticationProperties();

            this.ProcessLoginCallbackForOidc(result, additionalLocalClaims, localSignInProps);

            // issue authentication cookie for user
            // we must issue the cookie maually, and can't use the SignInManager because
            // it doesn't expose an API to issue additional claims from the login workflow
            var principal = await this._signInManager.CreateUserPrincipalAsync(user);

            additionalLocalClaims.AddRange(principal.Claims);

            var name = principal.FindFirst(JwtClaimTypes.Name)?.Value ?? user.Id;

            var isuser = new IdentityServerUser(user.Id)
            {
                DisplayName      = name,
                IdentityProvider = info.LoginProvider,
                AdditionalClaims = additionalLocalClaims
            };

            await this.HttpContext.SignInAsync(isuser, localSignInProps);

            await this._eventService.RaiseAsync(new UserLoginSuccessEvent(info.LoginProvider, info.ProviderKey, user.Id, name));

            // delete temporary cookie used during external authentication
            await this.HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);

            // check if external login is in the context of an OIDC request
            var context = await this._interaction.GetAuthorizationContextAsync(returnUrl);

            await this._eventService.RaiseAsync(new UserLoginSuccessEvent(info.LoginProvider, info.ProviderKey, user.Id, user.Email, true, context?.Client.ClientId));

            if (context != null)
            {
                if (context.IsNativeClient())
                {
                    // if the client is PKCE then we assume it's native, so this change in how to
                    // return the response is for better UX for the end user.
                    return(this.RedirectToPage("/Redirect", new { RedirectUrl = returnUrl }));
                }
            }

            return(this.Redirect(returnUrl));
        }
Exemplo n.º 15
0
 /// <summary>
 /// Signs the user in.
 /// </summary>
 /// <param name="context">The manager.</param>
 /// <param name="user">The IdentityServer user.</param>
 /// <param name="properties">The authentication properties.</param>
 /// <returns></returns>
 public static async Task SignInAsync(this HttpContext context, IdentityServerUser user, AuthenticationProperties properties)
 {
     await context.SignInAsync(await context.GetCookieAuthenticationSchemeAsync(), user.CreatePrincipal(), properties);
 }
Exemplo n.º 16
0
        public async Task <IActionResult> Login(LoginInputModel model, string button)
        {
            var context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl);

            _logger.LogInformation("displaying login options");

            // the user clicked the "cancel" button
            if (button != "login")
            {
                if (context != null)
                {
                    // if the user cancels, send a result back into IdentityServer as if they
                    // denied the consent (even if this client does not require consent).
                    // this will send back an access denied OIDC error response to the client.
                    await _interaction.DenyAuthorizationAsync(context, AuthorizationError.AccessDenied);

                    // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null
                    if (await _clientStore.IsPkceClientAsync(context.Client.ClientId))
                    {
                        // if the client is PKCE then we assume it's native, so this change in how to
                        // return the response is for better UX for the end user.
                        return(View("Redirect", new RedirectViewModel {
                            RedirectUrl = model.ReturnUrl
                        }));
                    }

                    return(Redirect(model.ReturnUrl));
                }
                else
                {
                    // since we don't have a valid context, then we just go back to the home page
                    return(Redirect("~/"));
                }
            }

            if (ModelState.IsValid)
            {
                ResourceOwnerPasswordValidationContext ValidationContext = new ResourceOwnerPasswordValidationContext
                {
                    UserName = model.Username,
                    Password = model.Password,
                };
                _logger.LogInformation("Setting up validation context for user");

                var passwordValidator = _resourceOwnerPasswordValidation as ResourceOwnerPasswordValidator;

                ValidationContext = await passwordValidator.ValidatePassword(ValidationContext);

                _logger.LogInformation("Validation process started");

                // validate username/password against in-memory store
                if (ValidationContext.Result != null)
                {
                    if (ValidationContext.Result.Subject != null)
                    {
                        if (ValidationContext.Result.Subject.Identity.IsAuthenticated)
                        {
                            _logger.LogInformation("Validation process succesfully retrieved authenticated user");
                            var user = _userRepository.FindUserByUsernameOrEmail(model.Username);

                            await _events.RaiseAsync(new UserLoginSuccessEvent(model.Username,
                                                                               ValidationContext.Result.Subject.ToString(), model.Username));

                            // only set explicit expiration here if user chooses "remember me".
                            // otherwise we rely upon expiration configured in cookie middleware.
                            AuthenticationProperties props = null;
                            if (AccountOptions.AllowRememberLogin && model.RememberLogin)
                            {
                                props = new AuthenticationProperties
                                {
                                    IsPersistent = true,
                                    ExpiresUtc   = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration)
                                };
                            }

                            ;

                            var claims = ProfileService.GetUserClaims(user);
                            // issue authentication cookie with subject ID and username
                            _logger.LogInformation("Issuing authentication cookie");
                            var isuser = new IdentityServerUser(user.UsersId.ToString())
                            {
                                DisplayName = user.Username
                            };

                            await HttpContext.SignInAsync(isuser, props);

                            if (context != null)
                            {
                                if (await _clientStore.IsPkceClientAsync(context.Client.ClientId))
                                {
                                    // if the client is PKCE then we assume it's native, so this change in how to
                                    // return the response is for better UX for the end user.
                                    return(View("Redirect", new RedirectViewModel {
                                        RedirectUrl = model.ReturnUrl
                                    }));
                                }

                                // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null
                                return(Redirect(model.ReturnUrl));
                            }

                            // request for a local page
                            if (Url.IsLocalUrl(model.ReturnUrl))
                            {
                                return(Redirect(model.ReturnUrl));
                            }
                            else if (string.IsNullOrEmpty(model.ReturnUrl))
                            {
                                return(Redirect("~/"));
                            }
                            else
                            {
                                // user might have clicked on a malicious link - should be logged
                                throw new Exception("invalid return URL");
                            }
                        }
                    }
                }

                await _events.RaiseAsync(new UserLoginFailureEvent(model.Username, "invalid credentials"));

                ModelState.AddModelError(string.Empty, ValidationContext.Result.ErrorDescription);
            }

            // something went wrong, show form with error
            var vm = await BuildLoginViewModelAsync(model);

            return(View(vm));
        }
Exemplo n.º 17
0
        public async Task <IActionResult> Callback()
        {
            // read external identity from the temporary cookie
            AuthenticateResult?result = await HttpContext.AuthenticateAsync(IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme);

            if (result?.Succeeded != true)
            {
                throw new Exception(Properties.Resources.ExternalAuthenticationError);
            }

            if (_logger.IsEnabled(LogLevel.Debug))
            {
                IEnumerable <string>?externalClaims = result.Principal.Claims.Select(c => $"{c.Type}: {c.Value}");
                // External claims: {%1}.
                _logger.LogDebug(string.Format(
                                     CultureInfo.CurrentCulture,
                                     Properties.Resources.ExternalClaimsLog,
                                     string.Join(", ", externalClaims)));
            }

            // lookup our user and external provider info
            (TestUser user, string provider, string providerUserId, IEnumerable <Claim> claims) = FindUserFromExternalProvider(result);
            if (user == null)
            {
                // this might be where you might initiate a custom workflow for user registration in
                // this sample we don't show how that would be done, as our sample implementation
                // simply auto-provisions new external user
                user = AutoProvisionUser(provider, providerUserId, claims);
            }

            // this allows us to collect any additional claims or properties for the specific
            // protocols used and store them in the local auth cookie. this is typically used to
            // store data needed for signout from those protocols.
            var additionalLocalClaims = new List <Claim>();
            var localSignInProps      = new AuthenticationProperties();

            ProcessLoginCallbackForOidc(result, additionalLocalClaims, localSignInProps);
            //ProcessLoginCallbackForWsFed(result, additionalLocalClaims, localSignInProps);
            //ProcessLoginCallbackForSaml2p(result, additionalLocalClaims, localSignInProps);

            // issue authentication cookie for user
            var isuser = new IdentityServerUser(user.SubjectId)
            {
                DisplayName      = user.Username,
                IdentityProvider = provider,
                AdditionalClaims = additionalLocalClaims
            };

            await HttpContext.SignInAsync(isuser, localSignInProps);

            // delete temporary cookie used during external authentication
            await HttpContext.SignOutAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme);

            // retrieve return URL
            string?returnTo = result.Properties.Items["returnUrl"] ?? "~/";

            // check if external login is in the context of an OIDC request
            AuthorizationRequest?context = await _interaction.GetAuthorizationContextAsync(returnTo);

            await _events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.SubjectId, user.Username, true, context?.Client?.ClientId));

            if (context?.Client != null)
            {
                if (await _clientStore.IsPkceClientAsync(context.Client.ClientId))
                {
                    // if the client is PKCE then we assume it's native, so this change in how to
                    // return the response is for better UX for the end user.
                    return(this.LoadingPage("Redirect", returnTo));
                }
            }

            return(Redirect(returnTo));
        }
Exemplo n.º 18
0
        public async Task <string> GetAccessTokenAsync(UserModel user, List <Claim> additionalClientClaims = null, string userUuidOverride = null)
        {
            try
            {
                var tokenCreationRequest = new TokenCreationRequest();

                var identityPricipal = await _principalFactory.CreateAsync(user).ConfigureAwait(false);

                var identityUser = new IdentityServerUser(!string.IsNullOrEmpty(userUuidOverride) ? userUuidOverride : user.Id.ToString());

                identityUser.AdditionalClaims = identityPricipal.Claims.ToArray();

                identityUser.DisplayName = user.UserName;

                identityUser.AuthenticationTime = DateTime.UtcNow;
                identityUser.IdentityProvider   = IdentityServerConstants.LocalIdentityProvider;

                var subject = identityUser.CreatePrincipal();

                tokenCreationRequest.Subject = subject;

                tokenCreationRequest.IncludeAllIdentityClaims = true;

                tokenCreationRequest.ValidatedRequest = new ValidatedRequest();

                tokenCreationRequest.ValidatedRequest.Subject = tokenCreationRequest.Subject;

                string defaultClientId = _configurationProvider.DefaultClientId;

                var client = await _clientStore.FindClientByIdAsync(defaultClientId).ConfigureAwait(false);

                tokenCreationRequest.ValidatedRequest.SetClient(client);

                var resources = await _resourceStore.GetAllEnabledResourcesAsync().ConfigureAwait(false);

                tokenCreationRequest.Resources = resources;

                tokenCreationRequest.ValidatedRequest.Options = _options;

                if (additionalClientClaims != null)
                {
                    foreach (Claim additionalClientClaim in additionalClientClaims)
                    {
                        tokenCreationRequest.ValidatedRequest.ClientClaims.Add(additionalClientClaim);
                    }
                }

                var accessToken = await CreateAccessTokenAsync(tokenCreationRequest).ConfigureAwait(false);

                string defaultClientAuthority = _configurationProvider.DefaultClientAuthority;

                accessToken.Issuer    = defaultClientAuthority;
                accessToken.Audiences = new string[] { _configurationProvider.DefaultClientAudience };

                var accessTokenValue = await _tokenService.CreateSecurityTokenAsync(accessToken).ConfigureAwait(false);

                return(accessTokenValue);
            }
            catch (ApiException e)
            {
                throw e;
            }
            catch (Exception e)
            {
                _logger.LogError($"Error when getting access token: {e}");

                throw new InternalServerErrorApiException();
            }
        }
Exemplo n.º 19
0
        public async Task <IActionResult> Login(LoginInputModel model, string button)
        {
            _logger.LogInformation("Login. Email: {Email}, Remember login: {RememberLogin}.",
                                   model.Email, model.RememberLogin);

            // check if we are in the context of an authorization request
            var context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl);

            // the user clicked the "cancel" button
            if (button != "login")
            {
                if (context != null)
                {
                    // if the user cancels, send a result back into IdentityServer as if they
                    // denied the consent (even if this client does not require consent).
                    // this will send back an access denied OIDC error response to the client.
                    await _interaction.DenyAuthorizationAsync(context, AuthorizationError.AccessDenied);

                    // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null
                    if (context.IsNativeClient())
                    {
                        // The client is native, so this change in how to
                        // return the response is for better UX for the end user.
                        return(this.LoadingPage("Redirect", model.ReturnUrl));
                    }

                    return(Redirect(model.ReturnUrl));
                }
                else
                {
                    // since we don't have a valid context, then we just go back to the home page
                    return(Redirect("~/"));
                }
            }

            if (ModelState.IsValid)
            {
                var user = await _userRepository.GetUserByEmailAsync(model.Email.ToLower());

                var isHavePassword = !string.IsNullOrEmpty(user.HashPassword) && !string.IsNullOrEmpty(user.Salt);

                if (!user.IsEmpty() && isHavePassword)
                {
                    _logger.LogInformation("Login. Found user by mail: id {Id}, name {Name}, Surname {Surname}, mail {Mail}.",
                                           user.Id, user.Name, user.Surname, user.Mail);

                    //Validate found user
                    if (_userService.ValidateCredentials(user, model.Password))
                    {
                        _logger.LogInformation("Login. Validate Credentials was success. User: id {Id}, name {Name}, " +
                                               "Surname {Surname}, mail {Mail}.", user.Id, user.Name, user.Surname, user.Mail);

                        await _events.RaiseAsync(new UserLoginSuccessEvent(user.Name, user.Id.ToString(), user.Name));

                        // only set explicit expiration here if user chooses "remember me".
                        // otherwise we rely upon expiration configured in cookie middleware.
                        AuthenticationProperties props = null;
                        if (AccountOptions.AllowRememberLogin && model.RememberLogin)
                        {
                            props = new AuthenticationProperties
                            {
                                IsPersistent = true,
                                ExpiresUtc   = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration)
                            };
                        }
                        ;

                        // issue authentication cookie with subject ID and username
                        var isuser = new IdentityServerUser(user.Id.ToString())
                        {
                            DisplayName = user.Name
                        };

                        await HttpContext.SignInAsync(isuser, props);

                        if (context != null)
                        {
                            if (context.IsNativeClient())
                            {
                                // The client is native, so this change in how to
                                // return the response is for better UX for the end user.
                                return(this.LoadingPage("Redirect", model.ReturnUrl));
                            }

                            // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null
                            return(Redirect(model.ReturnUrl));
                        }

                        // request for a local page
                        if (Url.IsLocalUrl(model.ReturnUrl))
                        {
                            return(Redirect(model.ReturnUrl));
                        }
                        else if (string.IsNullOrEmpty(model.ReturnUrl))
                        {
                            return(Redirect("~/"));
                        }
                        else
                        {
                            // user might have clicked on a malicious link - should be logged
                            throw new Exception("invalid return URL");
                        }
                    }
                    else
                    {
                        _logger.LogWarning("Login. Validate Credentials was failed. User: id {Id}, name {Name}, " +
                                           "Surname {Surname}, mail {Mail}.", user.Id, user.Name, user.Surname, user.Mail);
                    }
                    _logger.LogWarning("Login. User with email {email} not exist.", model.Email.ToLower());
                }

                await _events.RaiseAsync(new UserLoginFailureEvent(model.Email, "invalid credentials", clientId : context?.Client.ClientId));

                ModelState.AddModelError(string.Empty, _localizer["Invalid_email_or_password"].Value);
            }

            // something went wrong, show form with error
            var vm = await BuildLoginViewModelAsync(model);

            return(View(vm));
        }
Exemplo n.º 20
0
        public async Task <IdentityServerStoreAppliedInfo> CreateIdentityServerUserAsync(IdentityServerUser user)
        {
            var result = await TryWithAwaitInCatch.ExecuteAndHandleErrorAsync(
                async() =>
            {
                await ResilientSessionContainer.EstablishSessionAsync();
                return(await ResilientSessionContainer.ResilientSession.CreateIdentityServerUserAsync(user));
            },
                async (ex) => ResilientSessionContainer.HandleCassandraException <IdentityServerStoreAppliedInfo>(ex));

            return(result);
        }
Exemplo n.º 21
0
    public async Task <IActionResult> OnGet()
    {
        // read external identity from the temporary cookie
        var result = await HttpContext.AuthenticateAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme);

        if (result?.Succeeded != true)
        {
            throw new Exception("External authentication error");
        }

        var externalUser = result.Principal;

        if (_logger.IsEnabled(LogLevel.Debug))
        {
            var externalClaims = externalUser.Claims.Select(c => $"{c.Type}: {c.Value}");
            _logger.LogDebug("External claims: {@claims}", externalClaims);
        }

        // lookup our user and external provider info
        // try to determine the unique id of the external user (issued by the provider)
        // the most common claim type for that are the sub claim and the NameIdentifier
        // depending on the external provider, some other claim type might be used
        var userIdClaim = externalUser.FindFirst(JwtClaimTypes.Subject) ??
                          externalUser.FindFirst(ClaimTypes.NameIdentifier) ??
                          throw new Exception("Unknown userid");

        var provider       = result.Properties.Items["scheme"];
        var providerUserId = userIdClaim.Value;

        // find external user
        var user = _users.FindByExternalProvider(provider, providerUserId);

        if (user == null)
        {
            // this might be where you might initiate a custom workflow for user registration
            // in this sample we don't show how that would be done, as our sample implementation
            // simply auto-provisions new external user
            //
            // remove the user id claim so we don't include it as an extra claim if/when we provision the user
            var claims = externalUser.Claims.ToList();
            claims.Remove(userIdClaim);
            user = _users.AutoProvisionUser(provider, providerUserId, claims.ToList());
        }

        // this allows us to collect any additional claims or properties
        // for the specific protocols used and store them in the local auth cookie.
        // this is typically used to store data needed for signout from those protocols.
        var additionalLocalClaims = new List <Claim>();
        var localSignInProps      = new AuthenticationProperties();

        CaptureExternalLoginContext(result, additionalLocalClaims, localSignInProps);

        // issue authentication cookie for user
        var isuser = new IdentityServerUser(user.SubjectId)
        {
            DisplayName      = user.Username,
            IdentityProvider = provider,
            AdditionalClaims = additionalLocalClaims
        };

        await HttpContext.SignInAsync(isuser, localSignInProps);

        // delete temporary cookie used during external authentication
        await HttpContext.SignOutAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme);

        // retrieve return URL
        var returnUrl = result.Properties.Items["returnUrl"] ?? "~/";

        // check if external login is in the context of an OIDC request
        var context = await _interaction.GetAuthorizationContextAsync(returnUrl);

        await _events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.SubjectId, user.Username, true, context?.Client.ClientId));

        if (context != null)
        {
            if (context.IsNativeClient())
            {
                // The client is native, so this change in how to
                // return the response is for better UX for the end user.
                return(this.LoadingPage(returnUrl));
            }
        }

        return(Redirect(returnUrl));
    }
Exemplo n.º 22
0
        public async Task <IActionResult> Login(LoginModel loginModel)
        {
            if (ModelState.IsValid)
            {
                var validCredentials = await AccountService.ValidateCredentials(loginModel);

                if (validCredentials)
                {
                    // check if we are in the context of an authorization request
                    var context = await InteractionService.GetAuthorizationContextAsync(loginModel.RedirectURL);

                    var user = await UserService.GetUserByEmail(loginModel.Email);

                    // only set explicit expiration here if user chooses "remember me".
                    // otherwise we rely upon expiration configured in cookie middleware.
                    var props = default(AuthenticationProperties);
                    if (loginModel.Remember)
                    {
                        props = new AuthenticationProperties
                        {
                            IsPersistent = true,
                            ExpiresUtc   = DateTimeOffset.UtcNow.Add(TimeSpan.FromDays(30))
                        };
                    }

                    // issue authentication cookie with subject ID and username
                    var isuser = new IdentityServerUser(user.Id)
                    {
                        DisplayName      = user.Name,
                        AdditionalClaims = user.Roles?.Select(role => new Claim(JwtClaimTypes.Role, role))?.ToList() ?? new System.Collections.Generic.List <Claim>()
                    };

                    await HttpContextWrapper.SignInAsync(HttpContext, isuser, props);

                    if (context != null)
                    {
                        // if (context.IsNativeClient())
                        // {
                        // The client is native, so this change in how to
                        // return the response is for better UX for the end user.
                        // return this.LoadingPage("Redirect", model.ReturnUrl);
                        //}

                        // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null
                        return(Redirect(loginModel.RedirectURL));
                    }

                    // request for a local page
                    if (Url.IsLocalUrl(loginModel.RedirectURL))
                    {
                        return(Redirect(loginModel.RedirectURL));
                    }
                    else if (string.IsNullOrEmpty(loginModel.RedirectURL))
                    {
                        return(Redirect("~/"));
                    }
                    else
                    {
                        // user might have clicked on a malicious link - should be logged
                        throw new Exception("invalid return URL");
                    }
                }
            }

            this.ModelState.AddModelError(INVALID_CREDENTIALS, "Invalid Credentials");

            return(View(ControllerConstants.LOGIN, loginModel));
        }
Exemplo n.º 23
0
        public async Task <IActionResult> Callback()
        {
            // read external identity from the temporary cookie
            var result = await HttpContext.AuthenticateAsync(IdentityConstants.ExternalScheme);

            if (result?.Succeeded != true)
            {
                throw new Exception("External authentication error");
            }

            if (_logger.IsEnabled(LogLevel.Debug))
            {
                var externalClaims = result.Principal.Claims.Select(c => $"{c.Type}: {c.Value}");
                _logger.LogDebug("External claims: {@claims}", externalClaims);
            }

            // lookup our user and external provider info
            var(user, provider, providerUserId, claims) = await FindUserFromExternalProviderAsync(result);

            if (user == null)
            {
                // this might be where you might initiate a custom workflow for user registration
                // in this sample we don't show how that would be done, as our sample implementation
                // simply auto-provisions new external user
                user = await AutoProvisionUserAsync(provider, providerUserId, claims);
            }

            // this allows us to collect any additonal claims or properties
            // for the specific prtotocols used and store them in the local auth cookie.
            // this is typically used to store data needed for signout from those protocols.
            var additionalLocalClaims = new List <Claim>();
            var localSignInProps      = new AuthenticationProperties();

            ProcessLoginCallbackForOidc(result, additionalLocalClaims, localSignInProps);
            //ProcessLoginCallbackForWsFed(result, additionalLocalClaims, localSignInProps);
            //ProcessLoginCallbackForSaml2p(result, additionalLocalClaims, localSignInProps);

            // issue authentication cookie for user
            // we must issue the cookie maually, and can't use the SignInManager because
            // it doesn't expose an API to issue additional claims from the login workflow
            var principal = await _signInManager.CreateUserPrincipalAsync(user);

            additionalLocalClaims.AddRange(principal.Claims);
            var name = principal.FindFirst(JwtClaimTypes.Name)?.Value ?? user.Id;

            var isuser = new IdentityServerUser(user.Id)
            {
                DisplayName      = name,
                IdentityProvider = provider,
                AdditionalClaims = additionalLocalClaims
            };

            await HttpContext.SignInAsync(isuser, localSignInProps);

            // delete temporary cookie used during external authentication
            await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);

            // retrieve return URL
            var returnUrl = result.Properties.Items["returnUrl"] ?? "~/";

            // check if external login is in the context of an OIDC request
            var context = await _interaction.GetAuthorizationContextAsync(returnUrl);

            await _events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.Id, name, true, context?.ClientId));

            if (context != null)
            {
                if (await _clientStore.IsPkceClientAsync(context.ClientId))
                {
                    // if the client is PKCE then we assume it's native, so this change in how to
                    // return the response is for better UX for the end user.
                    return(this.LoadingPage("Redirect", returnUrl));
                }
            }

            return(Redirect(returnUrl));
        }
Exemplo n.º 24
0
        public async Task <ActionResult> MakeAssertion([ModelBinder(typeof(NewtonsoftJsonAdapter.Binder))] MakeAssertionRequest request)
        {
            try
            {
                // 1. Get the assertion options we sent the client
                var jsonOptions = TestUsers.FidoAttestationOptions[request.SessionId];
                var options     = AssertionOptions.FromJson(jsonOptions);

                // 2. Get registered credential from database
                var creds = TestUsers.FidoCredentials.Where(c => c.Descriptor.Id.SequenceEqual(request.RawResponse.Id)).FirstOrDefault();
                if (creds == null)
                {
                    return(BadRequest("unknown credentials"));
                }

                // 3. Get credential counter from database
                var storedCounter = creds.SignatureCounter;

                // 4. Create callback to check if userhandle owns the credentialId
                IsUserHandleOwnerOfCredentialIdAsync callback = async(args) =>
                {
                    var storedCreds = TestUsers.FidoCredentials.Where(c => c.UserHandle.SequenceEqual(args.UserHandle));
                    return(storedCreds.Any(c => c.Descriptor.Id.SequenceEqual(args.CredentialId)));
                };

                // 5. Make the assertion
                var res = await _lib.MakeAssertionAsync(
                    assertionResponse : request.RawResponse,
                    originalOptions : options,
                    storedPublicKey : creds.PublicKey,
                    storedSignatureCounter : storedCounter,
                    isUserHandleOwnerOfCredentialIdCallback : callback);

                // 6. Store the updated counter
                TestUsers.FidoCredentials.Where(c => c.Descriptor.Id.SequenceEqual(res.CredentialId)).FirstOrDefault().SignatureCounter = res.Counter;

                // 7. return OK to client
                if (string.Equals(res.Status, "ok", StringComparison.InvariantCultureIgnoreCase))
                {
                    //actually loging the user in
                    var context = await _interaction.GetAuthorizationContextAsync(request.ReturnUrl);

                    var dbUser = TestUsers.Users.FirstOrDefault(u => string.Equals(u.SubjectId, creds.SubjectId, StringComparison.InvariantCultureIgnoreCase));
                    AuthenticationProperties props = null;
                    if (AccountOptions.AllowRememberLogin && request.RememberLogin)
                    {
                        props = new AuthenticationProperties
                        {
                            IsPersistent = true,
                            ExpiresUtc   = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration)
                        };
                    }
                    ;
                    var isuser = new IdentityServerUser(dbUser.SubjectId)
                    {
                        DisplayName = dbUser.Username
                    };
                    await HttpContext.SignInAsync(isuser, props);

                    if (context != null)
                    {
                        // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null
                        return(this.NewtonsoftJsonResult(new MakeAssertionResponse {
                            Status = "ok", Response = res, ReturnUrl = request.ReturnUrl
                        }));
                    }

                    // request for a local page
                    if (Url.IsLocalUrl(request.ReturnUrl))
                    {
                        return(this.NewtonsoftJsonResult(new MakeAssertionResponse {
                            Status = "ok", Response = res, ReturnUrl = request.ReturnUrl
                        }));
                    }
                    else if (string.IsNullOrEmpty(request.ReturnUrl))
                    {
                        return(this.NewtonsoftJsonResult(new MakeAssertionResponse {
                            Status = "ok", Response = res, ReturnUrl = "~/"
                        }));
                    }
                    else
                    {
                        // user might have clicked on a malicious link - should be logged
                        throw new Exception("invalid return URL");
                    }
                }
                else
                {
                    return(BadRequest("not ok"));
                }
            }
            catch (Exception e)
            {
                return(BadRequest(new AssertionVerificationResult {
                    Status = "error", ErrorMessage = FormatException(e)
                }));
            }
        }
        public async Task <IResponseOutput> Login(LoginInput input)
        {
            if (!ModelState.IsValid)
            {
                return(ResponseOutput.NotOk(ModelState.Values.First().Errors[0].ErrorMessage));
            }

            if (input.Captcha == null)
            {
                return(ResponseOutput.NotOk("请完成安全验证!"));
            }

            //滑动验证
            input.Captcha.DeleteCache = true;
            using var client          = new HttpClient();
            var res = await client.GetAsync($"{_appSettings.Captcha.CheckUrl}?{ToParams(input.Captcha)}");

            var content = await res.Content.ReadAsStringAsync();

            var captchaResult = JsonConvert.DeserializeObject <ResultModel <string> >(content);

            if (!captchaResult.Success)
            {
                return(ResponseOutput.NotOk("安全验证不通过,请重新登录!"));
            }


            var sw = new Stopwatch();

            sw.Start();

            var context = await _interaction.GetAuthorizationContextAsync(input.ReturnUrl);

            var user = await _userRepository.Select.Where(a => a.UserName == input.UserName)
                       .ToOneAsync(a => new { a.Id, a.Password, a.NickName, a.TenantId });

            if (user == null)
            {
                return(ResponseOutput.NotOk("", 1));
            }

            var password = MD5Encrypt.Encrypt32(input.Password);

            if (user.Password != password)
            {
                return(ResponseOutput.NotOk("", 2));
            }

            AuthenticationProperties props = null;

            if (input.RememberLogin)
            {
                props = new AuthenticationProperties
                {
                    IsPersistent = true,
                    ExpiresUtc   = DateTimeOffset.UtcNow.Add(TimeSpan.FromDays(1))
                };
            }
            ;

            var identityServerUser = new IdentityServerUser(user.Id.ToString())
            {
                DisplayName = input.UserName
            };

            await HttpContext.SignInAsync(identityServerUser, props);

            sw.Stop();

            //写登录日志
            var loginLogEntity = new LoginLogEntity()
            {
                Id                  = YitIdHelper.NextId(),
                TenantId            = user.TenantId,
                CreatedUserId       = user.Id,
                NickName            = user.NickName,
                CreatedUserName     = input.UserName,
                ElapsedMilliseconds = sw.ElapsedMilliseconds,
                Status              = true
            };

            await AddLoginLog(loginLogEntity);

            return(ResponseOutput.Ok());
        }
Exemplo n.º 26
0
        public async Task<IActionResult> Login(LoginInputModel model, string button)
        {
            if (button != "login")
            {
                // the user clicked the "cancel" button
                var context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl);
                if (context != null)
                {
                    // if the user cancels, send a result back into IdentityServer as if they 
                    // denied the consent (even if this client does not require consent).
                    // this will send back an access denied OIDC error response to the client.
                    await _interaction.DenyAuthorizationAsync(context, AuthorizationError.AccessDenied);
                    
                    // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null
                    return Redirect(model.ReturnUrl);
                }
                else
                {
                    // since we don't have a valid context, then we just go back to the home page
                    return Redirect("~/");
                }
            }

            if (ModelState.IsValid)
            {
                var user = await _userManager.FindByNameAsync(model.Username);

                if (user != null && await _userManager.CheckPasswordAsync(user, model.Password))
                {
                    await _events.RaiseAsync(new UserLoginSuccessEvent(user.UserName, user.Id, user.UserName));

                    // only set explicit expiration here if user chooses "remember me". 
                    // otherwise we rely upon expiration configured in cookie middleware.
                    AuthenticationProperties props = null;
                    if (AccountOptions.AllowRememberLogin && model.RememberLogin)
                    {
                        props = new AuthenticationProperties
                        {
                            IsPersistent = true,
                            ExpiresUtc = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration)
                        };
                    };

                    var isuser = new IdentityServerUser(user.Id)
                    {
                        DisplayName = user.UserName,
                        AdditionalClaims = new List<Claim>
                        {
                            new Claim("AspNet.Identity.SecurityStamp", user.SecurityStamp)
                        }
                    };

                    // issue authentication cookie with subject ID and username
                    await _events.RaiseAsync(new UserLoginSuccessEvent(user.UserName, user.Id, user.UserName));
                    await HttpContext.SignInAsync(isuser, props);

                    // make sure the returnUrl is still valid, and if so redirect back to authorize endpoint or a local page
                    if (_interaction.IsValidReturnUrl(model.ReturnUrl) || Url.IsLocalUrl(model.ReturnUrl))
                    {
                        return Redirect(model.ReturnUrl);
                    }

                    return Redirect("~/");
                }

                await _events.RaiseAsync(new UserLoginFailureEvent(model.Username, "invalid credentials"));

                ModelState.AddModelError("", AccountOptions.InvalidCredentialsErrorMessage);
            }

            // something went wrong, show form with error
            var vm = await _account.BuildLoginViewModelAsync(model);
            return View(vm);
        }
        public async Task <IActionResult> Callback()
        {
            // read external identity from the temporary cookie
            var result = await HttpContext.AuthenticateAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme);

            if (result?.Succeeded != true)
            {
                throw new Exception("External authentication error");
            }

            if (_logger.IsEnabled(LogLevel.Debug))
            {
                var externalClaims = result.Principal.Claims.Select(c => $"{c.Type}: {c.Value}");
                _logger.LogDebug("External claims: {@claims}", externalClaims);
            }

            // lookup our user and external provider info
            var(user, provider, providerUserId, claims) = FindUserFromExternalProvider(result);
            if (user == null)
            {
                // this might be where you might initiate a custom workflow for user registration
                // in this sample we don't show how that would be done, as our sample implementation
                // simply auto-provisions new external user
                user = AutoProvisionUser(provider, providerUserId, claims);
            }

            // this allows us to collect any additional claims or properties
            // for the specific protocols used and store them in the local auth cookie.
            // this is typically used to store data needed for signout from those protocols.
            var additionalLocalClaims = new List <Claim>();
            var localSignInProps      = new AuthenticationProperties();

            ProcessLoginCallback(result, additionalLocalClaims, localSignInProps);

            // issue authentication cookie for user
            var isuser = new IdentityServerUser(user.Id.ToString())
            {
                DisplayName      = user.UserName,
                IdentityProvider = provider,
                AdditionalClaims = additionalLocalClaims,
            };

            await HttpContext.SignInAsync(isuser, localSignInProps);

            // delete temporary cookie used during external authentication
            await HttpContext.SignOutAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme);

            // retrieve return URL
            var returnUrl = result.Properties.Items["returnUrl"] ?? "~/";

            // check if external login is in the context of an OIDC request
            var context = await _interaction.GetAuthorizationContextAsync(returnUrl);

            await _events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.Id.ToString(), user.UserName, true, context?.Client.ClientId));

            if (context != null)
            {
                if (context.IsNativeClient())
                {
                    // The client is native, so this change in how to
                    // return the response is for better UX for the end user.
                    return(this.LoadingPage("Redirect", returnUrl));
                }
            }

            return(Redirect(returnUrl));
        }
Exemplo n.º 28
0
 public Task SignInAsync(HttpContext httpContext, IdentityServerUser user, AuthenticationProperties properties)
 {
     return(httpContext.SignInAsync(user, properties));
 }
        public async Task <IResponseOutput> Login(LoginInputModel input)
        {
            if (!ModelState.IsValid)
            {
                return(ResponseOutput.NotOk(ModelState.Values.First().Errors[0].ErrorMessage));
            }

            var sw = new Stopwatch();

            sw.Start();

            // check if we are in the context of an authorization request
            var context = await _interaction.GetAuthorizationContextAsync(input.ReturnUrl);

            var user = await _userRepository.Select.Where(a => a.UserName == input.UserName)
                       .ToOneAsync(a => new { a.Id, a.Password, a.NickName });

            if (user == null)
            {
                return(ResponseOutput.NotOk("", 1));
            }

            var password = MD5Encrypt.Encrypt32(input.Password);

            if (user.Password != password)
            {
                return(ResponseOutput.NotOk("", 2));
            }

            await _events.RaiseAsync(new UserLoginSuccessEvent(input.UserName, user.Id.ToString(), input.UserName, clientId : context?.ClientId));

            // only set explicit expiration here if user chooses "remember me".
            // otherwise we rely upon expiration configured in cookie middleware.
            AuthenticationProperties props = null;

            if (AccountOptions.AllowRememberLogin && input.RememberLogin)
            {
                props = new AuthenticationProperties
                {
                    IsPersistent = true,
                    ExpiresUtc   = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration)
                };
            }
            ;

            // issue authentication cookie with subject ID and username
            var isuser = new IdentityServerUser(user.Id.ToString())
            {
                DisplayName = input.UserName
            };

            await HttpContext.SignInAsync(isuser, props);

            sw.Stop();

            //写登录日志
            var loginLogEntity = new LoginLogEntity()
            {
                CreatedUserId       = user.Id,
                NickName            = user.NickName,
                CreatedUserName     = input.UserName,
                ElapsedMilliseconds = sw.ElapsedMilliseconds,
                Status = true
            };

            await AddLoginLog(loginLogEntity);

            return(ResponseOutput.Ok());

            /*
             * if (context != null)
             * {
             *  if (await _clientStore.IsPkceClientAsync(context.ClientId))
             *  {
             *      // if the client is PKCE then we assume it's native, so this change in how to
             *      // return the response is for better UX for the end user.
             *      return this.LoadingPage("Redirect", input.ReturnUrl);
             *  }
             *
             *  // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null
             *  return Redirect(input.ReturnUrl);
             * }
             *
             * // request for a local page
             * if (Url.IsLocalUrl(input.ReturnUrl))
             * {
             *  return Redirect(input.ReturnUrl);
             * }
             * else if (string.IsNullOrEmpty(input.ReturnUrl))
             * {
             *  return Redirect("~/");
             * }
             * else
             * {
             *  // user might have clicked on a malicious link - should be logged
             *  throw new Exception("invalid return URL");
             * }
             *
             * await _events.RaiseAsync(new UserLoginFailureEvent(input.UserName, "invalid credentials", clientId: context?.ClientId));
             * ModelState.AddModelError(string.Empty, AccountOptions.InvalidCredentialsErrorMessage);
             */
        }
Exemplo n.º 30
0
        public async Task <IActionResult> Login(LoginInputModel model, string button)
        {
            // 检查我们是否在授权请求的上下文中
            var context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl);

            // 用户单击“取消”按钮
            if (button != "login")
            {
                if (context != null)
                {
                    //如果用户取消,则将结果发送到身份服务器,就像
                    // 拒绝同意(即使该客户不需要同意)。
                    // 这将向客户端发回一个被拒绝的oidc错误响应。
                    await _interaction.GrantConsentAsync(context, ConsentResponse.Denied);

                    // 我们可以信任模特。因为GetAuthorizationContextAsync回来了
                    if (await _clientStore.IsPkceClientAsync(context.ClientId))
                    {
                        // 如果客户端是pkce,那么我们假设它是本地的,因此在如何
                        // 返回响应是为了最终用户获得更好的ux。
                        return(View("Redirect", new RedirectViewModel {
                            RedirectUrl = model.ReturnUrl
                        }));
                    }

                    return(Redirect(model.ReturnUrl));
                }
                else
                {
                    // 既然我们没有一个有效的上下文,那么我们就回到主页
                    return(Redirect("~/"));
                }
            }

            if (ModelState.IsValid)
            {
                //查找用户
                //var user = _userApp.GetUser(model.Username);
                var requestUri = "http://localhost:61927/api/Account";
                var response   = MyHttp.Post(requestUri, null, model);

                CJ.Models.LoginInputModel user = new CJ.Models.LoginInputModel();
                if (!string.IsNullOrEmpty(response.Data))
                {
                    user = JsonConvert.DeserializeObject <CJ.Models.LoginInputModel>(response.Data);
                }
                else
                {
                    user = null;
                };
                //对内存中的用户名/密码进行验证
                if (user != null && (model.Password == DESCrypt.Decrypt(user.Password)))
                {
                    await _events.RaiseAsync(new UserLoginSuccessEvent(user.Username, user.Id, user.Username));

                    // 如果用户选择“记住我”,只在此设置显式过期。
                    // 否则,我们将依赖于Cookie中间件中配置的过期。
                    AuthenticationProperties props = null;
                    if (AccountOptions.AllowRememberLogin && model.RememberLogin)
                    {
                        props = new AuthenticationProperties
                        {
                            IsPersistent = true,                                                             //认证信息是否跨域有效
                            ExpiresUtc   = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration) //凭据有效时间
                        };
                    }
                    ;
                    var serverUser = new IdentityServerUser(user.Id);
                    serverUser.DisplayName = user.DisplayName;
                    var claims = new[]
                    {
                        new Claim("Username", user.Username),
                        new Claim("DisplayName", user.DisplayName)
                    };
                    serverUser.AdditionalClaims = claims;
                    // issue authentication cookie with subject ID and username
                    await HttpContext.SignInAsync(serverUser);

                    if (context != null)
                    {
                        if (await _clientStore.IsPkceClientAsync(context.ClientId))
                        {
                            // 如果客户端是pkce,那么我们假设它是本地的,所以在如何
                            // 返回的响应是为最终用户提供更好的ux。
                            return(View("Redirect", new RedirectViewModel {
                                RedirectUrl = model.ReturnUrl
                            }));
                        }

                        // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null
                        return(Redirect(model.ReturnUrl));
                    }

                    //请求本地页
                    if (Url.IsLocalUrl(model.ReturnUrl))
                    {
                        return(Redirect(model.ReturnUrl));
                    }
                    else if (string.IsNullOrEmpty(model.ReturnUrl))
                    {
                        return(Redirect("~/"));
                    }
                    else
                    {
                        // 用户可能点击了恶意链接-应该被记录
                        throw new Exception("无效的返回URL");
                    }
                }

                await _events.RaiseAsync(new UserLoginFailureEvent(model.Username, "无效的凭据"));

                ModelState.AddModelError(string.Empty, AccountOptions.InvalidCredentialsErrorMessage);
            }

            // 出了问题,显示形式错误
            var vm = await BuildLoginViewModelAsync(model);

            return(View(vm));
        }