forked from bhrugen/IdentityManager
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Section 7 - Scaffold Identity Class Library
- Loading branch information
Bhrugen Patel
committed
Sep 4, 2020
1 parent
3ba3905
commit 3619502
Showing
74 changed files
with
3,307 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
using System; | ||
using IdentityManager.Data; | ||
using Microsoft.AspNetCore.Hosting; | ||
using Microsoft.AspNetCore.Identity; | ||
using Microsoft.AspNetCore.Identity.UI; | ||
using Microsoft.EntityFrameworkCore; | ||
using Microsoft.Extensions.Configuration; | ||
using Microsoft.Extensions.DependencyInjection; | ||
|
||
[assembly: HostingStartup(typeof(IdentityManager.Areas.Identity.IdentityHostingStartup))] | ||
namespace IdentityManager.Areas.Identity | ||
{ | ||
public class IdentityHostingStartup : IHostingStartup | ||
{ | ||
public void Configure(IWebHostBuilder builder) | ||
{ | ||
builder.ConfigureServices((context, services) => { | ||
}); | ||
} | ||
} | ||
} |
10 changes: 10 additions & 0 deletions
10
IdentityManager/Areas/Identity/Pages/Account/AccessDenied.cshtml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
@page | ||
@model AccessDeniedModel | ||
@{ | ||
ViewData["Title"] = "Access denied"; | ||
} | ||
|
||
<header> | ||
<h1 class="text-danger">@ViewData["Title"]</h1> | ||
<p class="text-danger">You do not have access to this resource.</p> | ||
</header> |
17 changes: 17 additions & 0 deletions
17
IdentityManager/Areas/Identity/Pages/Account/AccessDenied.cshtml.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using Microsoft.AspNetCore.Mvc.RazorPages; | ||
|
||
namespace IdentityManager.Areas.Identity.Pages.Account | ||
{ | ||
public class AccessDeniedModel : PageModel | ||
{ | ||
public void OnGet() | ||
{ | ||
|
||
} | ||
} | ||
} | ||
|
7 changes: 7 additions & 0 deletions
7
IdentityManager/Areas/Identity/Pages/Account/ConfirmEmail.cshtml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
@page | ||
@model ConfirmEmailModel | ||
@{ | ||
ViewData["Title"] = "Confirm email"; | ||
} | ||
|
||
<h1>@ViewData["Title"]</h1> |
46 changes: 46 additions & 0 deletions
46
IdentityManager/Areas/Identity/Pages/Account/ConfirmEmail.cshtml.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using Microsoft.AspNetCore.Authorization; | ||
using Microsoft.AspNetCore.Identity; | ||
using Microsoft.AspNetCore.Mvc; | ||
using Microsoft.AspNetCore.Mvc.RazorPages; | ||
using Microsoft.AspNetCore.WebUtilities; | ||
|
||
namespace IdentityManager.Areas.Identity.Pages.Account | ||
{ | ||
[AllowAnonymous] | ||
public class ConfirmEmailModel : PageModel | ||
{ | ||
private readonly UserManager<IdentityUser> _userManager; | ||
|
||
public ConfirmEmailModel(UserManager<IdentityUser> userManager) | ||
{ | ||
_userManager = userManager; | ||
} | ||
|
||
[TempData] | ||
public string StatusMessage { get; set; } | ||
|
||
public async Task<IActionResult> OnGetAsync(string userId, string code) | ||
{ | ||
if (userId == null || code == null) | ||
{ | ||
return RedirectToPage("/Index"); | ||
} | ||
|
||
var user = await _userManager.FindByIdAsync(userId); | ||
if (user == null) | ||
{ | ||
return NotFound($"Unable to load user with ID '{userId}'."); | ||
} | ||
|
||
code = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(code)); | ||
var result = await _userManager.ConfirmEmailAsync(user, code); | ||
StatusMessage = result.Succeeded ? "Thank you for confirming your email." : "Error confirming your email."; | ||
return Page(); | ||
} | ||
} | ||
} |
8 changes: 8 additions & 0 deletions
8
IdentityManager/Areas/Identity/Pages/Account/ConfirmEmailChange.cshtml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
@page | ||
@model ConfirmEmailChangeModel | ||
@{ | ||
ViewData["Title"] = "Confirm email change"; | ||
} | ||
|
||
<h1>@ViewData["Title"]</h1> | ||
<partial name="_StatusMessage" model="Model.StatusMessage" /> |
64 changes: 64 additions & 0 deletions
64
IdentityManager/Areas/Identity/Pages/Account/ConfirmEmailChange.cshtml.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using Microsoft.AspNetCore.Authorization; | ||
using Microsoft.AspNetCore.Identity; | ||
using Microsoft.AspNetCore.Mvc; | ||
using Microsoft.AspNetCore.Mvc.RazorPages; | ||
using Microsoft.AspNetCore.WebUtilities; | ||
|
||
namespace IdentityManager.Areas.Identity.Pages.Account | ||
{ | ||
[AllowAnonymous] | ||
public class ConfirmEmailChangeModel : PageModel | ||
{ | ||
private readonly UserManager<IdentityUser> _userManager; | ||
private readonly SignInManager<IdentityUser> _signInManager; | ||
|
||
public ConfirmEmailChangeModel(UserManager<IdentityUser> userManager, SignInManager<IdentityUser> signInManager) | ||
{ | ||
_userManager = userManager; | ||
_signInManager = signInManager; | ||
} | ||
|
||
[TempData] | ||
public string StatusMessage { get; set; } | ||
|
||
public async Task<IActionResult> OnGetAsync(string userId, string email, string code) | ||
{ | ||
if (userId == null || email == null || code == null) | ||
{ | ||
return RedirectToPage("/Index"); | ||
} | ||
|
||
var user = await _userManager.FindByIdAsync(userId); | ||
if (user == null) | ||
{ | ||
return NotFound($"Unable to load user with ID '{userId}'."); | ||
} | ||
|
||
code = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(code)); | ||
var result = await _userManager.ChangeEmailAsync(user, email, code); | ||
if (!result.Succeeded) | ||
{ | ||
StatusMessage = "Error changing email."; | ||
return Page(); | ||
} | ||
|
||
// In our UI email and user name are one and the same, so when we update the email | ||
// we need to update the user name. | ||
var setUserNameResult = await _userManager.SetUserNameAsync(user, email); | ||
if (!setUserNameResult.Succeeded) | ||
{ | ||
StatusMessage = "Error changing user name."; | ||
return Page(); | ||
} | ||
|
||
await _signInManager.RefreshSignInAsync(user); | ||
StatusMessage = "Thank you for confirming your email change."; | ||
return Page(); | ||
} | ||
} | ||
} |
33 changes: 33 additions & 0 deletions
33
IdentityManager/Areas/Identity/Pages/Account/ExternalLogin.cshtml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
@page | ||
@model ExternalLoginModel | ||
@{ | ||
ViewData["Title"] = "Register"; | ||
} | ||
|
||
<h1>@ViewData["Title"]</h1> | ||
<h4 id="external-login-title">Associate your @Model.ProviderDisplayName account.</h4> | ||
<hr /> | ||
|
||
<p id="external-login-description" class="text-info"> | ||
You've successfully authenticated with <strong>@Model.ProviderDisplayName</strong>. | ||
Please enter an email address for this site below and click the Register button to finish | ||
logging in. | ||
</p> | ||
|
||
<div class="row"> | ||
<div class="col-md-4"> | ||
<form asp-page-handler="Confirmation" asp-route-returnUrl="@Model.ReturnUrl" method="post"> | ||
<div asp-validation-summary="ModelOnly" class="text-danger"></div> | ||
<div class="form-group"> | ||
<label asp-for="Input.Email"></label> | ||
<input asp-for="Input.Email" class="form-control" /> | ||
<span asp-validation-for="Input.Email" class="text-danger"></span> | ||
</div> | ||
<button type="submit" class="btn btn-primary">Register</button> | ||
</form> | ||
</div> | ||
</div> | ||
|
||
@section Scripts { | ||
<partial name="_ValidationScriptsPartial" /> | ||
} |
168 changes: 168 additions & 0 deletions
168
IdentityManager/Areas/Identity/Pages/Account/ExternalLogin.cshtml.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.ComponentModel.DataAnnotations; | ||
using System.Linq; | ||
using System.Security.Claims; | ||
using System.Text; | ||
using System.Text.Encodings.Web; | ||
using System.Threading.Tasks; | ||
using Microsoft.AspNetCore.Authorization; | ||
using Microsoft.AspNetCore.Identity; | ||
using Microsoft.AspNetCore.Identity.UI.Services; | ||
using Microsoft.AspNetCore.Mvc; | ||
using Microsoft.AspNetCore.Mvc.RazorPages; | ||
using Microsoft.AspNetCore.WebUtilities; | ||
using Microsoft.Extensions.Logging; | ||
|
||
namespace IdentityManager.Areas.Identity.Pages.Account | ||
{ | ||
[AllowAnonymous] | ||
public class ExternalLoginModel : PageModel | ||
{ | ||
private readonly SignInManager<IdentityUser> _signInManager; | ||
private readonly UserManager<IdentityUser> _userManager; | ||
private readonly IEmailSender _emailSender; | ||
private readonly ILogger<ExternalLoginModel> _logger; | ||
|
||
public ExternalLoginModel( | ||
SignInManager<IdentityUser> signInManager, | ||
UserManager<IdentityUser> userManager, | ||
ILogger<ExternalLoginModel> logger, | ||
IEmailSender emailSender) | ||
{ | ||
_signInManager = signInManager; | ||
_userManager = userManager; | ||
_logger = logger; | ||
_emailSender = emailSender; | ||
} | ||
|
||
[BindProperty] | ||
public InputModel Input { get; set; } | ||
|
||
public string ProviderDisplayName { get; set; } | ||
|
||
public string ReturnUrl { get; set; } | ||
|
||
[TempData] | ||
public string ErrorMessage { get; set; } | ||
|
||
public class InputModel | ||
{ | ||
[Required] | ||
[EmailAddress] | ||
public string Email { get; set; } | ||
} | ||
|
||
public IActionResult OnGetAsync() | ||
{ | ||
return RedirectToPage("./Login"); | ||
} | ||
|
||
public IActionResult OnPost(string provider, string returnUrl = null) | ||
{ | ||
// Request a redirect to the external login provider. | ||
var redirectUrl = Url.Page("./ExternalLogin", pageHandler: "Callback", values: new { returnUrl }); | ||
var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl); | ||
return new ChallengeResult(provider, properties); | ||
} | ||
|
||
public async Task<IActionResult> OnGetCallbackAsync(string returnUrl = null, string remoteError = null) | ||
{ | ||
returnUrl = returnUrl ?? Url.Content("~/"); | ||
if (remoteError != null) | ||
{ | ||
ErrorMessage = $"Error from external provider: {remoteError}"; | ||
return RedirectToPage("./Login", new {ReturnUrl = returnUrl }); | ||
} | ||
var info = await _signInManager.GetExternalLoginInfoAsync(); | ||
if (info == null) | ||
{ | ||
ErrorMessage = "Error loading external login information."; | ||
return RedirectToPage("./Login", new { ReturnUrl = returnUrl }); | ||
} | ||
|
||
// Sign in the user with this external login provider if the user already has a login. | ||
var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false, bypassTwoFactor : true); | ||
if (result.Succeeded) | ||
{ | ||
_logger.LogInformation("{Name} logged in with {LoginProvider} provider.", info.Principal.Identity.Name, info.LoginProvider); | ||
return LocalRedirect(returnUrl); | ||
} | ||
if (result.IsLockedOut) | ||
{ | ||
return RedirectToPage("./Lockout"); | ||
} | ||
else | ||
{ | ||
// If the user does not have an account, then ask the user to create an account. | ||
ReturnUrl = returnUrl; | ||
ProviderDisplayName = info.ProviderDisplayName; | ||
if (info.Principal.HasClaim(c => c.Type == ClaimTypes.Email)) | ||
{ | ||
Input = new InputModel | ||
{ | ||
Email = info.Principal.FindFirstValue(ClaimTypes.Email) | ||
}; | ||
} | ||
return Page(); | ||
} | ||
} | ||
|
||
public async Task<IActionResult> OnPostConfirmationAsync(string returnUrl = null) | ||
{ | ||
returnUrl = returnUrl ?? Url.Content("~/"); | ||
// Get the information about the user from the external login provider | ||
var info = await _signInManager.GetExternalLoginInfoAsync(); | ||
if (info == null) | ||
{ | ||
ErrorMessage = "Error loading external login information during confirmation."; | ||
return RedirectToPage("./Login", new { ReturnUrl = returnUrl }); | ||
} | ||
|
||
if (ModelState.IsValid) | ||
{ | ||
var user = new IdentityUser { UserName = Input.Email, Email = Input.Email }; | ||
|
||
var result = await _userManager.CreateAsync(user); | ||
if (result.Succeeded) | ||
{ | ||
result = await _userManager.AddLoginAsync(user, info); | ||
if (result.Succeeded) | ||
{ | ||
_logger.LogInformation("User created an account using {Name} provider.", info.LoginProvider); | ||
|
||
var userId = await _userManager.GetUserIdAsync(user); | ||
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user); | ||
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); | ||
var callbackUrl = Url.Page( | ||
"/Account/ConfirmEmail", | ||
pageHandler: null, | ||
values: new { area = "Identity", userId = userId, code = code }, | ||
protocol: Request.Scheme); | ||
|
||
await _emailSender.SendEmailAsync(Input.Email, "Confirm your email", | ||
$"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>."); | ||
|
||
// 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) | ||
{ | ||
return RedirectToPage("./RegisterConfirmation", new { Email = Input.Email }); | ||
} | ||
|
||
await _signInManager.SignInAsync(user, isPersistent: false, info.LoginProvider); | ||
|
||
return LocalRedirect(returnUrl); | ||
} | ||
} | ||
foreach (var error in result.Errors) | ||
{ | ||
ModelState.AddModelError(string.Empty, error.Description); | ||
} | ||
} | ||
|
||
ProviderDisplayName = info.ProviderDisplayName; | ||
ReturnUrl = returnUrl; | ||
return Page(); | ||
} | ||
} | ||
} |
Oops, something went wrong.