@page "/Account/ExternalLogin" @using System.ComponentModel.DataAnnotations @using System.Security.Claims @using System.Text @using System.Text.Encodings.Web @using Microsoft.AspNetCore.Identity @using Microsoft.AspNetCore.WebUtilities @inject SignInManager SignInManager @inject UserManager UserManager @inject IUserStore UserStore @inject IEmailSender EmailSender @inject NavigationManager NavigationManager @inject IdentityRedirectManager RedirectManager @inject ILogger Logger Register

Register

Associate your @ProviderDisplayName account.


You've successfully authenticated with @ProviderDisplayName. Please enter an email address for this site below and click the Register button to finish logging in.
@code { public const string LoginCallbackAction = "LoginCallback"; private string? message; private ExternalLoginInfo externalLoginInfo = default!; [CascadingParameter] private HttpContext HttpContext { get; set; } = default!; [SupplyParameterFromForm] private InputModel Input { get; set; } = new(); [SupplyParameterFromQuery] private string? RemoteError { get; set; } [SupplyParameterFromQuery] private string? ReturnUrl { get; set; } [SupplyParameterFromQuery] private string? Action { get; set; } private string? ProviderDisplayName => externalLoginInfo.ProviderDisplayName; protected override async Task OnInitializedAsync() { if(RemoteError is not null) { RedirectManager.RedirectToWithStatus("Account/Login", $"Error from external provider: {RemoteError}", HttpContext); } ExternalLoginInfo? info = await SignInManager.GetExternalLoginInfoAsync(); if(info is null) { RedirectManager.RedirectToWithStatus("Account/Login", "Error loading external login information.", HttpContext); } externalLoginInfo = info; if(HttpMethods.IsGet(HttpContext.Request.Method)) { if(Action == LoginCallbackAction) { await OnLoginCallbackAsync(); return; } // We should only reach this page via the login callback, so redirect back to // the login page if we get here some other way. RedirectManager.RedirectTo("Account/Login"); } } private async Task OnLoginCallbackAsync() { // Sign in the user with this external login provider if the user already has a login. SignInResult result = await SignInManager.ExternalLoginSignInAsync(externalLoginInfo.LoginProvider, externalLoginInfo.ProviderKey, false, true); if(result.Succeeded) { Logger.LogInformation("{Name} logged in with {LoginProvider} provider.", externalLoginInfo.Principal.Identity?.Name, externalLoginInfo.LoginProvider); RedirectManager.RedirectTo(ReturnUrl); } else if(result.IsLockedOut) { RedirectManager.RedirectTo("Account/Lockout"); } // If the user does not have an account, then ask the user to create an account. if(externalLoginInfo.Principal.HasClaim(c => c.Type == ClaimTypes.Email)) { Input.Email = externalLoginInfo.Principal.FindFirstValue(ClaimTypes.Email) ?? ""; } } private async Task OnValidSubmitAsync() { IUserEmailStore emailStore = GetEmailStore(); IdentityUser user = CreateUser(); await UserStore.SetUserNameAsync(user, Input.Email, CancellationToken.None); await emailStore.SetEmailAsync(user, Input.Email, CancellationToken.None); IdentityResult result = await UserManager.CreateAsync(user); if(result.Succeeded) { result = await UserManager.AddLoginAsync(user, externalLoginInfo); if(result.Succeeded) { Logger.LogInformation("User created an account using {Name} provider.", externalLoginInfo.LoginProvider); string userId = await UserManager.GetUserIdAsync(user); string code = await UserManager.GenerateEmailConfirmationTokenAsync(user); code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); string callbackUrl = NavigationManager.GetUriWithQueryParameters(NavigationManager.ToAbsoluteUri("Account/ConfirmEmail").AbsoluteUri, new Dictionary { ["userId"] = userId, ["code"] = code }); await EmailSender.SendConfirmationLinkAsync(user, Input.Email, HtmlEncoder.Default.Encode(callbackUrl)); // If account confirmation is required, we need to show the link if we don't have a real email sender if(UserManager.Options.SignIn.RequireConfirmedAccount) { RedirectManager.RedirectTo("Account/RegisterConfirmation", new Dictionary { ["email"] = Input.Email }); } await SignInManager.SignInAsync(user, false, externalLoginInfo.LoginProvider); RedirectManager.RedirectTo(ReturnUrl); } } message = $"Error: {string.Join(",", result.Errors.Select(error => error.Description))}"; } private IdentityUser CreateUser() { try { return Activator.CreateInstance(); } catch { throw new InvalidOperationException($"Can't create an instance of '{nameof(IdentityUser)}'. " + $"Ensure that '{nameof(IdentityUser)}' is not an abstract class and has a parameterless constructor"); } } private IUserEmailStore GetEmailStore() { if(!UserManager.SupportsUserEmail) { throw new NotSupportedException("The default UI requires a user store with email support."); } return (IUserEmailStore)UserStore; } private sealed class InputModel { [Required] [EmailAddress] public string Email { get; set; } = ""; } }