)> ProcessCallbackGet( IClientStore clientStore, IEventService events, HttpContext httpContext, IIdentityServerInteractionService interaction, HostBasePartAuthJobUserEntityCreateService jobUserEntityCreate, ILogger logger, RoleManager <DataEntityObjectRole> roleManager, SignInManager <DataEntityObjectUser> signInManager, UserManager <DataEntityObjectUser> userManager ) { // read external identity from the temporary cookie var result = await httpContext.AuthenticateAsync(IdentityConstants.ExternalScheme) .CoreBaseExtTaskWithCurrentCulture(false); if (result?.Succeeded != true) { throw new ModIdentityServerBaseExceptionExternalAuthentication(); } // lookup our user and external provider info var(user, provider, providerUserId, claims) = await FindUserFromExternalProviderAsync(result, userManager); 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, logger, jobUserEntityCreate, roleManager, userManager ).CoreBaseExtTaskWithCurrentCulture(false); } // 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(); ProcessCallbackGetForOidc(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) .CoreBaseExtTaskWithCurrentCulture(false); additionalLocalClaims.AddRange(principal.Claims); var name = principal.FindFirst(JwtClaimTypes.Name)?.Value ?? user.Id.ToString(); await httpContext.SignInAsync( user.Id.ToString(), name, provider, localSignInProps, additionalLocalClaims.ToArray() ).CoreBaseExtTaskWithCurrentCulture(false); // delete temporary cookie used during external authentication await httpContext.SignOutAsync(IdentityConstants.ExternalScheme) .CoreBaseExtTaskWithCurrentCulture(false); // 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) .CoreBaseExtTaskWithCurrentCulture(false); await events.RaiseAsync( new UserLoginSuccessEvent( provider, providerUserId, user.Id.ToString(), name, true, context?.ClientId ) ).CoreBaseExtTaskWithCurrentCulture(false); var status = ModIdentityServerWebMvcPartExternalJobCallbackGetEnumStatuses.Default; if (context != null) { var isPckeRequired = await clientStore.ModIdentityServerWebExtClientIsPkceRequired(context.ClientId) .CoreBaseExtTaskWithCurrentCulture(false); if (isPckeRequired) { // 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. status = ModIdentityServerWebMvcPartExternalJobCallbackGetEnumStatuses.Redirect; } } return(status, returnUrl); }
private async Task <ModIdentityServerWebMvcPartAccountJobLoginPostEnumStatuses> ProcessLoginPost( ModIdentityServerWebMvcPartAccountViewLoginModel model, string action, IEventService events, ModelStateDictionary modelState, SignInManager <DataEntityObjectUser> signInManager, IUrlHelper urlHelper, UserManager <DataEntityObjectUser> userManager, IIdentityServerInteractionService interaction, IClientStore clientStore ) { // check if we are in the context of an authorization request var context = await interaction.GetAuthorizationContextAsync(model.ReturnUrl) .CoreBaseExtTaskWithCurrentCulture(false); // the user clicked the "cancel" button if (action != ModIdentityServerWebMvcSettings.ACTION_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) .CoreBaseExtTaskWithCurrentCulture(false); var isPckeRequired = await clientStore.ModIdentityServerWebExtClientIsPkceRequired(context.ClientId) .CoreBaseExtTaskWithCurrentCulture(false); // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null if (isPckeRequired) { // 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(ModIdentityServerWebMvcPartAccountJobLoginPostEnumStatuses.Redirect); } return(ModIdentityServerWebMvcPartAccountJobLoginPostEnumStatuses.Return); } else { // since we don't have a valid context, then we just go back to the home page return(ModIdentityServerWebMvcPartAccountJobLoginPostEnumStatuses.Index); } } else if (modelState.IsValid) { var result = await signInManager.PasswordSignInAsync( model.Username, model.Password, model.RememberLogin, lockoutOnFailure : true ).CoreBaseExtTaskWithCurrentCulture(false); if (result.Succeeded) { var user = await userManager.FindByNameAsync(model.Username) .CoreBaseExtTaskWithCurrentCulture(false); await events.RaiseAsync( new UserLoginSuccessEvent( user.UserName, user.Id.ToString(), user.UserName, clientId : context?.ClientId ) ).CoreBaseExtTaskWithCurrentCulture(false); if (context != null) { var isPckeRequired = await clientStore.ModIdentityServerWebExtClientIsPkceRequired(context.ClientId) .CoreBaseExtTaskWithCurrentCulture(false); if (isPckeRequired) { // 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(ModIdentityServerWebMvcPartAccountJobLoginPostEnumStatuses.Redirect); } // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null return(ModIdentityServerWebMvcPartAccountJobLoginPostEnumStatuses.Return); } // request for a local page if (urlHelper.IsLocalUrl(model.ReturnUrl)) { return(ModIdentityServerWebMvcPartAccountJobLoginPostEnumStatuses.Return); } else if (string.IsNullOrEmpty(model.ReturnUrl)) { return(ModIdentityServerWebMvcPartAccountJobLoginPostEnumStatuses.Index); } else { // user might have clicked on a malicious link - should be logged throw new ModIdentityServerBaseExceptionInvalidReturnUrl(); } } await events.RaiseAsync( new UserLoginFailureEvent( model.Username, "invalid credentials", clientId : context?.ClientId ) ).CoreBaseExtTaskWithCurrentCulture(false); throw new ModIdentityServerBaseExceptionLogin(); } return(ModIdentityServerWebMvcPartAccountJobLoginPostEnumStatuses.Default); }