source: PostgreSqlDotnetCore/Areas/Identity/Pages/Account/ExternalLogin.cshtml.cs@ 8f8226c

main
Last change on this file since 8f8226c was 2aea0fd, checked in by ElenaMoskova <elena.moskova99@…>, 2 months ago

init commit Elena

  • Property mode set to 100644
File size: 9.6 KB
Line 
1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3#nullable disable
4
5using System;
6using System.ComponentModel.DataAnnotations;
7using System.Security.Claims;
8using System.Text;
9using System.Text.Encodings.Web;
10using System.Threading;
11using System.Threading.Tasks;
12using Microsoft.AspNetCore.Authorization;
13using Microsoft.Extensions.Options;
14using Microsoft.AspNetCore.Identity;
15using Microsoft.AspNetCore.Identity.UI.Services;
16using Microsoft.AspNetCore.Mvc;
17using Microsoft.AspNetCore.Mvc.RazorPages;
18using Microsoft.AspNetCore.WebUtilities;
19using Microsoft.Extensions.Logging;
20
21namespace PostgreSqlDotnetCore.Areas.Identity.Pages.Account
22{
23 [AllowAnonymous]
24 public class ExternalLoginModel : PageModel
25 {
26 private readonly SignInManager<IdentityUser> _signInManager;
27 private readonly UserManager<IdentityUser> _userManager;
28 private readonly IUserStore<IdentityUser> _userStore;
29 private readonly IUserEmailStore<IdentityUser> _emailStore;
30 private readonly IEmailSender _emailSender;
31 private readonly ILogger<ExternalLoginModel> _logger;
32
33 public ExternalLoginModel(
34 SignInManager<IdentityUser> signInManager,
35 UserManager<IdentityUser> userManager,
36 IUserStore<IdentityUser> userStore,
37 ILogger<ExternalLoginModel> logger,
38 IEmailSender emailSender)
39 {
40 _signInManager = signInManager;
41 _userManager = userManager;
42 _userStore = userStore;
43 _emailStore = GetEmailStore();
44 _logger = logger;
45 _emailSender = emailSender;
46 }
47
48 /// <summary>
49 /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
50 /// directly from your code. This API may change or be removed in future releases.
51 /// </summary>
52 [BindProperty]
53 public InputModel Input { get; set; }
54
55 /// <summary>
56 /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
57 /// directly from your code. This API may change or be removed in future releases.
58 /// </summary>
59 public string ProviderDisplayName { get; set; }
60
61 /// <summary>
62 /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
63 /// directly from your code. This API may change or be removed in future releases.
64 /// </summary>
65 public string ReturnUrl { get; set; }
66
67 /// <summary>
68 /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
69 /// directly from your code. This API may change or be removed in future releases.
70 /// </summary>
71 [TempData]
72 public string ErrorMessage { get; set; }
73
74 /// <summary>
75 /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
76 /// directly from your code. This API may change or be removed in future releases.
77 /// </summary>
78 public class InputModel
79 {
80 /// <summary>
81 /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
82 /// directly from your code. This API may change or be removed in future releases.
83 /// </summary>
84 [Required]
85 [EmailAddress]
86 public string Email { get; set; }
87 }
88
89 public IActionResult OnGet() => RedirectToPage("./Login");
90
91 public IActionResult OnPost(string provider, string returnUrl = null)
92 {
93 // Request a redirect to the external login provider.
94 var redirectUrl = Url.Page("./ExternalLogin", pageHandler: "Callback", values: new { returnUrl });
95 var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
96 return new ChallengeResult(provider, properties);
97 }
98
99 public async Task<IActionResult> OnGetCallbackAsync(string returnUrl = null, string remoteError = null)
100 {
101 returnUrl = returnUrl ?? Url.Content("~/");
102 if (remoteError != null)
103 {
104 ErrorMessage = $"Error from external provider: {remoteError}";
105 return RedirectToPage("./Login", new { ReturnUrl = returnUrl });
106 }
107 var info = await _signInManager.GetExternalLoginInfoAsync();
108 if (info == null)
109 {
110 ErrorMessage = "Error loading external login information.";
111 return RedirectToPage("./Login", new { ReturnUrl = returnUrl });
112 }
113
114 // Sign in the user with this external login provider if the user already has a login.
115 var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false, bypassTwoFactor: true);
116 if (result.Succeeded)
117 {
118 _logger.LogInformation("{Name} logged in with {LoginProvider} provider.", info.Principal.Identity.Name, info.LoginProvider);
119 return LocalRedirect(returnUrl);
120 }
121 if (result.IsLockedOut)
122 {
123 return RedirectToPage("./Lockout");
124 }
125 else
126 {
127 // If the user does not have an account, then ask the user to create an account.
128 ReturnUrl = returnUrl;
129 ProviderDisplayName = info.ProviderDisplayName;
130 if (info.Principal.HasClaim(c => c.Type == ClaimTypes.Email))
131 {
132 Input = new InputModel
133 {
134 Email = info.Principal.FindFirstValue(ClaimTypes.Email)
135 };
136 }
137 return Page();
138 }
139 }
140
141 public async Task<IActionResult> OnPostConfirmationAsync(string returnUrl = null)
142 {
143 returnUrl = returnUrl ?? Url.Content("~/");
144 // Get the information about the user from the external login provider
145 var info = await _signInManager.GetExternalLoginInfoAsync();
146 if (info == null)
147 {
148 ErrorMessage = "Error loading external login information during confirmation.";
149 return RedirectToPage("./Login", new { ReturnUrl = returnUrl });
150 }
151
152 if (ModelState.IsValid)
153 {
154 var user = CreateUser();
155
156 await _userStore.SetUserNameAsync(user, Input.Email, CancellationToken.None);
157 await _emailStore.SetEmailAsync(user, Input.Email, CancellationToken.None);
158
159 var result = await _userManager.CreateAsync(user);
160 if (result.Succeeded)
161 {
162 result = await _userManager.AddLoginAsync(user, info);
163 if (result.Succeeded)
164 {
165 _logger.LogInformation("User created an account using {Name} provider.", info.LoginProvider);
166
167 var userId = await _userManager.GetUserIdAsync(user);
168 var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
169 code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
170 var callbackUrl = Url.Page(
171 "/Account/ConfirmEmail",
172 pageHandler: null,
173 values: new { area = "Identity", userId = userId, code = code },
174 protocol: Request.Scheme);
175
176 await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",
177 $"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
178
179 // If account confirmation is required, we need to show the link if we don't have a real email sender
180 if (_userManager.Options.SignIn.RequireConfirmedAccount)
181 {
182 return RedirectToPage("./RegisterConfirmation", new { Email = Input.Email });
183 }
184
185 await _signInManager.SignInAsync(user, isPersistent: false, info.LoginProvider);
186 return LocalRedirect(returnUrl);
187 }
188 }
189 foreach (var error in result.Errors)
190 {
191 ModelState.AddModelError(string.Empty, error.Description);
192 }
193 }
194
195 ProviderDisplayName = info.ProviderDisplayName;
196 ReturnUrl = returnUrl;
197 return Page();
198 }
199
200 private IdentityUser CreateUser()
201 {
202 try
203 {
204 return Activator.CreateInstance<IdentityUser>();
205 }
206 catch
207 {
208 throw new InvalidOperationException($"Can't create an instance of '{nameof(IdentityUser)}'. " +
209 $"Ensure that '{nameof(IdentityUser)}' is not an abstract class and has a parameterless constructor, or alternatively " +
210 $"override the external login page in /Areas/Identity/Pages/Account/ExternalLogin.cshtml");
211 }
212 }
213
214 private IUserEmailStore<IdentityUser> GetEmailStore()
215 {
216 if (!_userManager.SupportsUserEmail)
217 {
218 throw new NotSupportedException("The default UI requires a user store with email support.");
219 }
220 return (IUserEmailStore<IdentityUser>)_userStore;
221 }
222 }
223}
Note: See TracBrowser for help on using the repository browser.