From 2ae53c2816c2762fc54eed1e9bd68816cf37052a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Chalet?= Date: Fri, 31 May 2024 16:43:24 +0200 Subject: [PATCH] Update the ASP.NET 4.8 samples to use file-scoped namespaces --- README.md | 4 +- .../Pages/Error.cshtml.cs | 31 +- samples/Fornax/Fornax.Server/About.aspx.cs | 9 +- .../Fornax.Server/About.aspx.designer.cs | 7 +- .../Account/AddPhoneNumber.aspx.cs | 29 +- .../Account/AddPhoneNumber.aspx.designer.cs | 41 +- .../Fornax.Server/Account/Confirm.aspx.cs | 39 +- .../Account/Confirm.aspx.designer.cs | 59 +- .../Fornax.Server/Account/Forgot.aspx.cs | 45 +- .../Account/Forgot.aspx.designer.cs | 95 ++- .../Fornax.Server/Account/Lockout.aspx.cs | 9 +- .../Account/Lockout.aspx.designer.cs | 9 +- .../Fornax.Server/Account/Login.aspx.cs | 81 +- .../Account/Login.aspx.designer.cs | 131 ++-- .../Fornax.Server/Account/Manage.aspx.cs | 171 ++-- .../Account/Manage.aspx.designer.cs | 77 +- .../Account/ManageLogins.aspx.cs | 83 +- .../Account/ManageLogins.aspx.designer.cs | 25 +- .../Account/ManagePassword.aspx.cs | 129 ++- .../Account/ManagePassword.aspx.designer.cs | 185 +++-- .../Account/OpenAuthProviders.ascx.cs | 49 +- .../OpenAuthProviders.ascx.designer.cs | 25 +- .../Fornax.Server/Account/Register.aspx.cs | 39 +- .../Account/Register.aspx.designer.cs | 77 +- .../Account/RegisterExternalLogin.aspx.cs | 163 ++-- .../RegisterExternalLogin.aspx.designer.cs | 25 +- .../Account/ResetPassword.aspx.cs | 53 +- .../Account/ResetPassword.aspx.designer.cs | 77 +- .../Account/ResetPasswordConfirmation.aspx.cs | 7 +- ...ResetPasswordConfirmation.aspx.designer.cs | 25 +- .../TwoFactorAuthenticationSignIn.aspx.cs | 99 ++- ...actorAuthenticationSignIn.aspx.designer.cs | 185 +++-- .../Account/VerifyPhoneNumber.aspx.cs | 55 +- .../VerifyPhoneNumber.aspx.designer.cs | 59 +- .../Fornax.Server/App_Start/BundleConfig.cs | 49 +- .../Fornax.Server/App_Start/IdentityConfig.cs | 141 ++-- .../Fornax.Server/App_Start/RouteConfig.cs | 15 +- .../Fornax.Server/Connect/Authorize.aspx.cs | 493 ++++++------ .../Connect/Authorize.aspx.designer.cs | 43 +- samples/Fornax/Fornax.Server/Contact.aspx.cs | 9 +- .../Fornax.Server/Contact.aspx.designer.cs | 7 +- samples/Fornax/Fornax.Server/Default.aspx.cs | 9 +- .../Fornax.Server/Default.aspx.designer.cs | 7 +- samples/Fornax/Fornax.Server/Global.asax.cs | 191 +++-- .../Helpers/AsyncEnumerableExtensions.cs | 33 +- samples/Fornax/Fornax.Server/Site.Master.cs | 106 ++- .../Fornax.Server/Site.Master.designer.cs | 25 +- .../Fornax.Server/Site.Mobile.Master.cs | 9 +- .../Site.Mobile.Master.designer.cs | 77 +- samples/Fornax/Fornax.Server/Startup.cs | 55 +- .../Fornax/Fornax.Server/ViewSwitcher.ascx.cs | 49 +- .../ViewSwitcher.ascx.designer.cs | 9 +- .../Mortis.Client/App_Start/BundleConfig.cs | 37 +- .../Mortis.Client/App_Start/FilterConfig.cs | 11 +- .../Mortis.Client/App_Start/RouteConfig.cs | 23 +- .../Controllers/AuthenticationController.cs | 257 +++--- .../Controllers/HomeController.cs | 43 +- samples/Mortis/Mortis.Client/Global.asax.cs | 17 +- .../Models/ApplicationDbContext.cs | 21 +- samples/Mortis/Mortis.Client/Startup.cs | 173 ++--- .../Mortis.Server/App_Start/BundleConfig.cs | 37 +- .../Mortis.Server/App_Start/FilterConfig.cs | 11 +- .../Mortis.Server/App_Start/IdentityConfig.cs | 147 ++-- .../Mortis.Server/App_Start/RouteConfig.cs | 23 +- .../Controllers/AccountController.cs | 735 +++++++++--------- .../Controllers/AuthorizationController.cs | 625 ++++++++------- .../Controllers/HomeController.cs | 31 +- .../Controllers/ManageController.cs | 567 +++++++------- .../Controllers/ResourceController.cs | 51 +- samples/Mortis/Mortis.Server/Global.asax.cs | 17 +- .../Helpers/AsyncEnumerableExtensions.cs | 33 +- .../Helpers/FormValueRequiredAttribute.cs | 47 +- .../Mortis.Server/Models/AccountViewModels.cs | 213 +++-- .../Mortis.Server/Models/IdentityModels.cs | 47 +- .../Mortis.Server/Models/ManageViewModels.cs | 135 ++-- samples/Mortis/Mortis.Server/Startup.cs | 267 ++++--- .../Authorization/AuthorizeViewModel.cs | 11 +- .../Authorization/LogoutViewModel.cs | 19 +- 78 files changed, 3522 insertions(+), 3600 deletions(-) diff --git a/README.md b/README.md index b3b4266eb..5b80448b1 100644 --- a/README.md +++ b/README.md @@ -22,8 +22,8 @@ This repository contains samples demonstrating **how to use [OpenIddict](https:/ ## OWIN/ASP.NET 4.8 samples - [Fornax](samples/Fornax): authorization code flow demo using ASP.NET Web Forms 4.8 and OWIN/Katana, with a .NET Framework 4.8 console acting as the client. - - [Mortis](samples/Mortis): authorization code flow demo, with an ASP.NET MVC 5.2 application acting as the client. - - [Kalarba](samples/Kalarba): resource owner password credentials demo using OWIN/Katana, ASP.NET Web API and the OpenIddict degraded mode. + - [Mortis](samples/Mortis): authorization code flow demo using ASP.NET MVC 5.2 and ASP.NET Web API 2.2, with an ASP.NET MVC 5.2 application acting as the client. + - [Kalarba](samples/Kalarba): resource owner password credentials demo using OWIN/Katana, ASP.NET Web API 2.2 and the OpenIddict degraded mode. ## External samples diff --git a/samples/Dantooine/Dantooine.WebAssembly.Server/Pages/Error.cshtml.cs b/samples/Dantooine/Dantooine.WebAssembly.Server/Pages/Error.cshtml.cs index 3aee6602c..9e371db66 100644 --- a/samples/Dantooine/Dantooine.WebAssembly.Server/Pages/Error.cshtml.cs +++ b/samples/Dantooine/Dantooine.WebAssembly.Server/Pages/Error.cshtml.cs @@ -3,26 +3,25 @@ using Microsoft.Extensions.Logging; using System.Diagnostics; -namespace Dantooine.WebAssembly.Server.Pages +namespace Dantooine.WebAssembly.Server.Pages; + +[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] +[IgnoreAntiforgeryToken] +public class ErrorModel : PageModel { - [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] - [IgnoreAntiforgeryToken] - public class ErrorModel : PageModel - { - public string RequestId { get; set; } + public string RequestId { get; set; } - public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); + public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); - private readonly ILogger _logger; + private readonly ILogger _logger; - public ErrorModel(ILogger logger) - { - _logger = logger; - } + public ErrorModel(ILogger logger) + { + _logger = logger; + } - public void OnGet() - { - RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; - } + public void OnGet() + { + RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; } } diff --git a/samples/Fornax/Fornax.Server/About.aspx.cs b/samples/Fornax/Fornax.Server/About.aspx.cs index 2c318c27f..b2d93e1c2 100644 --- a/samples/Fornax/Fornax.Server/About.aspx.cs +++ b/samples/Fornax/Fornax.Server/About.aspx.cs @@ -1,13 +1,12 @@ using System; using System.Web.UI; -namespace Fornax.Server +namespace Fornax.Server; + +public partial class About : Page { - public partial class About : Page + protected void Page_Load(object sender, EventArgs e) { - protected void Page_Load(object sender, EventArgs e) - { - } } } \ No newline at end of file diff --git a/samples/Fornax/Fornax.Server/About.aspx.designer.cs b/samples/Fornax/Fornax.Server/About.aspx.designer.cs index ea6488251..5216f40f5 100644 --- a/samples/Fornax/Fornax.Server/About.aspx.designer.cs +++ b/samples/Fornax/Fornax.Server/About.aspx.designer.cs @@ -8,9 +8,8 @@ //------------------------------------------------------------------------------ -namespace Fornax.Server +namespace Fornax.Server; + +public partial class About { - public partial class About - { - } } diff --git a/samples/Fornax/Fornax.Server/Account/AddPhoneNumber.aspx.cs b/samples/Fornax/Fornax.Server/Account/AddPhoneNumber.aspx.cs index 81c3ef23b..4d936231f 100644 --- a/samples/Fornax/Fornax.Server/Account/AddPhoneNumber.aspx.cs +++ b/samples/Fornax/Fornax.Server/Account/AddPhoneNumber.aspx.cs @@ -3,26 +3,25 @@ using Microsoft.AspNet.Identity; using Microsoft.AspNet.Identity.Owin; -namespace Fornax.Server.Account +namespace Fornax.Server.Account; + +public partial class AddPhoneNumber : System.Web.UI.Page { - public partial class AddPhoneNumber : System.Web.UI.Page + protected void PhoneNumber_Click(object sender, EventArgs e) { - protected void PhoneNumber_Click(object sender, EventArgs e) + var manager = Context.GetOwinContext().GetUserManager(); + var code = manager.GenerateChangePhoneNumberToken(User.Identity.GetUserId(), PhoneNumber.Text); + if (manager.SmsService != null) { - var manager = Context.GetOwinContext().GetUserManager(); - var code = manager.GenerateChangePhoneNumberToken(User.Identity.GetUserId(), PhoneNumber.Text); - if (manager.SmsService != null) + var message = new IdentityMessage { - var message = new IdentityMessage - { - Destination = PhoneNumber.Text, - Body = "Your security code is " + code - }; - - manager.SmsService.Send(message); - } + Destination = PhoneNumber.Text, + Body = "Your security code is " + code + }; - Response.Redirect("/Account/VerifyPhoneNumber?PhoneNumber=" + HttpUtility.UrlEncode(PhoneNumber.Text)); + manager.SmsService.Send(message); } + + Response.Redirect("/Account/VerifyPhoneNumber?PhoneNumber=" + HttpUtility.UrlEncode(PhoneNumber.Text)); } } \ No newline at end of file diff --git a/samples/Fornax/Fornax.Server/Account/AddPhoneNumber.aspx.designer.cs b/samples/Fornax/Fornax.Server/Account/AddPhoneNumber.aspx.designer.cs index 2c809d410..925260dd8 100644 --- a/samples/Fornax/Fornax.Server/Account/AddPhoneNumber.aspx.designer.cs +++ b/samples/Fornax/Fornax.Server/Account/AddPhoneNumber.aspx.designer.cs @@ -7,27 +7,26 @@ // //------------------------------------------------------------------------------ -namespace Fornax.Server.Account { +namespace Fornax.Server.Account; + + +public partial class AddPhoneNumber { + /// + /// ErrorMessage control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Literal ErrorMessage; - public partial class AddPhoneNumber { - - /// - /// ErrorMessage control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Literal ErrorMessage; - - /// - /// PhoneNumber control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox PhoneNumber; - } + /// + /// PhoneNumber control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox PhoneNumber; } diff --git a/samples/Fornax/Fornax.Server/Account/Confirm.aspx.cs b/samples/Fornax/Fornax.Server/Account/Confirm.aspx.cs index 6858b7d24..0f192e928 100644 --- a/samples/Fornax/Fornax.Server/Account/Confirm.aspx.cs +++ b/samples/Fornax/Fornax.Server/Account/Confirm.aspx.cs @@ -4,32 +4,31 @@ using Microsoft.AspNet.Identity; using Microsoft.AspNet.Identity.Owin; -namespace Fornax.Server.Account +namespace Fornax.Server.Account; + +public partial class Confirm : Page { - public partial class Confirm : Page + protected string StatusMessage { - protected string StatusMessage - { - get; - private set; - } + get; + private set; + } - protected void Page_Load(object sender, EventArgs e) + protected void Page_Load(object sender, EventArgs e) + { + string code = IdentityHelper.GetCodeFromRequest(Request); + string userId = IdentityHelper.GetUserIdFromRequest(Request); + if (code != null && userId != null) { - string code = IdentityHelper.GetCodeFromRequest(Request); - string userId = IdentityHelper.GetUserIdFromRequest(Request); - if (code != null && userId != null) + var manager = Context.GetOwinContext().GetUserManager(); + var result = manager.ConfirmEmail(userId, code); + if (result.Succeeded) { - var manager = Context.GetOwinContext().GetUserManager(); - var result = manager.ConfirmEmail(userId, code); - if (result.Succeeded) - { - successPanel.Visible = true; - return; - } + successPanel.Visible = true; + return; } - successPanel.Visible = false; - errorPanel.Visible = true; } + successPanel.Visible = false; + errorPanel.Visible = true; } } \ No newline at end of file diff --git a/samples/Fornax/Fornax.Server/Account/Confirm.aspx.designer.cs b/samples/Fornax/Fornax.Server/Account/Confirm.aspx.designer.cs index fc944a4dc..65d7a4661 100644 --- a/samples/Fornax/Fornax.Server/Account/Confirm.aspx.designer.cs +++ b/samples/Fornax/Fornax.Server/Account/Confirm.aspx.designer.cs @@ -7,37 +7,36 @@ // //------------------------------------------------------------------------------ -namespace Fornax.Server.Account { +namespace Fornax.Server.Account; + + +public partial class Confirm { + + /// + /// successPanel control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.PlaceHolder successPanel; + /// + /// login control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.HyperLink login; - public partial class Confirm { - - /// - /// successPanel control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.PlaceHolder successPanel; - - /// - /// login control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.HyperLink login; - - /// - /// errorPanel control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.PlaceHolder errorPanel; + /// + /// errorPanel control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.PlaceHolder errorPanel; - } } diff --git a/samples/Fornax/Fornax.Server/Account/Forgot.aspx.cs b/samples/Fornax/Fornax.Server/Account/Forgot.aspx.cs index eb48e5880..d4451d7a7 100644 --- a/samples/Fornax/Fornax.Server/Account/Forgot.aspx.cs +++ b/samples/Fornax/Fornax.Server/Account/Forgot.aspx.cs @@ -5,35 +5,34 @@ using Microsoft.AspNet.Identity.Owin; using Fornax.Server.Models; -namespace Fornax.Server.Account +namespace Fornax.Server.Account; + +public partial class ForgotPassword : Page { - public partial class ForgotPassword : Page + protected void Page_Load(object sender, EventArgs e) { - protected void Page_Load(object sender, EventArgs e) - { - } + } - protected void Forgot(object sender, EventArgs e) + protected void Forgot(object sender, EventArgs e) + { + if (IsValid) { - if (IsValid) + // Validate the user's email address + var manager = Context.GetOwinContext().GetUserManager(); + ApplicationUser user = manager.FindByName(Email.Text); + if (user == null || !manager.IsEmailConfirmed(user.Id)) { - // Validate the user's email address - var manager = Context.GetOwinContext().GetUserManager(); - ApplicationUser user = manager.FindByName(Email.Text); - if (user == null || !manager.IsEmailConfirmed(user.Id)) - { - FailureText.Text = "The user either does not exist or is not confirmed."; - ErrorMessage.Visible = true; - return; - } - // For more information on how to enable account confirmation and password reset please visit https://go.microsoft.com/fwlink/?LinkID=320771 - // Send email with the code and the redirect to reset password page - //string code = manager.GeneratePasswordResetToken(user.Id); - //string callbackUrl = IdentityHelper.GetResetPasswordRedirectUrl(code, Request); - //manager.SendEmail(user.Id, "Reset Password", "Please reset your password by clicking here."); - loginForm.Visible = false; - DisplayEmail.Visible = true; + FailureText.Text = "The user either does not exist or is not confirmed."; + ErrorMessage.Visible = true; + return; } + // For more information on how to enable account confirmation and password reset please visit https://go.microsoft.com/fwlink/?LinkID=320771 + // Send email with the code and the redirect to reset password page + //string code = manager.GeneratePasswordResetToken(user.Id); + //string callbackUrl = IdentityHelper.GetResetPasswordRedirectUrl(code, Request); + //manager.SendEmail(user.Id, "Reset Password", "Please reset your password by clicking here."); + loginForm.Visible = false; + DisplayEmail.Visible = true; } } } \ No newline at end of file diff --git a/samples/Fornax/Fornax.Server/Account/Forgot.aspx.designer.cs b/samples/Fornax/Fornax.Server/Account/Forgot.aspx.designer.cs index e63b15f39..4750a0289 100644 --- a/samples/Fornax/Fornax.Server/Account/Forgot.aspx.designer.cs +++ b/samples/Fornax/Fornax.Server/Account/Forgot.aspx.designer.cs @@ -7,54 +7,53 @@ // //------------------------------------------------------------------------------ -namespace Fornax.Server.Account { +namespace Fornax.Server.Account; + + +public partial class ForgotPassword { + + /// + /// loginForm control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.PlaceHolder loginForm; + + /// + /// ErrorMessage control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.PlaceHolder ErrorMessage; + + /// + /// FailureText control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Literal FailureText; + /// + /// Email control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox Email; - public partial class ForgotPassword { - - /// - /// loginForm control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.PlaceHolder loginForm; - - /// - /// ErrorMessage control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.PlaceHolder ErrorMessage; - - /// - /// FailureText control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Literal FailureText; - - /// - /// Email control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox Email; - - /// - /// DisplayEmail control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.PlaceHolder DisplayEmail; - } + /// + /// DisplayEmail control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.PlaceHolder DisplayEmail; } diff --git a/samples/Fornax/Fornax.Server/Account/Lockout.aspx.cs b/samples/Fornax/Fornax.Server/Account/Lockout.aspx.cs index f35b2667b..dfc7b863f 100644 --- a/samples/Fornax/Fornax.Server/Account/Lockout.aspx.cs +++ b/samples/Fornax/Fornax.Server/Account/Lockout.aspx.cs @@ -1,12 +1,11 @@ using System; -namespace Fornax.Server.Account +namespace Fornax.Server.Account; + +public partial class Lockout : System.Web.UI.Page { - public partial class Lockout : System.Web.UI.Page + protected void Page_Load(object sender, EventArgs e) { - protected void Page_Load(object sender, EventArgs e) - { - } } } \ No newline at end of file diff --git a/samples/Fornax/Fornax.Server/Account/Lockout.aspx.designer.cs b/samples/Fornax/Fornax.Server/Account/Lockout.aspx.designer.cs index 9b3e7045a..0a24b7665 100644 --- a/samples/Fornax/Fornax.Server/Account/Lockout.aspx.designer.cs +++ b/samples/Fornax/Fornax.Server/Account/Lockout.aspx.designer.cs @@ -7,11 +7,10 @@ // //------------------------------------------------------------------------------ -namespace Fornax.Server.Account -{ +namespace Fornax.Server.Account; + - public partial class Lockout - { - } +public partial class Lockout +{ } diff --git a/samples/Fornax/Fornax.Server/Account/Login.aspx.cs b/samples/Fornax/Fornax.Server/Account/Login.aspx.cs index c3c00d415..6f75950cd 100644 --- a/samples/Fornax/Fornax.Server/Account/Login.aspx.cs +++ b/samples/Fornax/Fornax.Server/Account/Login.aspx.cs @@ -3,55 +3,54 @@ using System.Web.UI; using Microsoft.AspNet.Identity.Owin; -namespace Fornax.Server.Account +namespace Fornax.Server.Account; + +public partial class Login : Page { - public partial class Login : Page + protected void Page_Load(object sender, EventArgs e) { - protected void Page_Load(object sender, EventArgs e) + RegisterHyperLink.NavigateUrl = "Register"; + // Enable this once you have account confirmation enabled for password reset functionality + //ForgotPasswordHyperLink.NavigateUrl = "Forgot"; + OpenAuthLogin.ReturnUrl = Request.QueryString["ReturnUrl"]; + var returnUrl = HttpUtility.UrlEncode(Request.QueryString["ReturnUrl"]); + if (!String.IsNullOrEmpty(returnUrl)) { - RegisterHyperLink.NavigateUrl = "Register"; - // Enable this once you have account confirmation enabled for password reset functionality - //ForgotPasswordHyperLink.NavigateUrl = "Forgot"; - OpenAuthLogin.ReturnUrl = Request.QueryString["ReturnUrl"]; - var returnUrl = HttpUtility.UrlEncode(Request.QueryString["ReturnUrl"]); - if (!String.IsNullOrEmpty(returnUrl)) - { - RegisterHyperLink.NavigateUrl += "?ReturnUrl=" + returnUrl; - } + RegisterHyperLink.NavigateUrl += "?ReturnUrl=" + returnUrl; } + } - protected void LogIn(object sender, EventArgs e) + protected void LogIn(object sender, EventArgs e) + { + if (IsValid) { - if (IsValid) - { - // Validate the user password - var manager = Context.GetOwinContext().GetUserManager(); - var signinManager = Context.GetOwinContext().GetUserManager(); + // Validate the user password + var manager = Context.GetOwinContext().GetUserManager(); + var signinManager = Context.GetOwinContext().GetUserManager(); - // This doen't count login failures towards account lockout - // To enable password failures to trigger lockout, change to shouldLockout: true - var result = signinManager.PasswordSignIn(Email.Text, Password.Text, RememberMe.Checked, shouldLockout: false); + // This doen't count login failures towards account lockout + // To enable password failures to trigger lockout, change to shouldLockout: true + var result = signinManager.PasswordSignIn(Email.Text, Password.Text, RememberMe.Checked, shouldLockout: false); - switch (result) - { - case SignInStatus.Success: - IdentityHelper.RedirectToReturnUrl(Request.QueryString["ReturnUrl"], Response); - break; - case SignInStatus.LockedOut: - Response.Redirect("/Account/Lockout"); - break; - case SignInStatus.RequiresVerification: - Response.Redirect(String.Format("/Account/TwoFactorAuthenticationSignIn?ReturnUrl={0}&RememberMe={1}", - Request.QueryString["ReturnUrl"], - RememberMe.Checked), - true); - break; - case SignInStatus.Failure: - default: - FailureText.Text = "Invalid login attempt"; - ErrorMessage.Visible = true; - break; - } + switch (result) + { + case SignInStatus.Success: + IdentityHelper.RedirectToReturnUrl(Request.QueryString["ReturnUrl"], Response); + break; + case SignInStatus.LockedOut: + Response.Redirect("/Account/Lockout"); + break; + case SignInStatus.RequiresVerification: + Response.Redirect(String.Format("/Account/TwoFactorAuthenticationSignIn?ReturnUrl={0}&RememberMe={1}", + Request.QueryString["ReturnUrl"], + RememberMe.Checked), + true); + break; + case SignInStatus.Failure: + default: + FailureText.Text = "Invalid login attempt"; + ErrorMessage.Visible = true; + break; } } } diff --git a/samples/Fornax/Fornax.Server/Account/Login.aspx.designer.cs b/samples/Fornax/Fornax.Server/Account/Login.aspx.designer.cs index 79d4a93cf..4de79f54a 100644 --- a/samples/Fornax/Fornax.Server/Account/Login.aspx.designer.cs +++ b/samples/Fornax/Fornax.Server/Account/Login.aspx.designer.cs @@ -7,72 +7,71 @@ // //------------------------------------------------------------------------------ -namespace Fornax.Server.Account { +namespace Fornax.Server.Account; + + +public partial class Login { + + /// + /// ErrorMessage control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.PlaceHolder ErrorMessage; + + /// + /// FailureText control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Literal FailureText; + + /// + /// Email control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox Email; + + /// + /// Password control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox Password; + + /// + /// RememberMe control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.CheckBox RememberMe; + /// + /// RegisterHyperLink control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.HyperLink RegisterHyperLink; - public partial class Login { - - /// - /// ErrorMessage control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.PlaceHolder ErrorMessage; - - /// - /// FailureText control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Literal FailureText; - - /// - /// Email control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox Email; - - /// - /// Password control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox Password; - - /// - /// RememberMe control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.CheckBox RememberMe; - - /// - /// RegisterHyperLink control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.HyperLink RegisterHyperLink; - - /// - /// OpenAuthLogin control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::Fornax.Server.Account.OpenAuthProviders OpenAuthLogin; - } + /// + /// OpenAuthLogin control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::Fornax.Server.Account.OpenAuthProviders OpenAuthLogin; } diff --git a/samples/Fornax/Fornax.Server/Account/Manage.aspx.cs b/samples/Fornax/Fornax.Server/Account/Manage.aspx.cs index 7d9c73e8f..c2fd76cfc 100644 --- a/samples/Fornax/Fornax.Server/Account/Manage.aspx.cs +++ b/samples/Fornax/Fornax.Server/Account/Manage.aspx.cs @@ -3,119 +3,118 @@ using Microsoft.AspNet.Identity; using Microsoft.AspNet.Identity.Owin; -namespace Fornax.Server.Account +namespace Fornax.Server.Account; + +public partial class Manage : System.Web.UI.Page { - public partial class Manage : System.Web.UI.Page + protected string SuccessMessage { - protected string SuccessMessage - { - get; - private set; - } - - private bool HasPassword(ApplicationUserManager manager) - { - return manager.HasPassword(User.Identity.GetUserId()); - } - - public bool HasPhoneNumber { get; private set; } + get; + private set; + } - public bool TwoFactorEnabled { get; private set; } + private bool HasPassword(ApplicationUserManager manager) + { + return manager.HasPassword(User.Identity.GetUserId()); + } - public bool TwoFactorBrowserRemembered { get; private set; } + public bool HasPhoneNumber { get; private set; } - public int LoginsCount { get; set; } + public bool TwoFactorEnabled { get; private set; } - protected void Page_Load() - { - var manager = Context.GetOwinContext().GetUserManager(); + public bool TwoFactorBrowserRemembered { get; private set; } - HasPhoneNumber = String.IsNullOrEmpty(manager.GetPhoneNumber(User.Identity.GetUserId())); + public int LoginsCount { get; set; } - // Enable this after setting up two-factor authentientication - //PhoneNumber.Text = manager.GetPhoneNumber(User.Identity.GetUserId()) ?? String.Empty; + protected void Page_Load() + { + var manager = Context.GetOwinContext().GetUserManager(); - TwoFactorEnabled = manager.GetTwoFactorEnabled(User.Identity.GetUserId()); + HasPhoneNumber = String.IsNullOrEmpty(manager.GetPhoneNumber(User.Identity.GetUserId())); - LoginsCount = manager.GetLogins(User.Identity.GetUserId()).Count; + // Enable this after setting up two-factor authentientication + //PhoneNumber.Text = manager.GetPhoneNumber(User.Identity.GetUserId()) ?? String.Empty; - var authenticationManager = HttpContext.Current.GetOwinContext().Authentication; + TwoFactorEnabled = manager.GetTwoFactorEnabled(User.Identity.GetUserId()); - if (!IsPostBack) - { - // Determine the sections to render - if (HasPassword(manager)) - { - ChangePassword.Visible = true; - } - else - { - CreatePassword.Visible = true; - ChangePassword.Visible = false; - } - - // Render success message - var message = Request.QueryString["m"]; - if (message != null) - { - // Strip the query string from action - Form.Action = ResolveUrl("~/Account/Manage"); - - SuccessMessage = - message == "ChangePwdSuccess" ? "Your password has been changed." - : message == "SetPwdSuccess" ? "Your password has been set." - : message == "RemoveLoginSuccess" ? "The account was removed." - : message == "AddPhoneNumberSuccess" ? "Phone number has been added" - : message == "RemovePhoneNumberSuccess" ? "Phone number was removed" - : String.Empty; - successMessage.Visible = !String.IsNullOrEmpty(SuccessMessage); - } - } - } + LoginsCount = manager.GetLogins(User.Identity.GetUserId()).Count; + var authenticationManager = HttpContext.Current.GetOwinContext().Authentication; - private void AddErrors(IdentityResult result) + if (!IsPostBack) { - foreach (var error in result.Errors) + // Determine the sections to render + if (HasPassword(manager)) { - ModelState.AddModelError("", error); + ChangePassword.Visible = true; } - } - - // Remove phonenumber from user - protected void RemovePhone_Click(object sender, EventArgs e) - { - var manager = Context.GetOwinContext().GetUserManager(); - var signInManager = Context.GetOwinContext().Get(); - var result = manager.SetPhoneNumber(User.Identity.GetUserId(), null); - if (!result.Succeeded) + else { - return; + CreatePassword.Visible = true; + ChangePassword.Visible = false; } - var user = manager.FindById(User.Identity.GetUserId()); - if (user != null) + + // Render success message + var message = Request.QueryString["m"]; + if (message != null) { - signInManager.SignIn(user, isPersistent: false, rememberBrowser: false); - Response.Redirect("/Account/Manage?m=RemovePhoneNumberSuccess"); + // Strip the query string from action + Form.Action = ResolveUrl("~/Account/Manage"); + + SuccessMessage = + message == "ChangePwdSuccess" ? "Your password has been changed." + : message == "SetPwdSuccess" ? "Your password has been set." + : message == "RemoveLoginSuccess" ? "The account was removed." + : message == "AddPhoneNumberSuccess" ? "Phone number has been added" + : message == "RemovePhoneNumberSuccess" ? "Phone number was removed" + : String.Empty; + successMessage.Visible = !String.IsNullOrEmpty(SuccessMessage); } } + } - // DisableTwoFactorAuthentication - protected void TwoFactorDisable_Click(object sender, EventArgs e) - { - var manager = Context.GetOwinContext().GetUserManager(); - manager.SetTwoFactorEnabled(User.Identity.GetUserId(), false); - Response.Redirect("/Account/Manage"); + private void AddErrors(IdentityResult result) + { + foreach (var error in result.Errors) + { + ModelState.AddModelError("", error); } + } - //EnableTwoFactorAuthentication - protected void TwoFactorEnable_Click(object sender, EventArgs e) + // Remove phonenumber from user + protected void RemovePhone_Click(object sender, EventArgs e) + { + var manager = Context.GetOwinContext().GetUserManager(); + var signInManager = Context.GetOwinContext().Get(); + var result = manager.SetPhoneNumber(User.Identity.GetUserId(), null); + if (!result.Succeeded) { - var manager = Context.GetOwinContext().GetUserManager(); - manager.SetTwoFactorEnabled(User.Identity.GetUserId(), true); - - Response.Redirect("/Account/Manage"); + return; + } + var user = manager.FindById(User.Identity.GetUserId()); + if (user != null) + { + signInManager.SignIn(user, isPersistent: false, rememberBrowser: false); + Response.Redirect("/Account/Manage?m=RemovePhoneNumberSuccess"); } } + + // DisableTwoFactorAuthentication + protected void TwoFactorDisable_Click(object sender, EventArgs e) + { + var manager = Context.GetOwinContext().GetUserManager(); + manager.SetTwoFactorEnabled(User.Identity.GetUserId(), false); + + Response.Redirect("/Account/Manage"); + } + + //EnableTwoFactorAuthentication + protected void TwoFactorEnable_Click(object sender, EventArgs e) + { + var manager = Context.GetOwinContext().GetUserManager(); + manager.SetTwoFactorEnabled(User.Identity.GetUserId(), true); + + Response.Redirect("/Account/Manage"); + } } \ No newline at end of file diff --git a/samples/Fornax/Fornax.Server/Account/Manage.aspx.designer.cs b/samples/Fornax/Fornax.Server/Account/Manage.aspx.designer.cs index 2c3215fca..8bd904afb 100644 --- a/samples/Fornax/Fornax.Server/Account/Manage.aspx.designer.cs +++ b/samples/Fornax/Fornax.Server/Account/Manage.aspx.designer.cs @@ -7,45 +7,44 @@ // //------------------------------------------------------------------------------ -namespace Fornax.Server.Account { +namespace Fornax.Server.Account; + + +public partial class Manage { + + /// + /// successMessage control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.PlaceHolder successMessage; + + /// + /// ChangePassword control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.HyperLink ChangePassword; + /// + /// CreatePassword control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.HyperLink CreatePassword; - public partial class Manage { - - /// - /// successMessage control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.PlaceHolder successMessage; - - /// - /// ChangePassword control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.HyperLink ChangePassword; - - /// - /// CreatePassword control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.HyperLink CreatePassword; - - /// - /// PhoneNumber control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Label PhoneNumber; - } + /// + /// PhoneNumber control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Label PhoneNumber; } diff --git a/samples/Fornax/Fornax.Server/Account/ManageLogins.aspx.cs b/samples/Fornax/Fornax.Server/Account/ManageLogins.aspx.cs index 6d4e40f59..039b922c4 100644 --- a/samples/Fornax/Fornax.Server/Account/ManageLogins.aspx.cs +++ b/samples/Fornax/Fornax.Server/Account/ManageLogins.aspx.cs @@ -5,56 +5,55 @@ using Microsoft.AspNet.Identity; using Microsoft.AspNet.Identity.Owin; -namespace Fornax.Server.Account +namespace Fornax.Server.Account; + +public partial class ManageLogins : System.Web.UI.Page { - public partial class ManageLogins : System.Web.UI.Page + protected string SuccessMessage { - protected string SuccessMessage - { - get; - private set; - } - protected bool CanRemoveExternalLogins - { - get; - private set; - } + get; + private set; + } + protected bool CanRemoveExternalLogins + { + get; + private set; + } - private bool HasPassword(ApplicationUserManager manager) - { - return manager.HasPassword(User.Identity.GetUserId()); - } + private bool HasPassword(ApplicationUserManager manager) + { + return manager.HasPassword(User.Identity.GetUserId()); + } - protected void Page_Load(object sender, EventArgs e) - { - var manager = Context.GetOwinContext().GetUserManager(); - CanRemoveExternalLogins = manager.GetLogins(User.Identity.GetUserId()).Count() > 1; + protected void Page_Load(object sender, EventArgs e) + { + var manager = Context.GetOwinContext().GetUserManager(); + CanRemoveExternalLogins = manager.GetLogins(User.Identity.GetUserId()).Count() > 1; - SuccessMessage = String.Empty; - successMessage.Visible = !String.IsNullOrEmpty(SuccessMessage); - } + SuccessMessage = String.Empty; + successMessage.Visible = !String.IsNullOrEmpty(SuccessMessage); + } - public IEnumerable GetLogins() - { - var manager = Context.GetOwinContext().GetUserManager(); - var accounts = manager.GetLogins(User.Identity.GetUserId()); - CanRemoveExternalLogins = accounts.Count() > 1 || HasPassword(manager); - return accounts; - } + public IEnumerable GetLogins() + { + var manager = Context.GetOwinContext().GetUserManager(); + var accounts = manager.GetLogins(User.Identity.GetUserId()); + CanRemoveExternalLogins = accounts.Count() > 1 || HasPassword(manager); + return accounts; + } - public void RemoveLogin(string loginProvider, string providerKey) + public void RemoveLogin(string loginProvider, string providerKey) + { + var manager = Context.GetOwinContext().GetUserManager(); + var signInManager = Context.GetOwinContext().Get(); + var result = manager.RemoveLogin(User.Identity.GetUserId(), new UserLoginInfo(loginProvider, providerKey)); + string msg = String.Empty; + if (result.Succeeded) { - var manager = Context.GetOwinContext().GetUserManager(); - var signInManager = Context.GetOwinContext().Get(); - var result = manager.RemoveLogin(User.Identity.GetUserId(), new UserLoginInfo(loginProvider, providerKey)); - string msg = String.Empty; - if (result.Succeeded) - { - var user = manager.FindById(User.Identity.GetUserId()); - signInManager.SignIn(user, isPersistent: false, rememberBrowser: false); - msg = "?m=RemoveLoginSuccess"; - } - Response.Redirect("~/Account/ManageLogins" + msg); + var user = manager.FindById(User.Identity.GetUserId()); + signInManager.SignIn(user, isPersistent: false, rememberBrowser: false); + msg = "?m=RemoveLoginSuccess"; } + Response.Redirect("~/Account/ManageLogins" + msg); } } \ No newline at end of file diff --git a/samples/Fornax/Fornax.Server/Account/ManageLogins.aspx.designer.cs b/samples/Fornax/Fornax.Server/Account/ManageLogins.aspx.designer.cs index c1953e4f2..c84202e61 100644 --- a/samples/Fornax/Fornax.Server/Account/ManageLogins.aspx.designer.cs +++ b/samples/Fornax/Fornax.Server/Account/ManageLogins.aspx.designer.cs @@ -7,18 +7,17 @@ // //------------------------------------------------------------------------------ -namespace Fornax.Server.Account { - +namespace Fornax.Server.Account; + + +public partial class ManageLogins { - public partial class ManageLogins { - - /// - /// successMessage control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.PlaceHolder successMessage; - } + /// + /// successMessage control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.PlaceHolder successMessage; } diff --git a/samples/Fornax/Fornax.Server/Account/ManagePassword.aspx.cs b/samples/Fornax/Fornax.Server/Account/ManagePassword.aspx.cs index 5222c0bc9..df6a4a48b 100644 --- a/samples/Fornax/Fornax.Server/Account/ManagePassword.aspx.cs +++ b/samples/Fornax/Fornax.Server/Account/ManagePassword.aspx.cs @@ -3,92 +3,91 @@ using Microsoft.AspNet.Identity; using Microsoft.AspNet.Identity.Owin; -namespace Fornax.Server.Account +namespace Fornax.Server.Account; + +public partial class ManagePassword : System.Web.UI.Page { - public partial class ManagePassword : System.Web.UI.Page + protected string SuccessMessage { - protected string SuccessMessage - { - get; - private set; - } + get; + private set; + } - private bool HasPassword(ApplicationUserManager manager) - { - return manager.HasPassword(User.Identity.GetUserId()); - } + private bool HasPassword(ApplicationUserManager manager) + { + return manager.HasPassword(User.Identity.GetUserId()); + } - protected void Page_Load(object sender, EventArgs e) - { - var manager = Context.GetOwinContext().GetUserManager(); + protected void Page_Load(object sender, EventArgs e) + { + var manager = Context.GetOwinContext().GetUserManager(); - if (!IsPostBack) + if (!IsPostBack) + { + // Determine the sections to render + if (HasPassword(manager)) { - // Determine the sections to render - if (HasPassword(manager)) - { - changePasswordHolder.Visible = true; - } - else - { - setPassword.Visible = true; - changePasswordHolder.Visible = false; - } + changePasswordHolder.Visible = true; + } + else + { + setPassword.Visible = true; + changePasswordHolder.Visible = false; + } - // Render success message - var message = Request.QueryString["m"]; - if (message != null) - { - // Strip the query string from action - Form.Action = ResolveUrl("~/Account/Manage"); - } + // Render success message + var message = Request.QueryString["m"]; + if (message != null) + { + // Strip the query string from action + Form.Action = ResolveUrl("~/Account/Manage"); } } + } - protected void ChangePassword_Click(object sender, EventArgs e) + protected void ChangePassword_Click(object sender, EventArgs e) + { + if (IsValid) { - if (IsValid) + var manager = Context.GetOwinContext().GetUserManager(); + var signInManager = Context.GetOwinContext().Get(); + IdentityResult result = manager.ChangePassword(User.Identity.GetUserId(), CurrentPassword.Text, NewPassword.Text); + if (result.Succeeded) { - var manager = Context.GetOwinContext().GetUserManager(); - var signInManager = Context.GetOwinContext().Get(); - IdentityResult result = manager.ChangePassword(User.Identity.GetUserId(), CurrentPassword.Text, NewPassword.Text); - if (result.Succeeded) - { - var user = manager.FindById(User.Identity.GetUserId()); - signInManager.SignIn( user, isPersistent: false, rememberBrowser: false); - Response.Redirect("~/Account/Manage?m=ChangePwdSuccess"); - } - else - { - AddErrors(result); - } + var user = manager.FindById(User.Identity.GetUserId()); + signInManager.SignIn( user, isPersistent: false, rememberBrowser: false); + Response.Redirect("~/Account/Manage?m=ChangePwdSuccess"); + } + else + { + AddErrors(result); } } + } - protected void SetPassword_Click(object sender, EventArgs e) + protected void SetPassword_Click(object sender, EventArgs e) + { + if (IsValid) { - if (IsValid) + // Create the local login info and link the local account to the user + var manager = Context.GetOwinContext().GetUserManager(); + IdentityResult result = manager.AddPassword(User.Identity.GetUserId(), password.Text); + if (result.Succeeded) + { + Response.Redirect("~/Account/Manage?m=SetPwdSuccess"); + } + else { - // Create the local login info and link the local account to the user - var manager = Context.GetOwinContext().GetUserManager(); - IdentityResult result = manager.AddPassword(User.Identity.GetUserId(), password.Text); - if (result.Succeeded) - { - Response.Redirect("~/Account/Manage?m=SetPwdSuccess"); - } - else - { - AddErrors(result); - } + AddErrors(result); } } + } - private void AddErrors(IdentityResult result) + private void AddErrors(IdentityResult result) + { + foreach (var error in result.Errors) { - foreach (var error in result.Errors) - { - ModelState.AddModelError("", error); - } + ModelState.AddModelError("", error); } } } \ No newline at end of file diff --git a/samples/Fornax/Fornax.Server/Account/ManagePassword.aspx.designer.cs b/samples/Fornax/Fornax.Server/Account/ManagePassword.aspx.designer.cs index 99a152d88..71807c36e 100644 --- a/samples/Fornax/Fornax.Server/Account/ManagePassword.aspx.designer.cs +++ b/samples/Fornax/Fornax.Server/Account/ManagePassword.aspx.designer.cs @@ -7,99 +7,98 @@ // //------------------------------------------------------------------------------ -namespace Fornax.Server.Account { +namespace Fornax.Server.Account; + + +public partial class ManagePassword { + + /// + /// setPassword control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.PlaceHolder setPassword; + + /// + /// password control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox password; + + /// + /// confirmPassword control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox confirmPassword; + + /// + /// changePasswordHolder control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.PlaceHolder changePasswordHolder; + + /// + /// CurrentPasswordLabel control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Label CurrentPasswordLabel; + + /// + /// CurrentPassword control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox CurrentPassword; + + /// + /// NewPasswordLabel control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Label NewPasswordLabel; + + /// + /// NewPassword control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox NewPassword; + /// + /// ConfirmNewPasswordLabel control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Label ConfirmNewPasswordLabel; - public partial class ManagePassword { - - /// - /// setPassword control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.PlaceHolder setPassword; - - /// - /// password control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox password; - - /// - /// confirmPassword control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox confirmPassword; - - /// - /// changePasswordHolder control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.PlaceHolder changePasswordHolder; - - /// - /// CurrentPasswordLabel control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Label CurrentPasswordLabel; - - /// - /// CurrentPassword control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox CurrentPassword; - - /// - /// NewPasswordLabel control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Label NewPasswordLabel; - - /// - /// NewPassword control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox NewPassword; - - /// - /// ConfirmNewPasswordLabel control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Label ConfirmNewPasswordLabel; - - /// - /// ConfirmNewPassword control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox ConfirmNewPassword; - } + /// + /// ConfirmNewPassword control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox ConfirmNewPassword; } diff --git a/samples/Fornax/Fornax.Server/Account/OpenAuthProviders.ascx.cs b/samples/Fornax/Fornax.Server/Account/OpenAuthProviders.ascx.cs index 639228ebe..dbd46c0de 100644 --- a/samples/Fornax/Fornax.Server/Account/OpenAuthProviders.ascx.cs +++ b/samples/Fornax/Fornax.Server/Account/OpenAuthProviders.ascx.cs @@ -6,38 +6,37 @@ using Microsoft.AspNet.Identity; using Microsoft.Owin.Security; -namespace Fornax.Server.Account +namespace Fornax.Server.Account; + +public partial class OpenAuthProviders : System.Web.UI.UserControl { - public partial class OpenAuthProviders : System.Web.UI.UserControl + protected void Page_Load(object sender, EventArgs e) { - protected void Page_Load(object sender, EventArgs e) + if (IsPostBack) { - if (IsPostBack) + var provider = Request.Form["provider"]; + if (provider == null) + { + return; + } + // Request a redirect to the external login provider + string redirectUrl = ResolveUrl(String.Format(CultureInfo.InvariantCulture, "~/Account/RegisterExternalLogin?{0}={1}&returnUrl={2}", IdentityHelper.ProviderNameKey, provider, ReturnUrl)); + var properties = new AuthenticationProperties() { RedirectUri = redirectUrl }; + // Add xsrf verification when linking accounts + if (Context.User.Identity.IsAuthenticated) { - var provider = Request.Form["provider"]; - if (provider == null) - { - return; - } - // Request a redirect to the external login provider - string redirectUrl = ResolveUrl(String.Format(CultureInfo.InvariantCulture, "~/Account/RegisterExternalLogin?{0}={1}&returnUrl={2}", IdentityHelper.ProviderNameKey, provider, ReturnUrl)); - var properties = new AuthenticationProperties() { RedirectUri = redirectUrl }; - // Add xsrf verification when linking accounts - if (Context.User.Identity.IsAuthenticated) - { - properties.Dictionary[IdentityHelper.XsrfKey] = Context.User.Identity.GetUserId(); - } - Context.GetOwinContext().Authentication.Challenge(properties, provider); - Response.StatusCode = 401; - Response.End(); + properties.Dictionary[IdentityHelper.XsrfKey] = Context.User.Identity.GetUserId(); } + Context.GetOwinContext().Authentication.Challenge(properties, provider); + Response.StatusCode = 401; + Response.End(); } + } - public string ReturnUrl { get; set; } + public string ReturnUrl { get; set; } - public IEnumerable GetProviderNames() - { - return Context.GetOwinContext().Authentication.GetExternalAuthenticationTypes().Select(t => t.AuthenticationType); - } + public IEnumerable GetProviderNames() + { + return Context.GetOwinContext().Authentication.GetExternalAuthenticationTypes().Select(t => t.AuthenticationType); } } \ No newline at end of file diff --git a/samples/Fornax/Fornax.Server/Account/OpenAuthProviders.ascx.designer.cs b/samples/Fornax/Fornax.Server/Account/OpenAuthProviders.ascx.designer.cs index 1130dfc0d..0c967fb77 100644 --- a/samples/Fornax/Fornax.Server/Account/OpenAuthProviders.ascx.designer.cs +++ b/samples/Fornax/Fornax.Server/Account/OpenAuthProviders.ascx.designer.cs @@ -7,18 +7,17 @@ // //------------------------------------------------------------------------------ -namespace Fornax.Server.Account { - +namespace Fornax.Server.Account; + + +public partial class OpenAuthProviders { - public partial class OpenAuthProviders { - - /// - /// providerDetails control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.ListView providerDetails; - } + /// + /// providerDetails control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.ListView providerDetails; } diff --git a/samples/Fornax/Fornax.Server/Account/Register.aspx.cs b/samples/Fornax/Fornax.Server/Account/Register.aspx.cs index 99f46f581..45f59bce7 100644 --- a/samples/Fornax/Fornax.Server/Account/Register.aspx.cs +++ b/samples/Fornax/Fornax.Server/Account/Register.aspx.cs @@ -6,30 +6,29 @@ using Microsoft.AspNet.Identity.Owin; using Fornax.Server.Models; -namespace Fornax.Server.Account +namespace Fornax.Server.Account; + +public partial class Register : Page { - public partial class Register : Page + protected void CreateUser_Click(object sender, EventArgs e) { - protected void CreateUser_Click(object sender, EventArgs e) + var manager = Context.GetOwinContext().GetUserManager(); + var signInManager = Context.GetOwinContext().Get(); + var user = new ApplicationUser() { UserName = Email.Text, Email = Email.Text }; + IdentityResult result = manager.Create(user, Password.Text); + if (result.Succeeded) { - var manager = Context.GetOwinContext().GetUserManager(); - var signInManager = Context.GetOwinContext().Get(); - var user = new ApplicationUser() { UserName = Email.Text, Email = Email.Text }; - IdentityResult result = manager.Create(user, Password.Text); - if (result.Succeeded) - { - // For more information on how to enable account confirmation and password reset please visit https://go.microsoft.com/fwlink/?LinkID=320771 - //string code = manager.GenerateEmailConfirmationToken(user.Id); - //string callbackUrl = IdentityHelper.GetUserConfirmationRedirectUrl(code, user.Id, Request); - //manager.SendEmail(user.Id, "Confirm your account", "Please confirm your account by clicking here."); + // For more information on how to enable account confirmation and password reset please visit https://go.microsoft.com/fwlink/?LinkID=320771 + //string code = manager.GenerateEmailConfirmationToken(user.Id); + //string callbackUrl = IdentityHelper.GetUserConfirmationRedirectUrl(code, user.Id, Request); + //manager.SendEmail(user.Id, "Confirm your account", "Please confirm your account by clicking here."); - signInManager.SignIn( user, isPersistent: false, rememberBrowser: false); - IdentityHelper.RedirectToReturnUrl(Request.QueryString["ReturnUrl"], Response); - } - else - { - ErrorMessage.Text = result.Errors.FirstOrDefault(); - } + signInManager.SignIn( user, isPersistent: false, rememberBrowser: false); + IdentityHelper.RedirectToReturnUrl(Request.QueryString["ReturnUrl"], Response); + } + else + { + ErrorMessage.Text = result.Errors.FirstOrDefault(); } } } \ No newline at end of file diff --git a/samples/Fornax/Fornax.Server/Account/Register.aspx.designer.cs b/samples/Fornax/Fornax.Server/Account/Register.aspx.designer.cs index 80ef9d7c5..4373d98c5 100644 --- a/samples/Fornax/Fornax.Server/Account/Register.aspx.designer.cs +++ b/samples/Fornax/Fornax.Server/Account/Register.aspx.designer.cs @@ -7,45 +7,44 @@ // //------------------------------------------------------------------------------ -namespace Fornax.Server.Account { +namespace Fornax.Server.Account; + + +public partial class Register { + + /// + /// ErrorMessage control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Literal ErrorMessage; + + /// + /// Email control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox Email; + /// + /// Password control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox Password; - public partial class Register { - - /// - /// ErrorMessage control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Literal ErrorMessage; - - /// - /// Email control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox Email; - - /// - /// Password control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox Password; - - /// - /// ConfirmPassword control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox ConfirmPassword; - } + /// + /// ConfirmPassword control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox ConfirmPassword; } diff --git a/samples/Fornax/Fornax.Server/Account/RegisterExternalLogin.aspx.cs b/samples/Fornax/Fornax.Server/Account/RegisterExternalLogin.aspx.cs index 488bf270c..b919ac41c 100644 --- a/samples/Fornax/Fornax.Server/Account/RegisterExternalLogin.aspx.cs +++ b/samples/Fornax/Fornax.Server/Account/RegisterExternalLogin.aspx.cs @@ -5,125 +5,124 @@ using Microsoft.Owin.Security; using Fornax.Server.Models; -namespace Fornax.Server.Account +namespace Fornax.Server.Account; + +public partial class RegisterExternalLogin : System.Web.UI.Page { - public partial class RegisterExternalLogin : System.Web.UI.Page + protected string ProviderName { - protected string ProviderName - { - get { return (string)ViewState["ProviderName"] ?? String.Empty; } - private set { ViewState["ProviderName"] = value; } - } + get { return (string)ViewState["ProviderName"] ?? String.Empty; } + private set { ViewState["ProviderName"] = value; } + } - protected string ProviderAccountKey - { - get { return (string)ViewState["ProviderAccountKey"] ?? String.Empty; } - private set { ViewState["ProviderAccountKey"] = value; } - } + protected string ProviderAccountKey + { + get { return (string)ViewState["ProviderAccountKey"] ?? String.Empty; } + private set { ViewState["ProviderAccountKey"] = value; } + } + + private void RedirectOnFail() + { + Response.Redirect((User.Identity.IsAuthenticated) ? "~/Account/Manage" : "~/Account/Login"); + } - private void RedirectOnFail() + protected void Page_Load() + { + // Process the result from an auth provider in the request + ProviderName = IdentityHelper.GetProviderNameFromRequest(Request); + if (String.IsNullOrEmpty(ProviderName)) { - Response.Redirect((User.Identity.IsAuthenticated) ? "~/Account/Manage" : "~/Account/Login"); + RedirectOnFail(); + return; } - - protected void Page_Load() + if (!IsPostBack) { - // Process the result from an auth provider in the request - ProviderName = IdentityHelper.GetProviderNameFromRequest(Request); - if (String.IsNullOrEmpty(ProviderName)) + var manager = Context.GetOwinContext().GetUserManager(); + var signInManager = Context.GetOwinContext().Get(); + var loginInfo = Context.GetOwinContext().Authentication.GetExternalLoginInfo(); + if (loginInfo == null) { RedirectOnFail(); return; } - if (!IsPostBack) + var user = manager.Find(loginInfo.Login); + if (user != null) + { + signInManager.SignIn(user, isPersistent: false, rememberBrowser: false); + IdentityHelper.RedirectToReturnUrl(Request.QueryString["ReturnUrl"], Response); + } + else if (User.Identity.IsAuthenticated) { - var manager = Context.GetOwinContext().GetUserManager(); - var signInManager = Context.GetOwinContext().Get(); - var loginInfo = Context.GetOwinContext().Authentication.GetExternalLoginInfo(); - if (loginInfo == null) + // Apply Xsrf check when linking + var verifiedloginInfo = Context.GetOwinContext().Authentication.GetExternalLoginInfo(IdentityHelper.XsrfKey, User.Identity.GetUserId()); + if (verifiedloginInfo == null) { RedirectOnFail(); return; } - var user = manager.Find(loginInfo.Login); - if (user != null) + + var result = manager.AddLogin(User.Identity.GetUserId(), verifiedloginInfo.Login); + if (result.Succeeded) { - signInManager.SignIn(user, isPersistent: false, rememberBrowser: false); IdentityHelper.RedirectToReturnUrl(Request.QueryString["ReturnUrl"], Response); } - else if (User.Identity.IsAuthenticated) - { - // Apply Xsrf check when linking - var verifiedloginInfo = Context.GetOwinContext().Authentication.GetExternalLoginInfo(IdentityHelper.XsrfKey, User.Identity.GetUserId()); - if (verifiedloginInfo == null) - { - RedirectOnFail(); - return; - } - - var result = manager.AddLogin(User.Identity.GetUserId(), verifiedloginInfo.Login); - if (result.Succeeded) - { - IdentityHelper.RedirectToReturnUrl(Request.QueryString["ReturnUrl"], Response); - } - else - { - AddErrors(result); - return; - } - } else { - email.Text = loginInfo.Email; + AddErrors(result); + return; } } - } - - protected void LogIn_Click(object sender, EventArgs e) - { - CreateAndLoginUser(); + else + { + email.Text = loginInfo.Email; + } } + } + + protected void LogIn_Click(object sender, EventArgs e) + { + CreateAndLoginUser(); + } - private void CreateAndLoginUser() + private void CreateAndLoginUser() + { + if (!IsValid) + { + return; + } + var manager = Context.GetOwinContext().GetUserManager(); + var signInManager = Context.GetOwinContext().GetUserManager(); + var user = new ApplicationUser() { UserName = email.Text, Email = email.Text }; + IdentityResult result = manager.Create(user); + if (result.Succeeded) { - if (!IsValid) + var loginInfo = Context.GetOwinContext().Authentication.GetExternalLoginInfo(); + if (loginInfo == null) { + RedirectOnFail(); return; } - var manager = Context.GetOwinContext().GetUserManager(); - var signInManager = Context.GetOwinContext().GetUserManager(); - var user = new ApplicationUser() { UserName = email.Text, Email = email.Text }; - IdentityResult result = manager.Create(user); + result = manager.AddLogin(user.Id, loginInfo.Login); if (result.Succeeded) { - var loginInfo = Context.GetOwinContext().Authentication.GetExternalLoginInfo(); - if (loginInfo == null) - { - RedirectOnFail(); - return; - } - result = manager.AddLogin(user.Id, loginInfo.Login); - if (result.Succeeded) - { - signInManager.SignIn(user, isPersistent: false, rememberBrowser: false); + signInManager.SignIn(user, isPersistent: false, rememberBrowser: false); - // For more information on how to enable account confirmation and password reset please visit https://go.microsoft.com/fwlink/?LinkID=320771 - // var code = manager.GenerateEmailConfirmationToken(user.Id); - // Send this link via email: IdentityHelper.GetUserConfirmationRedirectUrl(code, user.Id) + // For more information on how to enable account confirmation and password reset please visit https://go.microsoft.com/fwlink/?LinkID=320771 + // var code = manager.GenerateEmailConfirmationToken(user.Id); + // Send this link via email: IdentityHelper.GetUserConfirmationRedirectUrl(code, user.Id) - IdentityHelper.RedirectToReturnUrl(Request.QueryString["ReturnUrl"], Response); - return; - } + IdentityHelper.RedirectToReturnUrl(Request.QueryString["ReturnUrl"], Response); + return; } - AddErrors(result); } + AddErrors(result); + } - private void AddErrors(IdentityResult result) + private void AddErrors(IdentityResult result) + { + foreach (var error in result.Errors) { - foreach (var error in result.Errors) - { - ModelState.AddModelError("", error); - } + ModelState.AddModelError("", error); } } } \ No newline at end of file diff --git a/samples/Fornax/Fornax.Server/Account/RegisterExternalLogin.aspx.designer.cs b/samples/Fornax/Fornax.Server/Account/RegisterExternalLogin.aspx.designer.cs index 58f60ff43..c589836df 100644 --- a/samples/Fornax/Fornax.Server/Account/RegisterExternalLogin.aspx.designer.cs +++ b/samples/Fornax/Fornax.Server/Account/RegisterExternalLogin.aspx.designer.cs @@ -7,18 +7,17 @@ // //------------------------------------------------------------------------------ -namespace Fornax.Server.Account { - +namespace Fornax.Server.Account; + + +public partial class RegisterExternalLogin { - public partial class RegisterExternalLogin { - - /// - /// email control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox email; - } + /// + /// email control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox email; } diff --git a/samples/Fornax/Fornax.Server/Account/ResetPassword.aspx.cs b/samples/Fornax/Fornax.Server/Account/ResetPassword.aspx.cs index c71b2447f..c43766129 100644 --- a/samples/Fornax/Fornax.Server/Account/ResetPassword.aspx.cs +++ b/samples/Fornax/Fornax.Server/Account/ResetPassword.aspx.cs @@ -5,40 +5,39 @@ using Microsoft.AspNet.Identity; using Microsoft.AspNet.Identity.Owin; -namespace Fornax.Server.Account +namespace Fornax.Server.Account; + +public partial class ResetPassword : Page { - public partial class ResetPassword : Page + protected string StatusMessage { - protected string StatusMessage - { - get; - private set; - } + get; + private set; + } - protected void Reset_Click(object sender, EventArgs e) + protected void Reset_Click(object sender, EventArgs e) + { + string code = IdentityHelper.GetCodeFromRequest(Request); + if (code != null) { - string code = IdentityHelper.GetCodeFromRequest(Request); - if (code != null) - { - var manager = Context.GetOwinContext().GetUserManager(); + var manager = Context.GetOwinContext().GetUserManager(); - var user = manager.FindByName(Email.Text); - if (user == null) - { - ErrorMessage.Text = "No user found"; - return; - } - var result = manager.ResetPassword(user.Id, code, Password.Text); - if (result.Succeeded) - { - Response.Redirect("~/Account/ResetPasswordConfirmation"); - return; - } - ErrorMessage.Text = result.Errors.FirstOrDefault(); + var user = manager.FindByName(Email.Text); + if (user == null) + { + ErrorMessage.Text = "No user found"; return; } - - ErrorMessage.Text = "An error has occurred"; + var result = manager.ResetPassword(user.Id, code, Password.Text); + if (result.Succeeded) + { + Response.Redirect("~/Account/ResetPasswordConfirmation"); + return; + } + ErrorMessage.Text = result.Errors.FirstOrDefault(); + return; } + + ErrorMessage.Text = "An error has occurred"; } } \ No newline at end of file diff --git a/samples/Fornax/Fornax.Server/Account/ResetPassword.aspx.designer.cs b/samples/Fornax/Fornax.Server/Account/ResetPassword.aspx.designer.cs index afd56b929..871a9b2fa 100644 --- a/samples/Fornax/Fornax.Server/Account/ResetPassword.aspx.designer.cs +++ b/samples/Fornax/Fornax.Server/Account/ResetPassword.aspx.designer.cs @@ -7,45 +7,44 @@ // //------------------------------------------------------------------------------ -namespace Fornax.Server.Account { +namespace Fornax.Server.Account; + + +public partial class ResetPassword { + + /// + /// ErrorMessage control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Literal ErrorMessage; + + /// + /// Email control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox Email; + /// + /// Password control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox Password; - public partial class ResetPassword { - - /// - /// ErrorMessage control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Literal ErrorMessage; - - /// - /// Email control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox Email; - - /// - /// Password control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox Password; - - /// - /// ConfirmPassword control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox ConfirmPassword; - } + /// + /// ConfirmPassword control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox ConfirmPassword; } diff --git a/samples/Fornax/Fornax.Server/Account/ResetPasswordConfirmation.aspx.cs b/samples/Fornax/Fornax.Server/Account/ResetPasswordConfirmation.aspx.cs index 1c0ee92c1..4bfef426f 100644 --- a/samples/Fornax/Fornax.Server/Account/ResetPasswordConfirmation.aspx.cs +++ b/samples/Fornax/Fornax.Server/Account/ResetPasswordConfirmation.aspx.cs @@ -1,8 +1,7 @@ using System.Web.UI; -namespace Fornax.Server.Account +namespace Fornax.Server.Account; + +public partial class ResetPasswordConfirmation : Page { - public partial class ResetPasswordConfirmation : Page - { - } } \ No newline at end of file diff --git a/samples/Fornax/Fornax.Server/Account/ResetPasswordConfirmation.aspx.designer.cs b/samples/Fornax/Fornax.Server/Account/ResetPasswordConfirmation.aspx.designer.cs index e9f0842b0..7df69152b 100644 --- a/samples/Fornax/Fornax.Server/Account/ResetPasswordConfirmation.aspx.designer.cs +++ b/samples/Fornax/Fornax.Server/Account/ResetPasswordConfirmation.aspx.designer.cs @@ -7,18 +7,17 @@ // //------------------------------------------------------------------------------ -namespace Fornax.Server.Account { - - - public partial class ResetPasswordConfirmation { +namespace Fornax.Server.Account; - /// - /// login control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.HyperLink login; - } + +public partial class ResetPasswordConfirmation { + + /// + /// login control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.HyperLink login; } diff --git a/samples/Fornax/Fornax.Server/Account/TwoFactorAuthenticationSignIn.aspx.cs b/samples/Fornax/Fornax.Server/Account/TwoFactorAuthenticationSignIn.aspx.cs index a7070f943..6237a9cf8 100644 --- a/samples/Fornax/Fornax.Server/Account/TwoFactorAuthenticationSignIn.aspx.cs +++ b/samples/Fornax/Fornax.Server/Account/TwoFactorAuthenticationSignIn.aspx.cs @@ -6,69 +6,68 @@ using Microsoft.AspNet.Identity.Owin; using Fornax.Server.Models; -namespace Fornax.Server.Account +namespace Fornax.Server.Account; + +public partial class TwoFactorAuthenticationSignIn : System.Web.UI.Page { - public partial class TwoFactorAuthenticationSignIn : System.Web.UI.Page + private ApplicationSignInManager signinManager; + private ApplicationUserManager manager; + + public TwoFactorAuthenticationSignIn() { - private ApplicationSignInManager signinManager; - private ApplicationUserManager manager; + manager = Context.GetOwinContext().GetUserManager(); + signinManager = Context.GetOwinContext().GetUserManager(); + } - public TwoFactorAuthenticationSignIn() + protected void Page_Load(object sender, EventArgs e) + { + var userId = signinManager.GetVerifiedUserId(); + if (userId == null) { - manager = Context.GetOwinContext().GetUserManager(); - signinManager = Context.GetOwinContext().GetUserManager(); + Response.Redirect("/Account/Error", true); } + var userFactors = manager.GetValidTwoFactorProviders(userId); + Providers.DataSource = userFactors.Select(x => x).ToList(); + Providers.DataBind(); + } - protected void Page_Load(object sender, EventArgs e) + protected void CodeSubmit_Click(object sender, EventArgs e) + { + bool rememberMe = false; + bool.TryParse(Request.QueryString["RememberMe"], out rememberMe); + + var result = signinManager.TwoFactorSignIn(SelectedProvider.Value, Code.Text, isPersistent: rememberMe, rememberBrowser: RememberBrowser.Checked); + switch (result) { - var userId = signinManager.GetVerifiedUserId(); - if (userId == null) - { - Response.Redirect("/Account/Error", true); - } - var userFactors = manager.GetValidTwoFactorProviders(userId); - Providers.DataSource = userFactors.Select(x => x).ToList(); - Providers.DataBind(); + case SignInStatus.Success: + IdentityHelper.RedirectToReturnUrl(Request.QueryString["ReturnUrl"], Response); + break; + case SignInStatus.LockedOut: + Response.Redirect("/Account/Lockout"); + break; + case SignInStatus.Failure: + default: + FailureText.Text = "Invalid code"; + ErrorMessage.Visible = true; + break; } + } - protected void CodeSubmit_Click(object sender, EventArgs e) + protected void ProviderSubmit_Click(object sender, EventArgs e) + { + if (!signinManager.SendTwoFactorCode(Providers.SelectedValue)) { - bool rememberMe = false; - bool.TryParse(Request.QueryString["RememberMe"], out rememberMe); - - var result = signinManager.TwoFactorSignIn(SelectedProvider.Value, Code.Text, isPersistent: rememberMe, rememberBrowser: RememberBrowser.Checked); - switch (result) - { - case SignInStatus.Success: - IdentityHelper.RedirectToReturnUrl(Request.QueryString["ReturnUrl"], Response); - break; - case SignInStatus.LockedOut: - Response.Redirect("/Account/Lockout"); - break; - case SignInStatus.Failure: - default: - FailureText.Text = "Invalid code"; - ErrorMessage.Visible = true; - break; - } + Response.Redirect("/Account/Error"); } - protected void ProviderSubmit_Click(object sender, EventArgs e) + var user = manager.FindById(signinManager.GetVerifiedUserId()); + if (user != null) { - if (!signinManager.SendTwoFactorCode(Providers.SelectedValue)) - { - Response.Redirect("/Account/Error"); - } - - var user = manager.FindById(signinManager.GetVerifiedUserId()); - if (user != null) - { - var code = manager.GenerateTwoFactorToken(user.Id, Providers.SelectedValue); - } - - SelectedProvider.Value = Providers.SelectedValue; - sendcode.Visible = false; - verifycode.Visible = true; + var code = manager.GenerateTwoFactorToken(user.Id, Providers.SelectedValue); } + + SelectedProvider.Value = Providers.SelectedValue; + sendcode.Visible = false; + verifycode.Visible = true; } } \ No newline at end of file diff --git a/samples/Fornax/Fornax.Server/Account/TwoFactorAuthenticationSignIn.aspx.designer.cs b/samples/Fornax/Fornax.Server/Account/TwoFactorAuthenticationSignIn.aspx.designer.cs index bce90851f..78764a81c 100644 --- a/samples/Fornax/Fornax.Server/Account/TwoFactorAuthenticationSignIn.aspx.designer.cs +++ b/samples/Fornax/Fornax.Server/Account/TwoFactorAuthenticationSignIn.aspx.designer.cs @@ -7,99 +7,98 @@ // //------------------------------------------------------------------------------ -namespace Fornax.Server.Account { +namespace Fornax.Server.Account; + + +public partial class TwoFactorAuthenticationSignIn { + + /// + /// sendcode control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.PlaceHolder sendcode; + + /// + /// Providers control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.DropDownList Providers; + + /// + /// ProviderSubmit control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Button ProviderSubmit; + + /// + /// verifycode control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.PlaceHolder verifycode; + + /// + /// SelectedProvider control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.HiddenField SelectedProvider; + + /// + /// ErrorMessage control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.PlaceHolder ErrorMessage; + + /// + /// FailureText control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Literal FailureText; + + /// + /// Code control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox Code; + /// + /// RememberBrowser control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.CheckBox RememberBrowser; - public partial class TwoFactorAuthenticationSignIn { - - /// - /// sendcode control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.PlaceHolder sendcode; - - /// - /// Providers control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.DropDownList Providers; - - /// - /// ProviderSubmit control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Button ProviderSubmit; - - /// - /// verifycode control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.PlaceHolder verifycode; - - /// - /// SelectedProvider control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.HiddenField SelectedProvider; - - /// - /// ErrorMessage control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.PlaceHolder ErrorMessage; - - /// - /// FailureText control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Literal FailureText; - - /// - /// Code control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox Code; - - /// - /// RememberBrowser control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.CheckBox RememberBrowser; - - /// - /// CodeSubmit control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Button CodeSubmit; - } + /// + /// CodeSubmit control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Button CodeSubmit; } diff --git a/samples/Fornax/Fornax.Server/Account/VerifyPhoneNumber.aspx.cs b/samples/Fornax/Fornax.Server/Account/VerifyPhoneNumber.aspx.cs index b13dabc33..ff311f182 100644 --- a/samples/Fornax/Fornax.Server/Account/VerifyPhoneNumber.aspx.cs +++ b/samples/Fornax/Fornax.Server/Account/VerifyPhoneNumber.aspx.cs @@ -3,44 +3,43 @@ using Microsoft.AspNet.Identity; using Microsoft.AspNet.Identity.Owin; -namespace Fornax.Server.Account +namespace Fornax.Server.Account; + +public partial class VerifyPhoneNumber : System.Web.UI.Page { - public partial class VerifyPhoneNumber : System.Web.UI.Page + protected void Page_Load(object sender, EventArgs e) + { + var manager = Context.GetOwinContext().GetUserManager(); + var phonenumber = Request.QueryString["PhoneNumber"]; + var code = manager.GenerateChangePhoneNumberToken(User.Identity.GetUserId(), phonenumber); + PhoneNumber.Value = phonenumber; + } + + protected void Code_Click(object sender, EventArgs e) { - protected void Page_Load(object sender, EventArgs e) + if (!ModelState.IsValid) { - var manager = Context.GetOwinContext().GetUserManager(); - var phonenumber = Request.QueryString["PhoneNumber"]; - var code = manager.GenerateChangePhoneNumberToken(User.Identity.GetUserId(), phonenumber); - PhoneNumber.Value = phonenumber; + ModelState.AddModelError("", "Invalid code"); + return; } - protected void Code_Click(object sender, EventArgs e) - { - if (!ModelState.IsValid) - { - ModelState.AddModelError("", "Invalid code"); - return; - } + var manager = Context.GetOwinContext().GetUserManager(); + var signInManager = Context.GetOwinContext().Get(); - var manager = Context.GetOwinContext().GetUserManager(); - var signInManager = Context.GetOwinContext().Get(); + var result = manager.ChangePhoneNumber(User.Identity.GetUserId(), PhoneNumber.Value, Code.Text); - var result = manager.ChangePhoneNumber(User.Identity.GetUserId(), PhoneNumber.Value, Code.Text); + if (result.Succeeded) + { + var user = manager.FindById(User.Identity.GetUserId()); - if (result.Succeeded) + if (user != null) { - var user = manager.FindById(User.Identity.GetUserId()); - - if (user != null) - { - signInManager.SignIn(user, isPersistent: false, rememberBrowser: false); - Response.Redirect("/Account/Manage?m=AddPhoneNumberSuccess"); - } + signInManager.SignIn(user, isPersistent: false, rememberBrowser: false); + Response.Redirect("/Account/Manage?m=AddPhoneNumberSuccess"); } - - // If we got this far, something failed, redisplay form - ModelState.AddModelError("", "Failed to verify phone"); } + + // If we got this far, something failed, redisplay form + ModelState.AddModelError("", "Failed to verify phone"); } } \ No newline at end of file diff --git a/samples/Fornax/Fornax.Server/Account/VerifyPhoneNumber.aspx.designer.cs b/samples/Fornax/Fornax.Server/Account/VerifyPhoneNumber.aspx.designer.cs index fd96147c7..32641af0b 100644 --- a/samples/Fornax/Fornax.Server/Account/VerifyPhoneNumber.aspx.designer.cs +++ b/samples/Fornax/Fornax.Server/Account/VerifyPhoneNumber.aspx.designer.cs @@ -7,36 +7,35 @@ // //------------------------------------------------------------------------------ -namespace Fornax.Server.Account { +namespace Fornax.Server.Account; + + +public partial class VerifyPhoneNumber { + + /// + /// ErrorMessage control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Literal ErrorMessage; + /// + /// PhoneNumber control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.HiddenField PhoneNumber; - public partial class VerifyPhoneNumber { - - /// - /// ErrorMessage control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Literal ErrorMessage; - - /// - /// PhoneNumber control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.HiddenField PhoneNumber; - - /// - /// Code control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox Code; - } + /// + /// Code control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.TextBox Code; } diff --git a/samples/Fornax/Fornax.Server/App_Start/BundleConfig.cs b/samples/Fornax/Fornax.Server/App_Start/BundleConfig.cs index 4ee2aaf71..9cb2c8378 100644 --- a/samples/Fornax/Fornax.Server/App_Start/BundleConfig.cs +++ b/samples/Fornax/Fornax.Server/App_Start/BundleConfig.cs @@ -1,33 +1,32 @@ using System.Web.Optimization; -namespace Fornax.Server +namespace Fornax.Server; + +public class BundleConfig { - public class BundleConfig + // For more information on Bundling, visit https://go.microsoft.com/fwlink/?LinkID=303951 + public static void RegisterBundles(BundleCollection bundles) { - // For more information on Bundling, visit https://go.microsoft.com/fwlink/?LinkID=303951 - public static void RegisterBundles(BundleCollection bundles) - { - bundles.Add(new ScriptBundle("~/bundles/WebFormsJs").Include( - "~/Scripts/WebForms/WebForms.js", - "~/Scripts/WebForms/WebUIValidation.js", - "~/Scripts/WebForms/MenuStandards.js", - "~/Scripts/WebForms/Focus.js", - "~/Scripts/WebForms/GridView.js", - "~/Scripts/WebForms/DetailsView.js", - "~/Scripts/WebForms/TreeView.js", - "~/Scripts/WebForms/WebParts.js")); + bundles.Add(new ScriptBundle("~/bundles/WebFormsJs").Include( + "~/Scripts/WebForms/WebForms.js", + "~/Scripts/WebForms/WebUIValidation.js", + "~/Scripts/WebForms/MenuStandards.js", + "~/Scripts/WebForms/Focus.js", + "~/Scripts/WebForms/GridView.js", + "~/Scripts/WebForms/DetailsView.js", + "~/Scripts/WebForms/TreeView.js", + "~/Scripts/WebForms/WebParts.js")); - // Order is very important for these files to work, they have explicit dependencies - bundles.Add(new ScriptBundle("~/bundles/MsAjaxJs").Include( - "~/Scripts/WebForms/MsAjax/MicrosoftAjax.js", - "~/Scripts/WebForms/MsAjax/MicrosoftAjaxApplicationServices.js", - "~/Scripts/WebForms/MsAjax/MicrosoftAjaxTimer.js", - "~/Scripts/WebForms/MsAjax/MicrosoftAjaxWebForms.js")); + // Order is very important for these files to work, they have explicit dependencies + bundles.Add(new ScriptBundle("~/bundles/MsAjaxJs").Include( + "~/Scripts/WebForms/MsAjax/MicrosoftAjax.js", + "~/Scripts/WebForms/MsAjax/MicrosoftAjaxApplicationServices.js", + "~/Scripts/WebForms/MsAjax/MicrosoftAjaxTimer.js", + "~/Scripts/WebForms/MsAjax/MicrosoftAjaxWebForms.js")); - // Use the Development version of Modernizr to develop with and learn from. Then, when you’re - // ready for production, use the build tool at https://modernizr.com to pick only the tests you need - bundles.Add(new ScriptBundle("~/bundles/modernizr").Include( - "~/Scripts/modernizr-*")); - } + // Use the Development version of Modernizr to develop with and learn from. Then, when you’re + // ready for production, use the build tool at https://modernizr.com to pick only the tests you need + bundles.Add(new ScriptBundle("~/bundles/modernizr").Include( + "~/Scripts/modernizr-*")); } } \ No newline at end of file diff --git a/samples/Fornax/Fornax.Server/App_Start/IdentityConfig.cs b/samples/Fornax/Fornax.Server/App_Start/IdentityConfig.cs index 8ebd9634b..f02a35504 100644 --- a/samples/Fornax/Fornax.Server/App_Start/IdentityConfig.cs +++ b/samples/Fornax/Fornax.Server/App_Start/IdentityConfig.cs @@ -8,95 +8,94 @@ using Microsoft.Owin.Security; using Fornax.Server.Models; -namespace Fornax.Server +namespace Fornax.Server; + +public class EmailService : IIdentityMessageService { - public class EmailService : IIdentityMessageService + public Task SendAsync(IdentityMessage message) { - public Task SendAsync(IdentityMessage message) - { - // Plug in your email service here to send an email. - return Task.FromResult(0); - } + // Plug in your email service here to send an email. + return Task.FromResult(0); } +} - public class SmsService : IIdentityMessageService +public class SmsService : IIdentityMessageService +{ + public Task SendAsync(IdentityMessage message) { - public Task SendAsync(IdentityMessage message) - { - // Plug in your SMS service here to send a text message. - return Task.FromResult(0); - } + // Plug in your SMS service here to send a text message. + return Task.FromResult(0); } +} - // Configure the application user manager used in this application. UserManager is defined in ASP.NET Identity and is used by the application. - public class ApplicationUserManager : UserManager +// Configure the application user manager used in this application. UserManager is defined in ASP.NET Identity and is used by the application. +public class ApplicationUserManager : UserManager +{ + public ApplicationUserManager(IUserStore store) + : base(store) { - public ApplicationUserManager(IUserStore store) - : base(store) - { - } + } - public static ApplicationUserManager Create(IdentityFactoryOptions options, IOwinContext context) + public static ApplicationUserManager Create(IdentityFactoryOptions options, IOwinContext context) + { + var manager = new ApplicationUserManager(new UserStore(context.Get())); + // Configure validation logic for usernames + manager.UserValidator = new UserValidator(manager) { - var manager = new ApplicationUserManager(new UserStore(context.Get())); - // Configure validation logic for usernames - manager.UserValidator = new UserValidator(manager) - { - AllowOnlyAlphanumericUserNames = false, - RequireUniqueEmail = true - }; + AllowOnlyAlphanumericUserNames = false, + RequireUniqueEmail = true + }; - // Configure validation logic for passwords - manager.PasswordValidator = new PasswordValidator - { - RequiredLength = 6, - RequireNonLetterOrDigit = true, - RequireDigit = true, - RequireLowercase = true, - RequireUppercase = true, - }; + // Configure validation logic for passwords + manager.PasswordValidator = new PasswordValidator + { + RequiredLength = 6, + RequireNonLetterOrDigit = true, + RequireDigit = true, + RequireLowercase = true, + RequireUppercase = true, + }; - // Register two factor authentication providers. This application uses Phone and Emails as a step of receiving a code for verifying the user - // You can write your own provider and plug it in here. - manager.RegisterTwoFactorProvider("Phone Code", new PhoneNumberTokenProvider - { - MessageFormat = "Your security code is {0}" - }); - manager.RegisterTwoFactorProvider("Email Code", new EmailTokenProvider - { - Subject = "Security Code", - BodyFormat = "Your security code is {0}" - }); + // Register two factor authentication providers. This application uses Phone and Emails as a step of receiving a code for verifying the user + // You can write your own provider and plug it in here. + manager.RegisterTwoFactorProvider("Phone Code", new PhoneNumberTokenProvider + { + MessageFormat = "Your security code is {0}" + }); + manager.RegisterTwoFactorProvider("Email Code", new EmailTokenProvider + { + Subject = "Security Code", + BodyFormat = "Your security code is {0}" + }); - // Configure user lockout defaults - manager.UserLockoutEnabledByDefault = true; - manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5); - manager.MaxFailedAccessAttemptsBeforeLockout = 5; + // Configure user lockout defaults + manager.UserLockoutEnabledByDefault = true; + manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5); + manager.MaxFailedAccessAttemptsBeforeLockout = 5; - manager.EmailService = new EmailService(); - manager.SmsService = new SmsService(); - var dataProtectionProvider = options.DataProtectionProvider; - if (dataProtectionProvider != null) - { - manager.UserTokenProvider = new DataProtectorTokenProvider(dataProtectionProvider.Create("ASP.NET Identity")); - } - return manager; + manager.EmailService = new EmailService(); + manager.SmsService = new SmsService(); + var dataProtectionProvider = options.DataProtectionProvider; + if (dataProtectionProvider != null) + { + manager.UserTokenProvider = new DataProtectorTokenProvider(dataProtectionProvider.Create("ASP.NET Identity")); } + return manager; } +} - public class ApplicationSignInManager : SignInManager - { - public ApplicationSignInManager(ApplicationUserManager userManager, IAuthenticationManager authenticationManager) : - base(userManager, authenticationManager) { } +public class ApplicationSignInManager : SignInManager +{ + public ApplicationSignInManager(ApplicationUserManager userManager, IAuthenticationManager authenticationManager) : + base(userManager, authenticationManager) { } - public override Task CreateUserIdentityAsync(ApplicationUser user) - { - return user.GenerateUserIdentityAsync((ApplicationUserManager)UserManager); - } + public override Task CreateUserIdentityAsync(ApplicationUser user) + { + return user.GenerateUserIdentityAsync((ApplicationUserManager)UserManager); + } - public static ApplicationSignInManager Create(IdentityFactoryOptions options, IOwinContext context) - { - return new ApplicationSignInManager(context.GetUserManager(), context.Authentication); - } + public static ApplicationSignInManager Create(IdentityFactoryOptions options, IOwinContext context) + { + return new ApplicationSignInManager(context.GetUserManager(), context.Authentication); } } diff --git a/samples/Fornax/Fornax.Server/App_Start/RouteConfig.cs b/samples/Fornax/Fornax.Server/App_Start/RouteConfig.cs index 669b80e67..269a47e40 100644 --- a/samples/Fornax/Fornax.Server/App_Start/RouteConfig.cs +++ b/samples/Fornax/Fornax.Server/App_Start/RouteConfig.cs @@ -1,15 +1,14 @@ using System.Web.Routing; using Microsoft.AspNet.FriendlyUrls; -namespace Fornax.Server +namespace Fornax.Server; + +public static class RouteConfig { - public static class RouteConfig + public static void RegisterRoutes(RouteCollection routes) { - public static void RegisterRoutes(RouteCollection routes) - { - var settings = new FriendlyUrlSettings(); - settings.AutoRedirectMode = RedirectMode.Permanent; - routes.EnableFriendlyUrls(settings); - } + var settings = new FriendlyUrlSettings(); + settings.AutoRedirectMode = RedirectMode.Permanent; + routes.EnableFriendlyUrls(settings); } } diff --git a/samples/Fornax/Fornax.Server/Connect/Authorize.aspx.cs b/samples/Fornax/Fornax.Server/Connect/Authorize.aspx.cs index 599df18e9..c22af888f 100644 --- a/samples/Fornax/Fornax.Server/Connect/Authorize.aspx.cs +++ b/samples/Fornax/Fornax.Server/Connect/Authorize.aspx.cs @@ -14,291 +14,290 @@ using Owin; using static OpenIddict.Abstractions.OpenIddictConstants; -namespace Fornax.Server.Connect +namespace Fornax.Server.Connect; + +public partial class Authorize : Page { - public partial class Authorize : Page + // Note: these properties are automatically injected by Autofac. + public IOpenIddictApplicationManager ApplicationManager { get; set; } + public IOpenIddictAuthorizationManager AuthorizationManager { get; set; } + public IOpenIddictScopeManager ScopeManager { get; set; } + + public IEnumerable> Parameters { get; private set; } + + protected void Page_Load(object sender, EventArgs e) => RegisterAsyncTask(new PageAsyncTask(async () => { - // Note: these properties are automatically injected by Autofac. - public IOpenIddictApplicationManager ApplicationManager { get; set; } - public IOpenIddictAuthorizationManager AuthorizationManager { get; set; } - public IOpenIddictScopeManager ScopeManager { get; set; } + var context = Context.GetOwinContext(); + var request = context.GetOpenIddictServerRequest() ?? + throw new InvalidOperationException("The OpenID Connect request cannot be retrieved."); + + // Retrieve the user principal stored in the authentication cookie. + // If a max_age parameter was provided, ensure that the cookie is not too old. + // If the user principal can't be extracted or the cookie is too old, redirect the user to the login page. + var result = await context.Authentication.AuthenticateAsync(DefaultAuthenticationTypes.ApplicationCookie); + if (result == null || result.Identity == null || (request.MaxAge != null && result.Properties?.IssuedUtc != null && + DateTimeOffset.UtcNow - result.Properties.IssuedUtc > TimeSpan.FromSeconds(request.MaxAge.Value))) + { + context.Authentication.Challenge(DefaultAuthenticationTypes.ApplicationCookie); + Visible = false; + return; + } + + // Retrieve the profile of the logged in user. + var user = await context.GetUserManager().FindByIdAsync(result.Identity.GetUserId()) ?? + throw new InvalidOperationException("The user details cannot be retrieved."); + + // Retrieve the application details from the database. + var application = await ApplicationManager.FindByClientIdAsync(request.ClientId) ?? + throw new InvalidOperationException("Details concerning the calling client application cannot be found."); - public IEnumerable> Parameters { get; private set; } + // Retrieve the permanent authorizations associated with the user and the calling client application. + var authorizations = await AuthorizationManager.FindAsync( + subject: user.Id, + client : await ApplicationManager.GetIdAsync(application), + status : Statuses.Valid, + type : AuthorizationTypes.Permanent, + scopes : request.GetScopes()).ToListAsync(); - protected void Page_Load(object sender, EventArgs e) => RegisterAsyncTask(new PageAsyncTask(async () => + switch (await ApplicationManager.GetConsentTypeAsync(application)) { - var context = Context.GetOwinContext(); - var request = context.GetOpenIddictServerRequest() ?? - throw new InvalidOperationException("The OpenID Connect request cannot be retrieved."); - - // Retrieve the user principal stored in the authentication cookie. - // If a max_age parameter was provided, ensure that the cookie is not too old. - // If the user principal can't be extracted or the cookie is too old, redirect the user to the login page. - var result = await context.Authentication.AuthenticateAsync(DefaultAuthenticationTypes.ApplicationCookie); - if (result == null || result.Identity == null || (request.MaxAge != null && result.Properties?.IssuedUtc != null && - DateTimeOffset.UtcNow - result.Properties.IssuedUtc > TimeSpan.FromSeconds(request.MaxAge.Value))) - { - context.Authentication.Challenge(DefaultAuthenticationTypes.ApplicationCookie); + // If the consent is external (e.g when authorizations are granted by a sysadmin), + // immediately return an error if no authorization can be found in the database. + case ConsentTypes.External when authorizations.Count is 0: + context.Authentication.Challenge( + authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType, + properties: new AuthenticationProperties(new Dictionary + { + [OpenIddictServerOwinConstants.Properties.Error] = Errors.ConsentRequired, + [OpenIddictServerOwinConstants.Properties.ErrorDescription] = + "The logged in user is not allowed to access this client application." + })); Visible = false; return; - } - - // Retrieve the profile of the logged in user. - var user = await context.GetUserManager().FindByIdAsync(result.Identity.GetUserId()) ?? - throw new InvalidOperationException("The user details cannot be retrieved."); - - // Retrieve the application details from the database. - var application = await ApplicationManager.FindByClientIdAsync(request.ClientId) ?? - throw new InvalidOperationException("Details concerning the calling client application cannot be found."); - - // Retrieve the permanent authorizations associated with the user and the calling client application. - var authorizations = await AuthorizationManager.FindAsync( - subject: user.Id, - client : await ApplicationManager.GetIdAsync(application), - status : Statuses.Valid, - type : AuthorizationTypes.Permanent, - scopes : request.GetScopes()).ToListAsync(); - - switch (await ApplicationManager.GetConsentTypeAsync(application)) - { - // If the consent is external (e.g when authorizations are granted by a sysadmin), - // immediately return an error if no authorization can be found in the database. - case ConsentTypes.External when authorizations.Count is 0: - context.Authentication.Challenge( - authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType, - properties: new AuthenticationProperties(new Dictionary - { - [OpenIddictServerOwinConstants.Properties.Error] = Errors.ConsentRequired, - [OpenIddictServerOwinConstants.Properties.ErrorDescription] = - "The logged in user is not allowed to access this client application." - })); - Visible = false; - return; - - // If the consent is implicit or if an authorization was found, - // return an authorization response without displaying the consent form. - case ConsentTypes.Implicit: - case ConsentTypes.External when authorizations.Count is not 0: - case ConsentTypes.Explicit when authorizations.Count is not 0 && !request.HasPrompt(Prompts.Consent): - // Create the claims-based identity that will be used by OpenIddict to generate tokens. - var identity = new ClaimsIdentity( - authenticationType: OpenIddictServerOwinDefaults.AuthenticationType, - nameType: Claims.Name, - roleType: Claims.Role); - - // Add the claims that will be persisted in the tokens. - identity.SetClaim(Claims.Subject, user.Id) - .SetClaim(Claims.Email, user.Email) - .SetClaim(Claims.Name, user.UserName) - .SetClaim(Claims.PreferredUsername, user.UserName) - .SetClaims(Claims.Role, (await context.Get().GetRolesAsync(user.Id)).ToImmutableArray()); - - // Note: in this sample, the granted scopes match the requested scope - // but you may want to allow the user to uncheck specific scopes. - // For that, simply restrict the list of scopes before calling SetScopes. - identity.SetScopes(request.GetScopes()); - identity.SetResources(await ScopeManager.ListResourcesAsync(identity.GetScopes()).ToListAsync()); - - // Automatically create a permanent authorization to avoid requiring explicit consent - // for future authorization or token requests containing the same scopes. - var authorization = authorizations.LastOrDefault(); - authorization ??= await AuthorizationManager.CreateAsync( - identity: identity, - subject : user.Id, - client : await ApplicationManager.GetIdAsync(application), - type : AuthorizationTypes.Permanent, - scopes : identity.GetScopes()); - - identity.SetAuthorizationId(await AuthorizationManager.GetIdAsync(authorization)); - identity.SetDestinations(GetDestinations); - - context.Authentication.SignIn(identity); - Visible = false; - return; - - // At this point, no authorization was found in the database and an error must be returned - // if the client application specified prompt=none in the authorization request. - case ConsentTypes.Explicit when request.HasPrompt(Prompts.None): - case ConsentTypes.Systematic when request.HasPrompt(Prompts.None): - context.Authentication.Challenge( - authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType, - properties: new AuthenticationProperties(new Dictionary - { - [OpenIddictServerOwinConstants.Properties.Error] = Errors.ConsentRequired, - [OpenIddictServerOwinConstants.Properties.ErrorDescription] = - "Interactive user consent is required." - })); - Visible = false; - return; - - // In every other case, render the consent form. - default: - ApplicationName.Text = await ApplicationManager.GetLocalizedDisplayNameAsync(application); - Scope.Text = request.Scope; - - // Flow the request parameters so they can be received by the Accept/Reject actions. - Parameters = string.Equals(Request.HttpMethod, "POST", StringComparison.OrdinalIgnoreCase) ? - from name in Request.Form.AllKeys - from value in Request.Form.GetValues(name) - select new KeyValuePair(name, value) : - from name in Request.QueryString.AllKeys - from value in Request.QueryString.GetValues(name) - select new KeyValuePair(name, value); - return; - } - })); - - // Important: this endpoint MUST be protected against CSRF and session fixation attacks. - // - // In applications generated using a Visual Studio 2012 or higher, antiforgery - // is implemented at the master page level, in the Site.Master.cs file. - protected void Accept(object sender, EventArgs e) => RegisterAsyncTask(new PageAsyncTask(async () => - { - if (!IsPostBack) - { - return; - } - - var context = Context.GetOwinContext(); - var request = context.GetOpenIddictServerRequest() ?? - throw new InvalidOperationException("The OpenID Connect request cannot be retrieved."); - // Retrieve the user principal stored in the authentication cookie. - var result = await context.Authentication.AuthenticateAsync(DefaultAuthenticationTypes.ApplicationCookie); - if (result == null || result.Identity == null) - { - context.Authentication.Challenge(DefaultAuthenticationTypes.ApplicationCookie); + // If the consent is implicit or if an authorization was found, + // return an authorization response without displaying the consent form. + case ConsentTypes.Implicit: + case ConsentTypes.External when authorizations.Count is not 0: + case ConsentTypes.Explicit when authorizations.Count is not 0 && !request.HasPrompt(Prompts.Consent): + // Create the claims-based identity that will be used by OpenIddict to generate tokens. + var identity = new ClaimsIdentity( + authenticationType: OpenIddictServerOwinDefaults.AuthenticationType, + nameType: Claims.Name, + roleType: Claims.Role); + + // Add the claims that will be persisted in the tokens. + identity.SetClaim(Claims.Subject, user.Id) + .SetClaim(Claims.Email, user.Email) + .SetClaim(Claims.Name, user.UserName) + .SetClaim(Claims.PreferredUsername, user.UserName) + .SetClaims(Claims.Role, (await context.Get().GetRolesAsync(user.Id)).ToImmutableArray()); + + // Note: in this sample, the granted scopes match the requested scope + // but you may want to allow the user to uncheck specific scopes. + // For that, simply restrict the list of scopes before calling SetScopes. + identity.SetScopes(request.GetScopes()); + identity.SetResources(await ScopeManager.ListResourcesAsync(identity.GetScopes()).ToListAsync()); + + // Automatically create a permanent authorization to avoid requiring explicit consent + // for future authorization or token requests containing the same scopes. + var authorization = authorizations.LastOrDefault(); + authorization ??= await AuthorizationManager.CreateAsync( + identity: identity, + subject : user.Id, + client : await ApplicationManager.GetIdAsync(application), + type : AuthorizationTypes.Permanent, + scopes : identity.GetScopes()); + + identity.SetAuthorizationId(await AuthorizationManager.GetIdAsync(authorization)); + identity.SetDestinations(GetDestinations); + + context.Authentication.SignIn(identity); Visible = false; return; - } - - // Retrieve the profile of the logged in user. - var user = await context.GetUserManager().FindByIdAsync(result.Identity.GetUserId()) ?? - throw new InvalidOperationException("The user details cannot be retrieved."); - - // Retrieve the application details from the database. - var application = await ApplicationManager.FindByClientIdAsync(request.ClientId) ?? - throw new InvalidOperationException("Details concerning the calling client application cannot be found."); - - // Retrieve the permanent authorizations associated with the user and the calling client application. - var authorizations = await AuthorizationManager.FindAsync( - subject: user.Id, - client : await ApplicationManager.GetIdAsync(application), - status : Statuses.Valid, - type : AuthorizationTypes.Permanent, - scopes : request.GetScopes()).ToListAsync(); - - // Note: the same check is already made in the other action but is repeated - // here to ensure a malicious user can't abuse this POST-only endpoint and - // force it to return a valid response without the external authorization. - if (authorizations.Count is 0 && await ApplicationManager.HasConsentTypeAsync(application, ConsentTypes.External)) - { + + // At this point, no authorization was found in the database and an error must be returned + // if the client application specified prompt=none in the authorization request. + case ConsentTypes.Explicit when request.HasPrompt(Prompts.None): + case ConsentTypes.Systematic when request.HasPrompt(Prompts.None): context.Authentication.Challenge( authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType, properties: new AuthenticationProperties(new Dictionary { [OpenIddictServerOwinConstants.Properties.Error] = Errors.ConsentRequired, [OpenIddictServerOwinConstants.Properties.ErrorDescription] = - "The logged in user is not allowed to access this client application." + "Interactive user consent is required." })); Visible = false; return; - } - - // Create the claims-based identity that will be used by OpenIddict to generate tokens. - var identity = new ClaimsIdentity( - authenticationType: OpenIddictServerOwinDefaults.AuthenticationType, - nameType: Claims.Name, - roleType: Claims.Role); - - // Add the claims that will be persisted in the tokens. - identity.SetClaim(Claims.Subject, user.Id) - .SetClaim(Claims.Email, user.Email) - .SetClaim(Claims.Name, user.UserName) - .SetClaim(Claims.PreferredUsername, user.UserName) - .SetClaims(Claims.Role, (await context.Get().GetRolesAsync(user.Id)).ToImmutableArray()); - - // Note: in this sample, the granted scopes match the requested scope - // but you may want to allow the user to uncheck specific scopes. - // For that, simply restrict the list of scopes before calling SetScopes. - identity.SetScopes(request.GetScopes()); - identity.SetResources(await ScopeManager.ListResourcesAsync(identity.GetScopes()).ToListAsync()); - - // Automatically create a permanent authorization to avoid requiring explicit consent - // for future authorization or token requests containing the same scopes. - var authorization = authorizations.LastOrDefault(); - authorization ??= await AuthorizationManager.CreateAsync( - identity: identity, - subject : user.Id, - client : await ApplicationManager.GetIdAsync(application), - type : AuthorizationTypes.Permanent, - scopes : identity.GetScopes()); - - identity.SetAuthorizationId(await AuthorizationManager.GetIdAsync(authorization)); - identity.SetDestinations(GetDestinations); - - context.Authentication.SignIn(identity); - Visible = false; + + // In every other case, render the consent form. + default: + ApplicationName.Text = await ApplicationManager.GetLocalizedDisplayNameAsync(application); + Scope.Text = request.Scope; + + // Flow the request parameters so they can be received by the Accept/Reject actions. + Parameters = string.Equals(Request.HttpMethod, "POST", StringComparison.OrdinalIgnoreCase) ? + from name in Request.Form.AllKeys + from value in Request.Form.GetValues(name) + select new KeyValuePair(name, value) : + from name in Request.QueryString.AllKeys + from value in Request.QueryString.GetValues(name) + select new KeyValuePair(name, value); + return; + } + })); + + // Important: this endpoint MUST be protected against CSRF and session fixation attacks. + // + // In applications generated using a Visual Studio 2012 or higher, antiforgery + // is implemented at the master page level, in the Site.Master.cs file. + protected void Accept(object sender, EventArgs e) => RegisterAsyncTask(new PageAsyncTask(async () => + { + if (!IsPostBack) + { return; - })); + } + + var context = Context.GetOwinContext(); + var request = context.GetOpenIddictServerRequest() ?? + throw new InvalidOperationException("The OpenID Connect request cannot be retrieved."); - // Important: this endpoint MUST be protected against CSRF and session fixation attacks. - // - // In applications generated using a Visual Studio 2012 or higher, antiforgery - // is implemented at the master page level, in the Site.Master.cs file. - protected void Deny(object sender, EventArgs e) + // Retrieve the user principal stored in the authentication cookie. + var result = await context.Authentication.AuthenticateAsync(DefaultAuthenticationTypes.ApplicationCookie); + if (result == null || result.Identity == null) { - if (!IsPostBack) - { - return; - } + context.Authentication.Challenge(DefaultAuthenticationTypes.ApplicationCookie); + Visible = false; + return; + } - // Notify OpenIddict that the authorization grant has been denied by the resource owner - // to redirect the user agent to the client application using the appropriate response_mode. - var context = Context.GetOwinContext(); - context.Authentication.Challenge(OpenIddictServerOwinDefaults.AuthenticationType); + // Retrieve the profile of the logged in user. + var user = await context.GetUserManager().FindByIdAsync(result.Identity.GetUserId()) ?? + throw new InvalidOperationException("The user details cannot be retrieved."); + + // Retrieve the application details from the database. + var application = await ApplicationManager.FindByClientIdAsync(request.ClientId) ?? + throw new InvalidOperationException("Details concerning the calling client application cannot be found."); + + // Retrieve the permanent authorizations associated with the user and the calling client application. + var authorizations = await AuthorizationManager.FindAsync( + subject: user.Id, + client : await ApplicationManager.GetIdAsync(application), + status : Statuses.Valid, + type : AuthorizationTypes.Permanent, + scopes : request.GetScopes()).ToListAsync(); + + // Note: the same check is already made in the other action but is repeated + // here to ensure a malicious user can't abuse this POST-only endpoint and + // force it to return a valid response without the external authorization. + if (authorizations.Count is 0 && await ApplicationManager.HasConsentTypeAsync(application, ConsentTypes.External)) + { + context.Authentication.Challenge( + authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType, + properties: new AuthenticationProperties(new Dictionary + { + [OpenIddictServerOwinConstants.Properties.Error] = Errors.ConsentRequired, + [OpenIddictServerOwinConstants.Properties.ErrorDescription] = + "The logged in user is not allowed to access this client application." + })); Visible = false; + return; } - private static IEnumerable GetDestinations(Claim claim) + // Create the claims-based identity that will be used by OpenIddict to generate tokens. + var identity = new ClaimsIdentity( + authenticationType: OpenIddictServerOwinDefaults.AuthenticationType, + nameType: Claims.Name, + roleType: Claims.Role); + + // Add the claims that will be persisted in the tokens. + identity.SetClaim(Claims.Subject, user.Id) + .SetClaim(Claims.Email, user.Email) + .SetClaim(Claims.Name, user.UserName) + .SetClaim(Claims.PreferredUsername, user.UserName) + .SetClaims(Claims.Role, (await context.Get().GetRolesAsync(user.Id)).ToImmutableArray()); + + // Note: in this sample, the granted scopes match the requested scope + // but you may want to allow the user to uncheck specific scopes. + // For that, simply restrict the list of scopes before calling SetScopes. + identity.SetScopes(request.GetScopes()); + identity.SetResources(await ScopeManager.ListResourcesAsync(identity.GetScopes()).ToListAsync()); + + // Automatically create a permanent authorization to avoid requiring explicit consent + // for future authorization or token requests containing the same scopes. + var authorization = authorizations.LastOrDefault(); + authorization ??= await AuthorizationManager.CreateAsync( + identity: identity, + subject : user.Id, + client : await ApplicationManager.GetIdAsync(application), + type : AuthorizationTypes.Permanent, + scopes : identity.GetScopes()); + + identity.SetAuthorizationId(await AuthorizationManager.GetIdAsync(authorization)); + identity.SetDestinations(GetDestinations); + + context.Authentication.SignIn(identity); + Visible = false; + return; + })); + + // Important: this endpoint MUST be protected against CSRF and session fixation attacks. + // + // In applications generated using a Visual Studio 2012 or higher, antiforgery + // is implemented at the master page level, in the Site.Master.cs file. + protected void Deny(object sender, EventArgs e) + { + if (!IsPostBack) { - // Note: by default, claims are NOT automatically included in the access and identity tokens. - // To allow OpenIddict to serialize them, you must attach them a destination, that specifies - // whether they should be included in access tokens, in identity tokens or in both. + return; + } - switch (claim.Type) - { - case Claims.Name or Claims.PreferredUsername: - yield return Destinations.AccessToken; + // Notify OpenIddict that the authorization grant has been denied by the resource owner + // to redirect the user agent to the client application using the appropriate response_mode. + var context = Context.GetOwinContext(); + context.Authentication.Challenge(OpenIddictServerOwinDefaults.AuthenticationType); + Visible = false; + } + + private static IEnumerable GetDestinations(Claim claim) + { + // Note: by default, claims are NOT automatically included in the access and identity tokens. + // To allow OpenIddict to serialize them, you must attach them a destination, that specifies + // whether they should be included in access tokens, in identity tokens or in both. + + switch (claim.Type) + { + case Claims.Name or Claims.PreferredUsername: + yield return Destinations.AccessToken; - if (claim.Subject.HasScope(Scopes.Profile)) - yield return Destinations.IdentityToken; + if (claim.Subject.HasScope(Scopes.Profile)) + yield return Destinations.IdentityToken; - yield break; + yield break; - case Claims.Email: - yield return Destinations.AccessToken; + case Claims.Email: + yield return Destinations.AccessToken; - if (claim.Subject.HasScope(Scopes.Email)) - yield return Destinations.IdentityToken; + if (claim.Subject.HasScope(Scopes.Email)) + yield return Destinations.IdentityToken; - yield break; + yield break; - case Claims.Role: - yield return Destinations.AccessToken; + case Claims.Role: + yield return Destinations.AccessToken; - if (claim.Subject.HasScope(Scopes.Roles)) - yield return Destinations.IdentityToken; + if (claim.Subject.HasScope(Scopes.Roles)) + yield return Destinations.IdentityToken; - yield break; + yield break; - // Never include the security stamp in the access and identity tokens, as it's a secret value. - case Constants.DefaultSecurityStampClaimType: yield break; + // Never include the security stamp in the access and identity tokens, as it's a secret value. + case Constants.DefaultSecurityStampClaimType: yield break; - default: - yield return Destinations.AccessToken; - yield break; - } + default: + yield return Destinations.AccessToken; + yield break; } } } \ No newline at end of file diff --git a/samples/Fornax/Fornax.Server/Connect/Authorize.aspx.designer.cs b/samples/Fornax/Fornax.Server/Connect/Authorize.aspx.designer.cs index 4414e0295..03a7c2416 100644 --- a/samples/Fornax/Fornax.Server/Connect/Authorize.aspx.designer.cs +++ b/samples/Fornax/Fornax.Server/Connect/Authorize.aspx.designer.cs @@ -8,27 +8,26 @@ //------------------------------------------------------------------------------ -namespace Fornax.Server.Connect +namespace Fornax.Server.Connect; + +public partial class Authorize { - public partial class Authorize - { - - /// - /// ApplicationName control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Label ApplicationName; - - /// - /// Scope control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Label Scope; - } + + /// + /// ApplicationName control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Label ApplicationName; + + /// + /// Scope control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Label Scope; } diff --git a/samples/Fornax/Fornax.Server/Contact.aspx.cs b/samples/Fornax/Fornax.Server/Contact.aspx.cs index cf00bccf0..649d44562 100644 --- a/samples/Fornax/Fornax.Server/Contact.aspx.cs +++ b/samples/Fornax/Fornax.Server/Contact.aspx.cs @@ -1,13 +1,12 @@ using System; using System.Web.UI; -namespace Fornax.Server +namespace Fornax.Server; + +public partial class Contact : Page { - public partial class Contact : Page + protected void Page_Load(object sender, EventArgs e) { - protected void Page_Load(object sender, EventArgs e) - { - } } } \ No newline at end of file diff --git a/samples/Fornax/Fornax.Server/Contact.aspx.designer.cs b/samples/Fornax/Fornax.Server/Contact.aspx.designer.cs index 773bdf608..1d8f3c5fd 100644 --- a/samples/Fornax/Fornax.Server/Contact.aspx.designer.cs +++ b/samples/Fornax/Fornax.Server/Contact.aspx.designer.cs @@ -8,9 +8,8 @@ //------------------------------------------------------------------------------ -namespace Fornax.Server +namespace Fornax.Server; + +public partial class Contact { - public partial class Contact - { - } } diff --git a/samples/Fornax/Fornax.Server/Default.aspx.cs b/samples/Fornax/Fornax.Server/Default.aspx.cs index 5a3fc5305..1f1bf5dee 100644 --- a/samples/Fornax/Fornax.Server/Default.aspx.cs +++ b/samples/Fornax/Fornax.Server/Default.aspx.cs @@ -1,13 +1,12 @@ using System; using System.Web.UI; -namespace Fornax.Server +namespace Fornax.Server; + +public partial class _Default : Page { - public partial class _Default : Page + protected void Page_Load(object sender, EventArgs e) { - protected void Page_Load(object sender, EventArgs e) - { - } } } \ No newline at end of file diff --git a/samples/Fornax/Fornax.Server/Default.aspx.designer.cs b/samples/Fornax/Fornax.Server/Default.aspx.designer.cs index 99b27c58d..c9c44f9eb 100644 --- a/samples/Fornax/Fornax.Server/Default.aspx.designer.cs +++ b/samples/Fornax/Fornax.Server/Default.aspx.designer.cs @@ -8,9 +8,8 @@ //------------------------------------------------------------------------------ -namespace Fornax.Server +namespace Fornax.Server; + +public partial class _Default { - public partial class _Default - { - } } diff --git a/samples/Fornax/Fornax.Server/Global.asax.cs b/samples/Fornax/Fornax.Server/Global.asax.cs index 2ab8a6b6d..b7beb89f5 100644 --- a/samples/Fornax/Fornax.Server/Global.asax.cs +++ b/samples/Fornax/Fornax.Server/Global.asax.cs @@ -11,116 +11,115 @@ using OpenIddict.Abstractions; using static OpenIddict.Abstractions.OpenIddictConstants; -namespace Fornax.Server +namespace Fornax.Server; + +public class Global : HttpApplication, IContainerProviderAccessor { - public class Global : HttpApplication, IContainerProviderAccessor - { - public static IContainerProvider Provider { get; private set; } + public static IContainerProvider Provider { get; private set; } - IContainerProvider IContainerProviderAccessor.ContainerProvider => Provider; + IContainerProvider IContainerProviderAccessor.ContainerProvider => Provider; - void Application_Start(object sender, EventArgs e) - { - // Code that runs on application startup - RouteConfig.RegisterRoutes(RouteTable.Routes); - BundleConfig.RegisterBundles(BundleTable.Bundles); + void Application_Start(object sender, EventArgs e) + { + // Code that runs on application startup + RouteConfig.RegisterRoutes(RouteTable.Routes); + BundleConfig.RegisterBundles(BundleTable.Bundles); - var services = new ServiceCollection(); + var services = new ServiceCollection(); - services.AddOpenIddict() + services.AddOpenIddict() - // Register the OpenIddict core components. - .AddCore(options => - { - // Configure OpenIddict to use the Entity Framework 6.x stores and models. - // Note: call ReplaceDefaultEntities() to replace the default OpenIddict entities. - options.UseEntityFramework() - .UseDbContext(); - }) - - // Register the OpenIddict server components. - .AddServer(options => - { - // Enable the authorization and token endpoints. - options.SetAuthorizationEndpointUris("connect/authorize") - .SetTokenEndpointUris("connect/token"); - - // Mark the "email", "profile" and "roles" scopes as supported scopes. - options.RegisterScopes(Scopes.Email, Scopes.Profile, Scopes.Roles); - - // Note: this sample only uses the authorization code flow but you can enable - // the other flows if you need to support implicit, password or client credentials. - options.AllowAuthorizationCodeFlow(); - - // Register the signing and encryption credentials. - options.AddDevelopmentEncryptionCertificate() - .AddDevelopmentSigningCertificate(); - - // Register the OWIN host and configure the OWIN-specific options. - // - // Note: unlike other samples, this sample doesn't use token endpoint pass-through - // to handle token requests in a custom MVC action. As such, the token requests - // will be automatically handled by OpenIddict, that will reuse the identity - // resolved from the authorization code to produce access and identity tokens. - // - options.UseOwin() - .EnableAuthorizationEndpointPassthrough(); - }) - - // Register the OpenIddict validation components. - .AddValidation(options => - { - // Import the configuration from the local OpenIddict server instance. - options.UseLocalServer(); + // Register the OpenIddict core components. + .AddCore(options => + { + // Configure OpenIddict to use the Entity Framework 6.x stores and models. + // Note: call ReplaceDefaultEntities() to replace the default OpenIddict entities. + options.UseEntityFramework() + .UseDbContext(); + }) + + // Register the OpenIddict server components. + .AddServer(options => + { + // Enable the authorization and token endpoints. + options.SetAuthorizationEndpointUris("connect/authorize") + .SetTokenEndpointUris("connect/token"); + + // Mark the "email", "profile" and "roles" scopes as supported scopes. + options.RegisterScopes(Scopes.Email, Scopes.Profile, Scopes.Roles); + + // Note: this sample only uses the authorization code flow but you can enable + // the other flows if you need to support implicit, password or client credentials. + options.AllowAuthorizationCodeFlow(); + + // Register the signing and encryption credentials. + options.AddDevelopmentEncryptionCertificate() + .AddDevelopmentSigningCertificate(); + + // Register the OWIN host and configure the OWIN-specific options. + // + // Note: unlike other samples, this sample doesn't use token endpoint pass-through + // to handle token requests in a custom MVC action. As such, the token requests + // will be automatically handled by OpenIddict, that will reuse the identity + // resolved from the authorization code to produce access and identity tokens. + // + options.UseOwin() + .EnableAuthorizationEndpointPassthrough(); + }) + + // Register the OpenIddict validation components. + .AddValidation(options => + { + // Import the configuration from the local OpenIddict server instance. + options.UseLocalServer(); - // Register the OWIN host. - options.UseOwin(); - }); + // Register the OWIN host. + options.UseOwin(); + }); - // Create a new Autofac container and import the OpenIddict services. - var builder = new ContainerBuilder(); - builder.Populate(services); + // Create a new Autofac container and import the OpenIddict services. + var builder = new ContainerBuilder(); + builder.Populate(services); - Provider = new ContainerProvider(builder.Build()); + Provider = new ContainerProvider(builder.Build()); - // Seed the database with the sample client using the OpenIddict application manager. - // Note: in a real world application, this step should be part of a setup script. - Task.Run(async delegate - { - await using var scope = Provider.ApplicationContainer.BeginLifetimeScope(); + // Seed the database with the sample client using the OpenIddict application manager. + // Note: in a real world application, this step should be part of a setup script. + Task.Run(async delegate + { + await using var scope = Provider.ApplicationContainer.BeginLifetimeScope(); - var context = scope.Resolve(); - context.Database.CreateIfNotExists(); + var context = scope.Resolve(); + context.Database.CreateIfNotExists(); - var manager = scope.Resolve(); + var manager = scope.Resolve(); - if (await manager.FindByClientIdAsync("console_app") == null) + if (await manager.FindByClientIdAsync("console_app") == null) + { + await manager.CreateAsync(new OpenIddictApplicationDescriptor { - await manager.CreateAsync(new OpenIddictApplicationDescriptor + ApplicationType = ApplicationTypes.Native, + ClientId = "console_app", + ClientType = ClientTypes.Public, + ConsentType = ConsentTypes.Explicit, + DisplayName = "Console application", + RedirectUris = + { + new Uri("http://localhost/") + }, + Permissions = { - ApplicationType = ApplicationTypes.Native, - ClientId = "console_app", - ClientType = ClientTypes.Public, - ConsentType = ConsentTypes.Explicit, - DisplayName = "Console application", - RedirectUris = - { - new Uri("http://localhost/") - }, - Permissions = - { - Permissions.Endpoints.Authorization, - Permissions.Endpoints.Token, - Permissions.GrantTypes.AuthorizationCode, - Permissions.ResponseTypes.Code - }, - Requirements = - { - Requirements.Features.ProofKeyForCodeExchange - } - }); - } - }).GetAwaiter().GetResult(); - } + Permissions.Endpoints.Authorization, + Permissions.Endpoints.Token, + Permissions.GrantTypes.AuthorizationCode, + Permissions.ResponseTypes.Code + }, + Requirements = + { + Requirements.Features.ProofKeyForCodeExchange + } + }); + } + }).GetAwaiter().GetResult(); } } \ No newline at end of file diff --git a/samples/Fornax/Fornax.Server/Helpers/AsyncEnumerableExtensions.cs b/samples/Fornax/Fornax.Server/Helpers/AsyncEnumerableExtensions.cs index d7081da17..7028832f9 100644 --- a/samples/Fornax/Fornax.Server/Helpers/AsyncEnumerableExtensions.cs +++ b/samples/Fornax/Fornax.Server/Helpers/AsyncEnumerableExtensions.cs @@ -2,30 +2,29 @@ using System.Collections.Generic; using System.Threading.Tasks; -namespace Fornax.Server.Helpers +namespace Fornax.Server.Helpers; + +public static class AsyncEnumerableExtensions { - public static class AsyncEnumerableExtensions + public static Task> ToListAsync(this IAsyncEnumerable source) { - public static Task> ToListAsync(this IAsyncEnumerable source) + if (source == null) { - if (source == null) - { - throw new ArgumentNullException(nameof(source)); - } + throw new ArgumentNullException(nameof(source)); + } - return ExecuteAsync(); + return ExecuteAsync(); - async Task> ExecuteAsync() - { - var list = new List(); - - await foreach (var element in source) - { - list.Add(element); - } + async Task> ExecuteAsync() + { + var list = new List(); - return list; + await foreach (var element in source) + { + list.Add(element); } + + return list; } } } \ No newline at end of file diff --git a/samples/Fornax/Fornax.Server/Site.Master.cs b/samples/Fornax/Fornax.Server/Site.Master.cs index cbc67f102..496a8b40c 100644 --- a/samples/Fornax/Fornax.Server/Site.Master.cs +++ b/samples/Fornax/Fornax.Server/Site.Master.cs @@ -5,74 +5,72 @@ using System.Web.UI.WebControls; using Microsoft.AspNet.Identity; -namespace Fornax.Server +namespace Fornax.Server; + +public partial class SiteMaster : MasterPage { - public partial class SiteMaster : MasterPage - { - private const string AntiXsrfTokenKey = "__AntiXsrfToken"; - private const string AntiXsrfUserNameKey = "__AntiXsrfUserName"; - private string _antiXsrfTokenValue; + private const string AntiXsrfTokenKey = "__AntiXsrfToken"; + private const string AntiXsrfUserNameKey = "__AntiXsrfUserName"; + private string _antiXsrfTokenValue; - protected void Page_Init(object sender, EventArgs e) + protected void Page_Init(object sender, EventArgs e) + { + // The code below helps to protect against XSRF attacks + var requestCookie = Request.Cookies[AntiXsrfTokenKey]; + Guid requestCookieGuidValue; + if (requestCookie != null && Guid.TryParse(requestCookie.Value, out requestCookieGuidValue)) { - // The code below helps to protect against XSRF attacks - var requestCookie = Request.Cookies[AntiXsrfTokenKey]; - Guid requestCookieGuidValue; - if (requestCookie != null && Guid.TryParse(requestCookie.Value, out requestCookieGuidValue)) - { - // Use the Anti-XSRF token from the cookie - _antiXsrfTokenValue = requestCookie.Value; - Page.ViewStateUserKey = _antiXsrfTokenValue; - } - else - { - // Generate a new Anti-XSRF token and save to the cookie - _antiXsrfTokenValue = Guid.NewGuid().ToString("N"); - Page.ViewStateUserKey = _antiXsrfTokenValue; - - var responseCookie = new HttpCookie(AntiXsrfTokenKey) - { - HttpOnly = true, - Value = _antiXsrfTokenValue - }; - if (FormsAuthentication.RequireSSL && Request.IsSecureConnection) - { - responseCookie.Secure = true; - } - Response.Cookies.Set(responseCookie); - } - - Page.PreLoad += master_Page_PreLoad; + // Use the Anti-XSRF token from the cookie + _antiXsrfTokenValue = requestCookie.Value; + Page.ViewStateUserKey = _antiXsrfTokenValue; } - - protected void master_Page_PreLoad(object sender, EventArgs e) + else { - if (!IsPostBack) + // Generate a new Anti-XSRF token and save to the cookie + _antiXsrfTokenValue = Guid.NewGuid().ToString("N"); + Page.ViewStateUserKey = _antiXsrfTokenValue; + + var responseCookie = new HttpCookie(AntiXsrfTokenKey) { - // Set Anti-XSRF token - ViewState[AntiXsrfTokenKey] = Page.ViewStateUserKey; - ViewState[AntiXsrfUserNameKey] = Context.User.Identity.Name ?? String.Empty; - } - else + HttpOnly = true, + Value = _antiXsrfTokenValue + }; + if (FormsAuthentication.RequireSSL && Request.IsSecureConnection) { - // Validate the Anti-XSRF token - if ((string)ViewState[AntiXsrfTokenKey] != _antiXsrfTokenValue - || (string)ViewState[AntiXsrfUserNameKey] != (Context.User.Identity.Name ?? String.Empty)) - { - throw new InvalidOperationException("Validation of Anti-XSRF token failed."); - } + responseCookie.Secure = true; } + Response.Cookies.Set(responseCookie); } - protected void Page_Load(object sender, EventArgs e) - { + Page.PreLoad += master_Page_PreLoad; + } + protected void master_Page_PreLoad(object sender, EventArgs e) + { + if (!IsPostBack) + { + // Set Anti-XSRF token + ViewState[AntiXsrfTokenKey] = Page.ViewStateUserKey; + ViewState[AntiXsrfUserNameKey] = Context.User.Identity.Name ?? String.Empty; } - - protected void Unnamed_LoggingOut(object sender, LoginCancelEventArgs e) + else { - Context.GetOwinContext().Authentication.SignOut(DefaultAuthenticationTypes.ApplicationCookie); + // Validate the Anti-XSRF token + if ((string)ViewState[AntiXsrfTokenKey] != _antiXsrfTokenValue + || (string)ViewState[AntiXsrfUserNameKey] != (Context.User.Identity.Name ?? String.Empty)) + { + throw new InvalidOperationException("Validation of Anti-XSRF token failed."); + } } } + protected void Page_Load(object sender, EventArgs e) + { + + } + + protected void Unnamed_LoggingOut(object sender, LoginCancelEventArgs e) + { + Context.GetOwinContext().Authentication.SignOut(DefaultAuthenticationTypes.ApplicationCookie); + } } \ No newline at end of file diff --git a/samples/Fornax/Fornax.Server/Site.Master.designer.cs b/samples/Fornax/Fornax.Server/Site.Master.designer.cs index 9d03162b3..a91762678 100644 --- a/samples/Fornax/Fornax.Server/Site.Master.designer.cs +++ b/samples/Fornax/Fornax.Server/Site.Master.designer.cs @@ -7,18 +7,17 @@ // //------------------------------------------------------------------------------ -namespace Fornax.Server { - +namespace Fornax.Server; + + +public partial class SiteMaster { - public partial class SiteMaster { - - /// - /// MainContent control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.ContentPlaceHolder MainContent; - } + /// + /// MainContent control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.ContentPlaceHolder MainContent; } diff --git a/samples/Fornax/Fornax.Server/Site.Mobile.Master.cs b/samples/Fornax/Fornax.Server/Site.Mobile.Master.cs index fc98122c9..224d1c778 100644 --- a/samples/Fornax/Fornax.Server/Site.Mobile.Master.cs +++ b/samples/Fornax/Fornax.Server/Site.Mobile.Master.cs @@ -1,12 +1,11 @@ using System; -namespace Fornax.Server +namespace Fornax.Server; + +public partial class Site_Mobile : System.Web.UI.MasterPage { - public partial class Site_Mobile : System.Web.UI.MasterPage + protected void Page_Load(object sender, EventArgs e) { - protected void Page_Load(object sender, EventArgs e) - { - } } } \ No newline at end of file diff --git a/samples/Fornax/Fornax.Server/Site.Mobile.Master.designer.cs b/samples/Fornax/Fornax.Server/Site.Mobile.Master.designer.cs index b95518f03..2952a2002 100644 --- a/samples/Fornax/Fornax.Server/Site.Mobile.Master.designer.cs +++ b/samples/Fornax/Fornax.Server/Site.Mobile.Master.designer.cs @@ -7,45 +7,44 @@ // //------------------------------------------------------------------------------ -namespace Fornax.Server { +namespace Fornax.Server; + + +public partial class Site_Mobile { + + /// + /// HeadContent control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.ContentPlaceHolder HeadContent; + + /// + /// form1 control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.HtmlControls.HtmlForm form1; + /// + /// FeaturedContent control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.ContentPlaceHolder FeaturedContent; - public partial class Site_Mobile { - - /// - /// HeadContent control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.ContentPlaceHolder HeadContent; - - /// - /// form1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.HtmlControls.HtmlForm form1; - - /// - /// FeaturedContent control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.ContentPlaceHolder FeaturedContent; - - /// - /// MainContent control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.ContentPlaceHolder MainContent; - } + /// + /// MainContent control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.ContentPlaceHolder MainContent; } diff --git a/samples/Fornax/Fornax.Server/Startup.cs b/samples/Fornax/Fornax.Server/Startup.cs index e00d5e355..43431f093 100644 --- a/samples/Fornax/Fornax.Server/Startup.cs +++ b/samples/Fornax/Fornax.Server/Startup.cs @@ -10,40 +10,39 @@ [assembly: OwinStartup(typeof(Fornax.Server.Startup))] -namespace Fornax.Server +namespace Fornax.Server; + +public class Startup { - public class Startup + public void Configuration(IAppBuilder app) { - public void Configuration(IAppBuilder app) - { - // Register the Entity Framework context and the user/sign-in managers used by ASP.NET Identity. - app.CreatePerOwinContext(ApplicationDbContext.Create); - app.CreatePerOwinContext(ApplicationUserManager.Create); - app.CreatePerOwinContext(ApplicationSignInManager.Create); + // Register the Entity Framework context and the user/sign-in managers used by ASP.NET Identity. + app.CreatePerOwinContext(ApplicationDbContext.Create); + app.CreatePerOwinContext(ApplicationUserManager.Create); + app.CreatePerOwinContext(ApplicationSignInManager.Create); - // Register the cookie middleware used by ASP.NET Identity. - app.UseCookieAuthentication(new CookieAuthenticationOptions + // Register the cookie middleware used by ASP.NET Identity. + app.UseCookieAuthentication(new CookieAuthenticationOptions + { + AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, + LoginPath = new PathString("/Account/Login"), + Provider = new CookieAuthenticationProvider { - AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, - LoginPath = new PathString("/Account/Login"), - Provider = new CookieAuthenticationProvider - { - OnValidateIdentity = SecurityStampValidator.OnValidateIdentity( - validateInterval: TimeSpan.FromMinutes(30), - regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager)) - } - }); + OnValidateIdentity = SecurityStampValidator.OnValidateIdentity( + validateInterval: TimeSpan.FromMinutes(30), + regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager)) + } + }); - app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie); - app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5)); - app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie); + app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie); + app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5)); + app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie); - // Register the Autofac scope injector middleware. - app.UseAutofacLifetimeScopeInjector(Global.Provider.ApplicationContainer); + // Register the Autofac scope injector middleware. + app.UseAutofacLifetimeScopeInjector(Global.Provider.ApplicationContainer); - // Register the two OpenIddict server/validation middleware. - app.UseMiddlewareFromContainer(); - app.UseMiddlewareFromContainer(); - } + // Register the two OpenIddict server/validation middleware. + app.UseMiddlewareFromContainer(); + app.UseMiddlewareFromContainer(); } } diff --git a/samples/Fornax/Fornax.Server/ViewSwitcher.ascx.cs b/samples/Fornax/Fornax.Server/ViewSwitcher.ascx.cs index e1ca35d62..91dcd3ff1 100644 --- a/samples/Fornax/Fornax.Server/ViewSwitcher.ascx.cs +++ b/samples/Fornax/Fornax.Server/ViewSwitcher.ascx.cs @@ -3,37 +3,36 @@ using System.Web.Routing; using Microsoft.AspNet.FriendlyUrls.Resolvers; -namespace Fornax.Server +namespace Fornax.Server; + +public partial class ViewSwitcher : System.Web.UI.UserControl { - public partial class ViewSwitcher : System.Web.UI.UserControl - { - protected string CurrentView { get; private set; } + protected string CurrentView { get; private set; } - protected string AlternateView { get; private set; } + protected string AlternateView { get; private set; } - protected string SwitchUrl { get; private set; } + protected string SwitchUrl { get; private set; } - protected void Page_Load(object sender, EventArgs e) - { - // Determine current view - var isMobile = WebFormsFriendlyUrlResolver.IsMobileView(new HttpContextWrapper(Context)); - CurrentView = isMobile ? "Mobile" : "Desktop"; + protected void Page_Load(object sender, EventArgs e) + { + // Determine current view + var isMobile = WebFormsFriendlyUrlResolver.IsMobileView(new HttpContextWrapper(Context)); + CurrentView = isMobile ? "Mobile" : "Desktop"; - // Determine alternate view - AlternateView = isMobile ? "Desktop" : "Mobile"; + // Determine alternate view + AlternateView = isMobile ? "Desktop" : "Mobile"; - // Create switch URL from the route, e.g. ~/__FriendlyUrls_SwitchView/Mobile?ReturnUrl=/Page - var switchViewRouteName = "AspNet.FriendlyUrls.SwitchView"; - var switchViewRoute = RouteTable.Routes[switchViewRouteName]; - if (switchViewRoute == null) - { - // Friendly URLs is not enabled or the name of the switch view route is out of sync - this.Visible = false; - return; - } - var url = GetRouteUrl(switchViewRouteName, new { view = AlternateView, __FriendlyUrls_SwitchViews = true }); - url += "?ReturnUrl=" + HttpUtility.UrlEncode(Request.RawUrl); - SwitchUrl = url; + // Create switch URL from the route, e.g. ~/__FriendlyUrls_SwitchView/Mobile?ReturnUrl=/Page + var switchViewRouteName = "AspNet.FriendlyUrls.SwitchView"; + var switchViewRoute = RouteTable.Routes[switchViewRouteName]; + if (switchViewRoute == null) + { + // Friendly URLs is not enabled or the name of the switch view route is out of sync + this.Visible = false; + return; } + var url = GetRouteUrl(switchViewRouteName, new { view = AlternateView, __FriendlyUrls_SwitchViews = true }); + url += "?ReturnUrl=" + HttpUtility.UrlEncode(Request.RawUrl); + SwitchUrl = url; } } \ No newline at end of file diff --git a/samples/Fornax/Fornax.Server/ViewSwitcher.ascx.designer.cs b/samples/Fornax/Fornax.Server/ViewSwitcher.ascx.designer.cs index 418ff1038..769ae7606 100644 --- a/samples/Fornax/Fornax.Server/ViewSwitcher.ascx.designer.cs +++ b/samples/Fornax/Fornax.Server/ViewSwitcher.ascx.designer.cs @@ -7,9 +7,8 @@ // //------------------------------------------------------------------------------ -namespace Fornax.Server { - - - public partial class ViewSwitcher { - } +namespace Fornax.Server; + + +public partial class ViewSwitcher { } diff --git a/samples/Mortis/Mortis.Client/App_Start/BundleConfig.cs b/samples/Mortis/Mortis.Client/App_Start/BundleConfig.cs index db1bd7fbe..499308e1d 100644 --- a/samples/Mortis/Mortis.Client/App_Start/BundleConfig.cs +++ b/samples/Mortis/Mortis.Client/App_Start/BundleConfig.cs @@ -1,29 +1,28 @@ using System.Web.Optimization; -namespace Mortis.Client +namespace Mortis.Client; + +public class BundleConfig { - public class BundleConfig + // Pour plus d'informations sur le regroupement, visitez https://go.microsoft.com/fwlink/?LinkId=301862 + public static void RegisterBundles(BundleCollection bundles) { - // Pour plus d'informations sur le regroupement, visitez https://go.microsoft.com/fwlink/?LinkId=301862 - public static void RegisterBundles(BundleCollection bundles) - { - bundles.Add(new ScriptBundle("~/bundles/jquery").Include( - "~/Scripts/jquery-{version}.js")); + bundles.Add(new ScriptBundle("~/bundles/jquery").Include( + "~/Scripts/jquery-{version}.js")); - bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include( - "~/Scripts/jquery.validate*")); + bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include( + "~/Scripts/jquery.validate*")); - // Utilisez la version de développement de Modernizr pour développer et apprendre. Puis, lorsque vous êtes - // prêt pour la production, utilisez l'outil de génération à l'adresse https://modernizr.com pour sélectionner uniquement les tests dont vous avez besoin. - bundles.Add(new ScriptBundle("~/bundles/modernizr").Include( - "~/Scripts/modernizr-*")); + // Utilisez la version de développement de Modernizr pour développer et apprendre. Puis, lorsque vous êtes + // prêt pour la production, utilisez l'outil de génération à l'adresse https://modernizr.com pour sélectionner uniquement les tests dont vous avez besoin. + bundles.Add(new ScriptBundle("~/bundles/modernizr").Include( + "~/Scripts/modernizr-*")); - bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include( - "~/Scripts/bootstrap.js")); + bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include( + "~/Scripts/bootstrap.js")); - bundles.Add(new StyleBundle("~/Content/css").Include( - "~/Content/bootstrap.css", - "~/Content/site.css")); - } + bundles.Add(new StyleBundle("~/Content/css").Include( + "~/Content/bootstrap.css", + "~/Content/site.css")); } } diff --git a/samples/Mortis/Mortis.Client/App_Start/FilterConfig.cs b/samples/Mortis/Mortis.Client/App_Start/FilterConfig.cs index c3dfc62a7..d87e636f1 100644 --- a/samples/Mortis/Mortis.Client/App_Start/FilterConfig.cs +++ b/samples/Mortis/Mortis.Client/App_Start/FilterConfig.cs @@ -1,12 +1,11 @@ using System.Web.Mvc; -namespace Mortis.Client +namespace Mortis.Client; + +public class FilterConfig { - public class FilterConfig + public static void RegisterGlobalFilters(GlobalFilterCollection filters) { - public static void RegisterGlobalFilters(GlobalFilterCollection filters) - { - filters.Add(new HandleErrorAttribute()); - } + filters.Add(new HandleErrorAttribute()); } } diff --git a/samples/Mortis/Mortis.Client/App_Start/RouteConfig.cs b/samples/Mortis/Mortis.Client/App_Start/RouteConfig.cs index b0a8a6def..a051d6292 100644 --- a/samples/Mortis/Mortis.Client/App_Start/RouteConfig.cs +++ b/samples/Mortis/Mortis.Client/App_Start/RouteConfig.cs @@ -1,21 +1,20 @@ using System.Web.Mvc; using System.Web.Routing; -namespace Mortis.Client +namespace Mortis.Client; + +public class RouteConfig { - public class RouteConfig + public static void RegisterRoutes(RouteCollection routes) { - public static void RegisterRoutes(RouteCollection routes) - { - routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); + routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); - routes.MapMvcAttributeRoutes(); + routes.MapMvcAttributeRoutes(); - routes.MapRoute( - name: "Default", - url: "{controller}/{action}/{id}", - defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } - ); - } + routes.MapRoute( + name: "Default", + url: "{controller}/{action}/{id}", + defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } + ); } } diff --git a/samples/Mortis/Mortis.Client/Controllers/AuthenticationController.cs b/samples/Mortis/Mortis.Client/Controllers/AuthenticationController.cs index 4a1e45ccb..bb2828fa2 100644 --- a/samples/Mortis/Mortis.Client/Controllers/AuthenticationController.cs +++ b/samples/Mortis/Mortis.Client/Controllers/AuthenticationController.cs @@ -10,154 +10,153 @@ using OpenIddict.Client.Owin; using static OpenIddict.Abstractions.OpenIddictConstants; -namespace Mortis.Client.Controllers +namespace Mortis.Client.Controllers; + +public class AuthenticationController : Controller { - public class AuthenticationController : Controller + [HttpGet, Route("~/login")] + public ActionResult LogIn(string returnUrl) { - [HttpGet, Route("~/login")] - public ActionResult LogIn(string returnUrl) + var context = HttpContext.GetOwinContext(); + + var properties = new AuthenticationProperties { - var context = HttpContext.GetOwinContext(); + // Only allow local return URLs to prevent open redirect attacks. + RedirectUri = Url.IsLocalUrl(returnUrl) ? returnUrl : "/" + }; - var properties = new AuthenticationProperties - { - // Only allow local return URLs to prevent open redirect attacks. - RedirectUri = Url.IsLocalUrl(returnUrl) ? returnUrl : "/" - }; + // Ask the OpenIddict client middleware to redirect the user agent to the identity provider. + context.Authentication.Challenge(properties, OpenIddictClientOwinDefaults.AuthenticationType); + return new EmptyResult(); + } - // Ask the OpenIddict client middleware to redirect the user agent to the identity provider. - context.Authentication.Challenge(properties, OpenIddictClientOwinDefaults.AuthenticationType); - return new EmptyResult(); - } + [HttpPost, Route("~/logout"), ValidateAntiForgeryToken] + public async Task LogOut(string returnUrl) + { + var context = HttpContext.GetOwinContext(); - [HttpPost, Route("~/logout"), ValidateAntiForgeryToken] - public async Task LogOut(string returnUrl) + // Retrieve the identity stored in the local authentication cookie. If it's not available, + // this indicate that the user is already logged out locally (or has not logged in yet). + var result = await context.Authentication.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationType); + if (result is not { Identity: ClaimsIdentity }) { - var context = HttpContext.GetOwinContext(); - - // Retrieve the identity stored in the local authentication cookie. If it's not available, - // this indicate that the user is already logged out locally (or has not logged in yet). - var result = await context.Authentication.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationType); - if (result is not { Identity: ClaimsIdentity }) - { - // Only allow local return URLs to prevent open redirect attacks. - return Redirect(Url.IsLocalUrl(returnUrl) ? returnUrl : "/"); - } - - // Remove the local authentication cookie before triggering a redirection to the remote server. - context.Authentication.SignOut(CookieAuthenticationDefaults.AuthenticationType); - - var properties = new AuthenticationProperties(new Dictionary - { - // While not required, the specification encourages sending an id_token_hint - // parameter containing an identity token returned by the server for this user. - [OpenIddictClientOwinConstants.Properties.IdentityTokenHint] = - result.Properties.Dictionary[OpenIddictClientOwinConstants.Tokens.BackchannelIdentityToken] - }) - { - // Only allow local return URLs to prevent open redirect attacks. - RedirectUri = Url.IsLocalUrl(returnUrl) ? returnUrl : "/" - }; - - // Ask the OpenIddict client middleware to redirect the user agent to the identity provider. - context.Authentication.SignOut(properties, OpenIddictClientOwinDefaults.AuthenticationType); - return Redirect(properties.RedirectUri); + // Only allow local return URLs to prevent open redirect attacks. + return Redirect(Url.IsLocalUrl(returnUrl) ? returnUrl : "/"); } - // Note: this controller uses the same callback action for all providers - // but for users who prefer using a different action per provider, - // the following action can be split into separate actions. - [AcceptVerbs("GET", "POST"), Route("~/callback/login/{provider}")] - public async Task LogInCallback() + // Remove the local authentication cookie before triggering a redirection to the remote server. + context.Authentication.SignOut(CookieAuthenticationDefaults.AuthenticationType); + + var properties = new AuthenticationProperties(new Dictionary { - var context = HttpContext.GetOwinContext(); + // While not required, the specification encourages sending an id_token_hint + // parameter containing an identity token returned by the server for this user. + [OpenIddictClientOwinConstants.Properties.IdentityTokenHint] = + result.Properties.Dictionary[OpenIddictClientOwinConstants.Tokens.BackchannelIdentityToken] + }) + { + // Only allow local return URLs to prevent open redirect attacks. + RedirectUri = Url.IsLocalUrl(returnUrl) ? returnUrl : "/" + }; - // Retrieve the authorization data validated by OpenIddict as part of the callback handling. - var result = await context.Authentication.AuthenticateAsync(OpenIddictClientOwinDefaults.AuthenticationType); + // Ask the OpenIddict client middleware to redirect the user agent to the identity provider. + context.Authentication.SignOut(properties, OpenIddictClientOwinDefaults.AuthenticationType); + return Redirect(properties.RedirectUri); + } - // Multiple strategies exist to handle OAuth 2.0/OpenID Connect callbacks, each with their pros and cons: - // - // * Directly using the tokens to perform the necessary action(s) on behalf of the user, which is suitable - // for applications that don't need a long-term access to the user's resources or don't want to store - // access/refresh tokens in a database or in an authentication cookie (which has security implications). - // It is also suitable for applications that don't need to authenticate users but only need to perform - // action(s) on their behalf by making API calls using the access token returned by the remote server. - // - // * Storing the external claims/tokens in a database (and optionally keeping the essential claims in an - // authentication cookie so that cookie size limits are not hit). For the applications that use ASP.NET - // Core Identity, the UserManager.SetAuthenticationTokenAsync() API can be used to store external tokens. - // - // Note: in this case, it's recommended to use column encryption to protect the tokens in the database. + // Note: this controller uses the same callback action for all providers + // but for users who prefer using a different action per provider, + // the following action can be split into separate actions. + [AcceptVerbs("GET", "POST"), Route("~/callback/login/{provider}")] + public async Task LogInCallback() + { + var context = HttpContext.GetOwinContext(); + + // Retrieve the authorization data validated by OpenIddict as part of the callback handling. + var result = await context.Authentication.AuthenticateAsync(OpenIddictClientOwinDefaults.AuthenticationType); + + // Multiple strategies exist to handle OAuth 2.0/OpenID Connect callbacks, each with their pros and cons: + // + // * Directly using the tokens to perform the necessary action(s) on behalf of the user, which is suitable + // for applications that don't need a long-term access to the user's resources or don't want to store + // access/refresh tokens in a database or in an authentication cookie (which has security implications). + // It is also suitable for applications that don't need to authenticate users but only need to perform + // action(s) on their behalf by making API calls using the access token returned by the remote server. + // + // * Storing the external claims/tokens in a database (and optionally keeping the essential claims in an + // authentication cookie so that cookie size limits are not hit). For the applications that use ASP.NET + // Core Identity, the UserManager.SetAuthenticationTokenAsync() API can be used to store external tokens. + // + // Note: in this case, it's recommended to use column encryption to protect the tokens in the database. + // + // * Storing the external claims/tokens in an authentication cookie, which doesn't require having + // a user database but may be affected by the cookie size limits enforced by most browser vendors + // (e.g Safari for macOS and Safari for iOS/iPadOS enforce a per-domain 4KB limit for all cookies). + // + // Note: this is the approach used here, but the external claims are first filtered to only persist + // a few claims like the user identifier. The same approach is used to store the access/refresh tokens. + + // Important: if the remote server doesn't support OpenID Connect and doesn't expose a userinfo endpoint, + // result.Principal.Identity will represent an unauthenticated identity and won't contain any user claim. + // + // Such identities cannot be used as-is to build an authentication cookie in ASP.NET (as the + // antiforgery stack requires at least a name claim to bind CSRF cookies to the user's identity) but + // the access/refresh tokens can be retrieved using result.Properties.GetTokens() to make API calls. + if (result.Identity is not ClaimsIdentity { IsAuthenticated: true }) + { + throw new InvalidOperationException("The external authorization data cannot be used for authentication."); + } + + // Build an identity based on the external claims and that will be used to create the authentication cookie. + // + // By default, all claims extracted during the authorization dance are available. The claims collection stored + // in the cookie can be filtered out or mapped to different names depending the claim name or its issuer. + var claims = result.Identity.Claims.Where(claim => claim.Type is ClaimTypes.NameIdentifier or ClaimTypes.Name // - // * Storing the external claims/tokens in an authentication cookie, which doesn't require having - // a user database but may be affected by the cookie size limits enforced by most browser vendors - // (e.g Safari for macOS and Safari for iOS/iPadOS enforce a per-domain 4KB limit for all cookies). + // Preserve the registration details to be able to resolve them later. // - // Note: this is the approach used here, but the external claims are first filtered to only persist - // a few claims like the user identifier. The same approach is used to store the access/refresh tokens. - - // Important: if the remote server doesn't support OpenID Connect and doesn't expose a userinfo endpoint, - // result.Principal.Identity will represent an unauthenticated identity and won't contain any user claim. + or Claims.Private.RegistrationId or Claims.Private.ProviderName // - // Such identities cannot be used as-is to build an authentication cookie in ASP.NET (as the - // antiforgery stack requires at least a name claim to bind CSRF cookies to the user's identity) but - // the access/refresh tokens can be retrieved using result.Properties.GetTokens() to make API calls. - if (result.Identity is not ClaimsIdentity { IsAuthenticated: true }) - { - throw new InvalidOperationException("The external authorization data cannot be used for authentication."); - } - - // Build an identity based on the external claims and that will be used to create the authentication cookie. + // The ASP.NET 4.x antiforgery module requires preserving the "identityprovider" claim. // - // By default, all claims extracted during the authorization dance are available. The claims collection stored - // in the cookie can be filtered out or mapped to different names depending the claim name or its issuer. - var claims = result.Identity.Claims.Where(claim => claim.Type is ClaimTypes.NameIdentifier or ClaimTypes.Name - // - // Preserve the registration details to be able to resolve them later. - // - or Claims.Private.RegistrationId or Claims.Private.ProviderName - // - // The ASP.NET 4.x antiforgery module requires preserving the "identityprovider" claim. - // - or "http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider"); - - var identity = new ClaimsIdentity(claims, - authenticationType: CookieAuthenticationDefaults.AuthenticationType, - nameType: ClaimTypes.Name, - roleType: ClaimTypes.Role); - - // Build the authentication properties based on the properties that were added when the challenge was triggered. - var properties = new AuthenticationProperties(result.Properties.Dictionary - .Where(item => item.Key is - // Preserve the return URL. - ".redirect" or - - // If needed, the tokens returned by the authorization server can be stored in the authentication cookie. - OpenIddictClientOwinConstants.Tokens.BackchannelAccessToken or - OpenIddictClientOwinConstants.Tokens.BackchannelIdentityToken or - OpenIddictClientOwinConstants.Tokens.RefreshToken) - .ToDictionary(pair => pair.Key, pair => pair.Value)); - - context.Authentication.SignIn(properties, identity); - return Redirect(properties.RedirectUri ?? "/"); - } + or "http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider"); + + var identity = new ClaimsIdentity(claims, + authenticationType: CookieAuthenticationDefaults.AuthenticationType, + nameType: ClaimTypes.Name, + roleType: ClaimTypes.Role); + + // Build the authentication properties based on the properties that were added when the challenge was triggered. + var properties = new AuthenticationProperties(result.Properties.Dictionary + .Where(item => item.Key is + // Preserve the return URL. + ".redirect" or + + // If needed, the tokens returned by the authorization server can be stored in the authentication cookie. + OpenIddictClientOwinConstants.Tokens.BackchannelAccessToken or + OpenIddictClientOwinConstants.Tokens.BackchannelIdentityToken or + OpenIddictClientOwinConstants.Tokens.RefreshToken) + .ToDictionary(pair => pair.Key, pair => pair.Value)); + + context.Authentication.SignIn(properties, identity); + return Redirect(properties.RedirectUri ?? "/"); + } - // Note: this controller uses the same callback action for all providers - // but for users who prefer using a different action per provider, - // the following action can be split into separate actions. - [AcceptVerbs("GET", "POST"), Route("~/callback/logout/{provider}")] - public async Task LogOutCallback() - { - var context = HttpContext.GetOwinContext(); + // Note: this controller uses the same callback action for all providers + // but for users who prefer using a different action per provider, + // the following action can be split into separate actions. + [AcceptVerbs("GET", "POST"), Route("~/callback/logout/{provider}")] + public async Task LogOutCallback() + { + var context = HttpContext.GetOwinContext(); - // Retrieve the data stored by OpenIddict in the state token created when the logout was triggered. - var result = await context.Authentication.AuthenticateAsync(OpenIddictClientOwinDefaults.AuthenticationType); + // Retrieve the data stored by OpenIddict in the state token created when the logout was triggered. + var result = await context.Authentication.AuthenticateAsync(OpenIddictClientOwinDefaults.AuthenticationType); - // In this sample, the local authentication cookie is always removed before the user agent is redirected - // to the authorization server. Applications that prefer delaying the removal of the local cookie can - // remove the corresponding code from the logout action and remove the authentication cookie in this action. + // In this sample, the local authentication cookie is always removed before the user agent is redirected + // to the authorization server. Applications that prefer delaying the removal of the local cookie can + // remove the corresponding code from the logout action and remove the authentication cookie in this action. - return Redirect(result!.Properties!.RedirectUri); - } + return Redirect(result!.Properties!.RedirectUri); } } diff --git a/samples/Mortis/Mortis.Client/Controllers/HomeController.cs b/samples/Mortis/Mortis.Client/Controllers/HomeController.cs index 20f22b007..d330b6188 100644 --- a/samples/Mortis/Mortis.Client/Controllers/HomeController.cs +++ b/samples/Mortis/Mortis.Client/Controllers/HomeController.cs @@ -7,36 +7,35 @@ using Microsoft.Owin.Security.Cookies; using static OpenIddict.Client.Owin.OpenIddictClientOwinConstants; -namespace Mortis.Client.Controllers +namespace Mortis.Client.Controllers; + +public class HomeController : Controller { - public class HomeController : Controller - { - private readonly IHttpClientFactory _httpClientFactory; + private readonly IHttpClientFactory _httpClientFactory; - public HomeController(IHttpClientFactory httpClientFactory) - => _httpClientFactory = httpClientFactory; + public HomeController(IHttpClientFactory httpClientFactory) + => _httpClientFactory = httpClientFactory; - [HttpGet, Route("~/")] - public ActionResult Index() => View(); + [HttpGet, Route("~/")] + public ActionResult Index() => View(); - [Authorize, HttpPost, Route("~/")] - [ValidateAntiForgeryToken] - public async Task Index(CancellationToken cancellationToken) - { - var context = HttpContext.GetOwinContext(); + [Authorize, HttpPost, Route("~/")] + [ValidateAntiForgeryToken] + public async Task Index(CancellationToken cancellationToken) + { + var context = HttpContext.GetOwinContext(); - var result = await context.Authentication.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationType); - var token = result.Properties.Dictionary[Tokens.BackchannelAccessToken]; + var result = await context.Authentication.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationType); + var token = result.Properties.Dictionary[Tokens.BackchannelAccessToken]; - using var client = _httpClientFactory.CreateClient(); + using var client = _httpClientFactory.CreateClient(); - using var request = new HttpRequestMessage(HttpMethod.Get, "https://localhost:44349/api/message"); - request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token); + using var request = new HttpRequestMessage(HttpMethod.Get, "https://localhost:44349/api/message"); + request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token); - using var response = await client.SendAsync(request, cancellationToken); - response.EnsureSuccessStatusCode(); + using var response = await client.SendAsync(request, cancellationToken); + response.EnsureSuccessStatusCode(); - return View(model: await response.Content.ReadAsStringAsync()); - } + return View(model: await response.Content.ReadAsStringAsync()); } } diff --git a/samples/Mortis/Mortis.Client/Global.asax.cs b/samples/Mortis/Mortis.Client/Global.asax.cs index b587a28d1..5d42e1e2c 100644 --- a/samples/Mortis/Mortis.Client/Global.asax.cs +++ b/samples/Mortis/Mortis.Client/Global.asax.cs @@ -2,16 +2,15 @@ using System.Web.Optimization; using System.Web.Routing; -namespace Mortis.Client +namespace Mortis.Client; + +public class MvcApplication : System.Web.HttpApplication { - public class MvcApplication : System.Web.HttpApplication + protected void Application_Start() { - protected void Application_Start() - { - AreaRegistration.RegisterAllAreas(); - FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); - RouteConfig.RegisterRoutes(RouteTable.Routes); - BundleConfig.RegisterBundles(BundleTable.Bundles); - } + AreaRegistration.RegisterAllAreas(); + FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); + RouteConfig.RegisterRoutes(RouteTable.Routes); + BundleConfig.RegisterBundles(BundleTable.Bundles); } } diff --git a/samples/Mortis/Mortis.Client/Models/ApplicationDbContext.cs b/samples/Mortis/Mortis.Client/Models/ApplicationDbContext.cs index e9e3d9d0b..a9f0ee636 100644 --- a/samples/Mortis/Mortis.Client/Models/ApplicationDbContext.cs +++ b/samples/Mortis/Mortis.Client/Models/ApplicationDbContext.cs @@ -1,19 +1,18 @@ using System.Data.Entity; -namespace Mortis.Client.Models +namespace Mortis.Client.Models; + +public class ApplicationDbContext : DbContext { - public class ApplicationDbContext : DbContext + public ApplicationDbContext() + : base("DefaultConnection") { - public ApplicationDbContext() - : base("DefaultConnection") - { - } + } - protected override void OnModelCreating(DbModelBuilder modelBuilder) - { - modelBuilder.UseOpenIddict(); + protected override void OnModelCreating(DbModelBuilder modelBuilder) + { + modelBuilder.UseOpenIddict(); - base.OnModelCreating(modelBuilder); - } + base.OnModelCreating(modelBuilder); } } diff --git a/samples/Mortis/Mortis.Client/Startup.cs b/samples/Mortis/Mortis.Client/Startup.cs index d3724d48b..5028656ea 100644 --- a/samples/Mortis/Mortis.Client/Startup.cs +++ b/samples/Mortis/Mortis.Client/Startup.cs @@ -13,107 +13,106 @@ using Owin; using static OpenIddict.Abstractions.OpenIddictConstants; -namespace Mortis.Client +namespace Mortis.Client; + +public class Startup { - public class Startup + public void Configuration(IAppBuilder app) { - public void Configuration(IAppBuilder app) - { - var services = new ServiceCollection(); + var services = new ServiceCollection(); - services.AddOpenIddict() + services.AddOpenIddict() - // Register the OpenIddict core components. - .AddCore(options => - { - // Configure OpenIddict to use the Entity Framework 6.x stores and models. - // Note: call ReplaceDefaultEntities() to replace the default OpenIddict entities. - options.UseEntityFramework() - .UseDbContext(); - - // Developers who prefer using MongoDB can remove the previous lines - // and configure OpenIddict to use the specified MongoDB database: - // options.UseMongoDb() - // .UseDatabase(new MongoClient().GetDatabase("openiddict")); - }) - - // Register the OpenIddict client components. - .AddClient(options => + // Register the OpenIddict core components. + .AddCore(options => + { + // Configure OpenIddict to use the Entity Framework 6.x stores and models. + // Note: call ReplaceDefaultEntities() to replace the default OpenIddict entities. + options.UseEntityFramework() + .UseDbContext(); + + // Developers who prefer using MongoDB can remove the previous lines + // and configure OpenIddict to use the specified MongoDB database: + // options.UseMongoDb() + // .UseDatabase(new MongoClient().GetDatabase("openiddict")); + }) + + // Register the OpenIddict client components. + .AddClient(options => + { + // Note: this sample uses the code flow, but you can enable the other flows if necessary. + options.AllowAuthorizationCodeFlow(); + + // Register the signing and encryption credentials used to protect + // sensitive data like the state tokens produced by OpenIddict. + options.AddDevelopmentEncryptionCertificate() + .AddDevelopmentSigningCertificate(); + + // Register the OWIN host and configure the OWIN-specific options. + options.UseOwin() + .EnableRedirectionEndpointPassthrough() + .EnablePostLogoutRedirectionEndpointPassthrough() + .SetCookieManager(new SystemWebCookieManager()); + + // Register the System.Net.Http integration and use the identity of the current + // assembly as a more specific user agent, which can be useful when dealing with + // providers that use the user agent as a way to throttle requests (e.g Reddit). + options.UseSystemNetHttp() + .SetProductInformation(typeof(Startup).Assembly); + + // Add a client registration matching the client application definition in the server project. + options.AddRegistration(new OpenIddictClientRegistration { - // Note: this sample uses the code flow, but you can enable the other flows if necessary. - options.AllowAuthorizationCodeFlow(); - - // Register the signing and encryption credentials used to protect - // sensitive data like the state tokens produced by OpenIddict. - options.AddDevelopmentEncryptionCertificate() - .AddDevelopmentSigningCertificate(); - - // Register the OWIN host and configure the OWIN-specific options. - options.UseOwin() - .EnableRedirectionEndpointPassthrough() - .EnablePostLogoutRedirectionEndpointPassthrough() - .SetCookieManager(new SystemWebCookieManager()); - - // Register the System.Net.Http integration and use the identity of the current - // assembly as a more specific user agent, which can be useful when dealing with - // providers that use the user agent as a way to throttle requests (e.g Reddit). - options.UseSystemNetHttp() - .SetProductInformation(typeof(Startup).Assembly); - - // Add a client registration matching the client application definition in the server project. - options.AddRegistration(new OpenIddictClientRegistration - { - Issuer = new Uri("https://localhost:44349/", UriKind.Absolute), - ProviderName = "Local", - ProviderDisplayName = "Local OIDC server", - - ClientId = "mvc", - ClientSecret = "901564A5-E7FE-42CB-B10D-61EF6A8F3654", - Scopes = { Scopes.Email, Scopes.Profile }, - - // Note: to mitigate mix-up attacks, it's recommended to use a unique redirection endpoint - // URI per provider, unless all the registered providers support returning a special "iss" - // parameter containing their URL as part of authorization responses. For more information, - // see https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics#section-4.4. - RedirectUri = new Uri("callback/login/local", UriKind.Relative), - PostLogoutRedirectUri = new Uri("callback/logout/local", UriKind.Relative) - }); + Issuer = new Uri("https://localhost:44349/", UriKind.Absolute), + ProviderName = "Local", + ProviderDisplayName = "Local OIDC server", + + ClientId = "mvc", + ClientSecret = "901564A5-E7FE-42CB-B10D-61EF6A8F3654", + Scopes = { Scopes.Email, Scopes.Profile }, + + // Note: to mitigate mix-up attacks, it's recommended to use a unique redirection endpoint + // URI per provider, unless all the registered providers support returning a special "iss" + // parameter containing their URL as part of authorization responses. For more information, + // see https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics#section-4.4. + RedirectUri = new Uri("callback/login/local", UriKind.Relative), + PostLogoutRedirectUri = new Uri("callback/logout/local", UriKind.Relative) }); + }); - // Create a new Autofac container and import the OpenIddict services. - var builder = new ContainerBuilder(); - builder.Populate(services); + // Create a new Autofac container and import the OpenIddict services. + var builder = new ContainerBuilder(); + builder.Populate(services); - // Register the MVC controllers. - builder.RegisterControllers(typeof(Startup).Assembly); + // Register the MVC controllers. + builder.RegisterControllers(typeof(Startup).Assembly); - var container = builder.Build(); + var container = builder.Build(); - // Register the Autofac scope injector middleware. - app.UseAutofacLifetimeScopeInjector(container); + // Register the Autofac scope injector middleware. + app.UseAutofacLifetimeScopeInjector(container); - // Register the cookie middleware responsible for storing the user sessions. - app.UseCookieAuthentication(new CookieAuthenticationOptions - { - ExpireTimeSpan = TimeSpan.FromMinutes(50), - SlidingExpiration = false - }); + // Register the cookie middleware responsible for storing the user sessions. + app.UseCookieAuthentication(new CookieAuthenticationOptions + { + ExpireTimeSpan = TimeSpan.FromMinutes(50), + SlidingExpiration = false + }); - // Register the OpenIddict middleware. - app.UseMiddlewareFromContainer(); + // Register the OpenIddict middleware. + app.UseMiddlewareFromContainer(); - // Configure ASP.NET MVC 5.2 to use Autofac when activating controller instances. - DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); + // Configure ASP.NET MVC to use Autofac when activating controller instances. + DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); - // Create the database used by the OpenIddict client stack to store tokens. - // Note: in a real world application, this step should be part of a setup script. - Task.Run(async delegate - { - await using var scope = container.BeginLifetimeScope(); + // Create the database used by the OpenIddict client stack to store tokens. + // Note: in a real world application, this step should be part of a setup script. + Task.Run(async delegate + { + await using var scope = container.BeginLifetimeScope(); - var context = scope.Resolve(); - context.Database.CreateIfNotExists(); - }).GetAwaiter().GetResult(); - } + var context = scope.Resolve(); + context.Database.CreateIfNotExists(); + }).GetAwaiter().GetResult(); } } diff --git a/samples/Mortis/Mortis.Server/App_Start/BundleConfig.cs b/samples/Mortis/Mortis.Server/App_Start/BundleConfig.cs index 9432e4bee..3ac824e33 100644 --- a/samples/Mortis/Mortis.Server/App_Start/BundleConfig.cs +++ b/samples/Mortis/Mortis.Server/App_Start/BundleConfig.cs @@ -1,29 +1,28 @@ using System.Web.Optimization; -namespace Mortis.Server +namespace Mortis.Server; + +public class BundleConfig { - public class BundleConfig + // Pour plus d'informations sur le regroupement, visitez https://go.microsoft.com/fwlink/?LinkId=301862 + public static void RegisterBundles(BundleCollection bundles) { - // Pour plus d'informations sur le regroupement, visitez https://go.microsoft.com/fwlink/?LinkId=301862 - public static void RegisterBundles(BundleCollection bundles) - { - bundles.Add(new ScriptBundle("~/bundles/jquery").Include( - "~/Scripts/jquery-{version}.js")); + bundles.Add(new ScriptBundle("~/bundles/jquery").Include( + "~/Scripts/jquery-{version}.js")); - bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include( - "~/Scripts/jquery.validate*")); + bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include( + "~/Scripts/jquery.validate*")); - // Utilisez la version de développement de Modernizr pour développer et apprendre. Puis, lorsque vous êtes - // prêt pour la production, utilisez l'outil de génération à l'adresse https://modernizr.com pour sélectionner uniquement les tests dont vous avez besoin. - bundles.Add(new ScriptBundle("~/bundles/modernizr").Include( - "~/Scripts/modernizr-*")); + // Utilisez la version de développement de Modernizr pour développer et apprendre. Puis, lorsque vous êtes + // prêt pour la production, utilisez l'outil de génération à l'adresse https://modernizr.com pour sélectionner uniquement les tests dont vous avez besoin. + bundles.Add(new ScriptBundle("~/bundles/modernizr").Include( + "~/Scripts/modernizr-*")); - bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include( - "~/Scripts/bootstrap.js")); + bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include( + "~/Scripts/bootstrap.js")); - bundles.Add(new StyleBundle("~/Content/css").Include( - "~/Content/bootstrap.css", - "~/Content/site.css")); - } + bundles.Add(new StyleBundle("~/Content/css").Include( + "~/Content/bootstrap.css", + "~/Content/site.css")); } } diff --git a/samples/Mortis/Mortis.Server/App_Start/FilterConfig.cs b/samples/Mortis/Mortis.Server/App_Start/FilterConfig.cs index 107d0766e..c0f032ebc 100644 --- a/samples/Mortis/Mortis.Server/App_Start/FilterConfig.cs +++ b/samples/Mortis/Mortis.Server/App_Start/FilterConfig.cs @@ -1,12 +1,11 @@ using System.Web.Mvc; -namespace Mortis.Server +namespace Mortis.Server; + +public class FilterConfig { - public class FilterConfig + public static void RegisterGlobalFilters(GlobalFilterCollection filters) { - public static void RegisterGlobalFilters(GlobalFilterCollection filters) - { - filters.Add(new HandleErrorAttribute()); - } + filters.Add(new HandleErrorAttribute()); } } diff --git a/samples/Mortis/Mortis.Server/App_Start/IdentityConfig.cs b/samples/Mortis/Mortis.Server/App_Start/IdentityConfig.cs index f9c96139c..270aa772a 100644 --- a/samples/Mortis/Mortis.Server/App_Start/IdentityConfig.cs +++ b/samples/Mortis/Mortis.Server/App_Start/IdentityConfig.cs @@ -8,98 +8,97 @@ using Microsoft.Owin.Security; using Mortis.Server.Models; -namespace Mortis.Server +namespace Mortis.Server; + +public class EmailService : IIdentityMessageService { - public class EmailService : IIdentityMessageService + public Task SendAsync(IdentityMessage message) { - public Task SendAsync(IdentityMessage message) - { - // Connectez votre service e-mail ici pour envoyer un e-mail. - return Task.FromResult(0); - } + // Connectez votre service e-mail ici pour envoyer un e-mail. + return Task.FromResult(0); } +} - public class SmsService : IIdentityMessageService +public class SmsService : IIdentityMessageService +{ + public Task SendAsync(IdentityMessage message) { - public Task SendAsync(IdentityMessage message) - { - // Connectez votre service SMS ici pour envoyer un message texte. - return Task.FromResult(0); - } + // Connectez votre service SMS ici pour envoyer un message texte. + return Task.FromResult(0); } +} - // Configurer l'application que le gestionnaire des utilisateurs a utilisée dans cette application. UserManager est défini dans ASP.NET Identity et est utilisé par l'application. - public class ApplicationUserManager : UserManager +// Configurer l'application que le gestionnaire des utilisateurs a utilisée dans cette application. UserManager est défini dans ASP.NET Identity et est utilisé par l'application. +public class ApplicationUserManager : UserManager +{ + public ApplicationUserManager(IUserStore store) + : base(store) { - public ApplicationUserManager(IUserStore store) - : base(store) - { - } + } - public static ApplicationUserManager Create(IdentityFactoryOptions options, IOwinContext context) + public static ApplicationUserManager Create(IdentityFactoryOptions options, IOwinContext context) + { + var manager = new ApplicationUserManager(new UserStore(context.Get())); + // Configurer la logique de validation pour les noms d'utilisateur + manager.UserValidator = new UserValidator(manager) { - var manager = new ApplicationUserManager(new UserStore(context.Get())); - // Configurer la logique de validation pour les noms d'utilisateur - manager.UserValidator = new UserValidator(manager) - { - AllowOnlyAlphanumericUserNames = false, - RequireUniqueEmail = true - }; + AllowOnlyAlphanumericUserNames = false, + RequireUniqueEmail = true + }; - // Configurer la logique de validation pour les mots de passe - manager.PasswordValidator = new PasswordValidator - { - RequiredLength = 6, - RequireNonLetterOrDigit = true, - RequireDigit = true, - RequireLowercase = true, - RequireUppercase = true, - }; + // Configurer la logique de validation pour les mots de passe + manager.PasswordValidator = new PasswordValidator + { + RequiredLength = 6, + RequireNonLetterOrDigit = true, + RequireDigit = true, + RequireLowercase = true, + RequireUppercase = true, + }; - // Configurer les valeurs par défaut du verrouillage de l'utilisateur - manager.UserLockoutEnabledByDefault = true; - manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5); - manager.MaxFailedAccessAttemptsBeforeLockout = 5; + // Configurer les valeurs par défaut du verrouillage de l'utilisateur + manager.UserLockoutEnabledByDefault = true; + manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5); + manager.MaxFailedAccessAttemptsBeforeLockout = 5; - // Inscrire les fournisseurs d'authentification à 2 facteurs. Cette application utilise le téléphone et l'e-mail comme procédure de réception d'un code de vérification de l'utilisateur - // Vous pouvez écrire votre propre fournisseur et le connecter ici. - manager.RegisterTwoFactorProvider("Code téléphonique ", new PhoneNumberTokenProvider - { - MessageFormat = "Votre code de sécurité est {0}" - }); - manager.RegisterTwoFactorProvider("Code d'e-mail", new EmailTokenProvider - { - Subject = "Code de sécurité", - BodyFormat = "Votre code de sécurité est {0}" - }); - manager.EmailService = new EmailService(); - manager.SmsService = new SmsService(); - var dataProtectionProvider = options.DataProtectionProvider; - if (dataProtectionProvider != null) - { - manager.UserTokenProvider = - new DataProtectorTokenProvider(dataProtectionProvider.Create("ASP.NET Identity")); - } - return manager; + // Inscrire les fournisseurs d'authentification à 2 facteurs. Cette application utilise le téléphone et l'e-mail comme procédure de réception d'un code de vérification de l'utilisateur + // Vous pouvez écrire votre propre fournisseur et le connecter ici. + manager.RegisterTwoFactorProvider("Code téléphonique ", new PhoneNumberTokenProvider + { + MessageFormat = "Votre code de sécurité est {0}" + }); + manager.RegisterTwoFactorProvider("Code d'e-mail", new EmailTokenProvider + { + Subject = "Code de sécurité", + BodyFormat = "Votre code de sécurité est {0}" + }); + manager.EmailService = new EmailService(); + manager.SmsService = new SmsService(); + var dataProtectionProvider = options.DataProtectionProvider; + if (dataProtectionProvider != null) + { + manager.UserTokenProvider = + new DataProtectorTokenProvider(dataProtectionProvider.Create("ASP.NET Identity")); } + return manager; } +} - // Configurer le gestionnaire de connexion d'application qui est utilisé dans cette application. - public class ApplicationSignInManager : SignInManager +// Configurer le gestionnaire de connexion d'application qui est utilisé dans cette application. +public class ApplicationSignInManager : SignInManager +{ + public ApplicationSignInManager(ApplicationUserManager userManager, IAuthenticationManager authenticationManager) + : base(userManager, authenticationManager) { - public ApplicationSignInManager(ApplicationUserManager userManager, IAuthenticationManager authenticationManager) - : base(userManager, authenticationManager) - { - } + } - public override Task CreateUserIdentityAsync(ApplicationUser user) - { - return user.GenerateUserIdentityAsync((ApplicationUserManager)UserManager); - } + public override Task CreateUserIdentityAsync(ApplicationUser user) + { + return user.GenerateUserIdentityAsync((ApplicationUserManager)UserManager); + } - public static ApplicationSignInManager Create(IdentityFactoryOptions options, IOwinContext context) - { - return new ApplicationSignInManager(context.GetUserManager(), context.Authentication); - } + public static ApplicationSignInManager Create(IdentityFactoryOptions options, IOwinContext context) + { + return new ApplicationSignInManager(context.GetUserManager(), context.Authentication); } } diff --git a/samples/Mortis/Mortis.Server/App_Start/RouteConfig.cs b/samples/Mortis/Mortis.Server/App_Start/RouteConfig.cs index 18e038437..e021b7d0e 100644 --- a/samples/Mortis/Mortis.Server/App_Start/RouteConfig.cs +++ b/samples/Mortis/Mortis.Server/App_Start/RouteConfig.cs @@ -1,21 +1,20 @@ using System.Web.Mvc; using System.Web.Routing; -namespace Mortis.Server +namespace Mortis.Server; + +public class RouteConfig { - public class RouteConfig + public static void RegisterRoutes(RouteCollection routes) { - public static void RegisterRoutes(RouteCollection routes) - { - routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); + routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); - routes.MapMvcAttributeRoutes(); + routes.MapMvcAttributeRoutes(); - routes.MapRoute( - name: "Default", - url: "{controller}/{action}/{id}", - defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } - ); - } + routes.MapRoute( + name: "Default", + url: "{controller}/{action}/{id}", + defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } + ); } } diff --git a/samples/Mortis/Mortis.Server/Controllers/AccountController.cs b/samples/Mortis/Mortis.Server/Controllers/AccountController.cs index 83b44343d..58160ec6d 100644 --- a/samples/Mortis/Mortis.Server/Controllers/AccountController.cs +++ b/samples/Mortis/Mortis.Server/Controllers/AccountController.cs @@ -7,476 +7,475 @@ using Microsoft.Owin.Security; using Mortis.Server.Models; -namespace Mortis.Server.Controllers +namespace Mortis.Server.Controllers; + +[Authorize] +public class AccountController : Controller { - [Authorize] - public class AccountController : Controller + private ApplicationSignInManager _signInManager; + private ApplicationUserManager _userManager; + + public AccountController() { - private ApplicationSignInManager _signInManager; - private ApplicationUserManager _userManager; + } - public AccountController() - { - } + public AccountController(ApplicationUserManager userManager, ApplicationSignInManager signInManager ) + { + UserManager = userManager; + SignInManager = signInManager; + } - public AccountController(ApplicationUserManager userManager, ApplicationSignInManager signInManager ) + public ApplicationSignInManager SignInManager + { + get { - UserManager = userManager; - SignInManager = signInManager; + return _signInManager ?? HttpContext.GetOwinContext().Get(); + } + private set + { + _signInManager = value; } + } - public ApplicationSignInManager SignInManager + public ApplicationUserManager UserManager + { + get { - get - { - return _signInManager ?? HttpContext.GetOwinContext().Get(); - } - private set - { - _signInManager = value; - } + return _userManager ?? HttpContext.GetOwinContext().GetUserManager(); } - - public ApplicationUserManager UserManager + private set { - get - { - return _userManager ?? HttpContext.GetOwinContext().GetUserManager(); - } - private set - { - _userManager = value; - } + _userManager = value; } + } + + // + // GET: /Account/Login + [AllowAnonymous] + public ActionResult Login(string returnUrl) + { + ViewBag.ReturnUrl = returnUrl; + return View(); + } - // - // GET: /Account/Login - [AllowAnonymous] - public ActionResult Login(string returnUrl) + // + // POST: /Account/Login + [HttpPost] + [AllowAnonymous] + [ValidateAntiForgeryToken] + public async Task Login(LoginViewModel model, string returnUrl) + { + if (!ModelState.IsValid) { - ViewBag.ReturnUrl = returnUrl; - return View(); + return View(model); } - // - // POST: /Account/Login - [HttpPost] - [AllowAnonymous] - [ValidateAntiForgeryToken] - public async Task Login(LoginViewModel model, string returnUrl) + // Ceci ne comptabilise pas les échecs de connexion pour le verrouillage du compte + // Pour que les échecs de mot de passe déclenchent le verrouillage du compte, utilisez shouldLockout: true + var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false); + switch (result) { - if (!ModelState.IsValid) - { + case SignInStatus.Success: + return RedirectToLocal(returnUrl); + case SignInStatus.LockedOut: + return View("Lockout"); + case SignInStatus.RequiresVerification: + return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe }); + case SignInStatus.Failure: + default: + ModelState.AddModelError("", "Tentative de connexion non valide."); return View(model); - } - - // Ceci ne comptabilise pas les échecs de connexion pour le verrouillage du compte - // Pour que les échecs de mot de passe déclenchent le verrouillage du compte, utilisez shouldLockout: true - var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false); - switch (result) - { - case SignInStatus.Success: - return RedirectToLocal(returnUrl); - case SignInStatus.LockedOut: - return View("Lockout"); - case SignInStatus.RequiresVerification: - return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe }); - case SignInStatus.Failure: - default: - ModelState.AddModelError("", "Tentative de connexion non valide."); - return View(model); - } } + } - // - // GET: /Account/VerifyCode - [AllowAnonymous] - public async Task VerifyCode(string provider, string returnUrl, bool rememberMe) + // + // GET: /Account/VerifyCode + [AllowAnonymous] + public async Task VerifyCode(string provider, string returnUrl, bool rememberMe) + { + // Nécessiter que l'utilisateur soit déjà connecté via un nom d'utilisateur/mot de passe ou une connexte externe + if (!await SignInManager.HasBeenVerifiedAsync()) { - // Nécessiter que l'utilisateur soit déjà connecté via un nom d'utilisateur/mot de passe ou une connexte externe - if (!await SignInManager.HasBeenVerifiedAsync()) - { - return View("Error"); - } - return View(new VerifyCodeViewModel { Provider = provider, ReturnUrl = returnUrl, RememberMe = rememberMe }); + return View("Error"); } + return View(new VerifyCodeViewModel { Provider = provider, ReturnUrl = returnUrl, RememberMe = rememberMe }); + } - // - // POST: /Account/VerifyCode - [HttpPost] - [AllowAnonymous] - [ValidateAntiForgeryToken] - public async Task VerifyCode(VerifyCodeViewModel model) + // + // POST: /Account/VerifyCode + [HttpPost] + [AllowAnonymous] + [ValidateAntiForgeryToken] + public async Task VerifyCode(VerifyCodeViewModel model) + { + if (!ModelState.IsValid) { - if (!ModelState.IsValid) - { - return View(model); - } - - // Le code suivant protège des attaques par force brute contre les codes à 2 facteurs. - // Si un utilisateur entre des codes incorrects pendant un certain intervalle, le compte de cet utilisateur - // est alors verrouillé pendant une durée spécifiée. - // Vous pouvez configurer les paramètres de verrouillage du compte dans IdentityConfig - var result = await SignInManager.TwoFactorSignInAsync(model.Provider, model.Code, isPersistent: model.RememberMe, rememberBrowser: model.RememberBrowser); - switch (result) - { - case SignInStatus.Success: - return RedirectToLocal(model.ReturnUrl); - case SignInStatus.LockedOut: - return View("Lockout"); - case SignInStatus.Failure: - default: - ModelState.AddModelError("", "Code non valide."); - return View(model); - } + return View(model); } - // - // GET: /Account/Register - [AllowAnonymous] - public ActionResult Register() + // Le code suivant protège des attaques par force brute contre les codes à 2 facteurs. + // Si un utilisateur entre des codes incorrects pendant un certain intervalle, le compte de cet utilisateur + // est alors verrouillé pendant une durée spécifiée. + // Vous pouvez configurer les paramètres de verrouillage du compte dans IdentityConfig + var result = await SignInManager.TwoFactorSignInAsync(model.Provider, model.Code, isPersistent: model.RememberMe, rememberBrowser: model.RememberBrowser); + switch (result) { - return View(); + case SignInStatus.Success: + return RedirectToLocal(model.ReturnUrl); + case SignInStatus.LockedOut: + return View("Lockout"); + case SignInStatus.Failure: + default: + ModelState.AddModelError("", "Code non valide."); + return View(model); } + } + + // + // GET: /Account/Register + [AllowAnonymous] + public ActionResult Register() + { + return View(); + } - // - // POST: /Account/Register - [HttpPost] - [AllowAnonymous] - [ValidateAntiForgeryToken] - public async Task Register(RegisterViewModel model) + // + // POST: /Account/Register + [HttpPost] + [AllowAnonymous] + [ValidateAntiForgeryToken] + public async Task Register(RegisterViewModel model) + { + if (ModelState.IsValid) { - if (ModelState.IsValid) + var user = new ApplicationUser { UserName = model.Email, Email = model.Email }; + var result = await UserManager.CreateAsync(user, model.Password); + if (result.Succeeded) { - var user = new ApplicationUser { UserName = model.Email, Email = model.Email }; - var result = await UserManager.CreateAsync(user, model.Password); - if (result.Succeeded) - { - await SignInManager.SignInAsync(user, isPersistent:false, rememberBrowser:false); - - // Pour plus d'informations sur l'activation de la confirmation de compte et de la réinitialisation de mot de passe, visitez https://go.microsoft.com/fwlink/?LinkID=320771 - // Envoyer un e-mail avec ce lien - // string code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id); - // var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme); - // await UserManager.SendEmailAsync(user.Id, "Confirmer votre compte", "Confirmez votre compte en cliquant ici"); - - return RedirectToAction("Index", "Home"); - } - AddErrors(result); + await SignInManager.SignInAsync(user, isPersistent:false, rememberBrowser:false); + + // Pour plus d'informations sur l'activation de la confirmation de compte et de la réinitialisation de mot de passe, visitez https://go.microsoft.com/fwlink/?LinkID=320771 + // Envoyer un e-mail avec ce lien + // string code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id); + // var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme); + // await UserManager.SendEmailAsync(user.Id, "Confirmer votre compte", "Confirmez votre compte en cliquant ici"); + + return RedirectToAction("Index", "Home"); } + AddErrors(result); + } - // Si nous sommes arrivés là, quelque chose a échoué, réafficher le formulaire - return View(model); + // Si nous sommes arrivés là, quelque chose a échoué, réafficher le formulaire + return View(model); + } + + // + // GET: /Account/ConfirmEmail + [AllowAnonymous] + public async Task ConfirmEmail(string userId, string code) + { + if (userId == null || code == null) + { + return View("Error"); } + var result = await UserManager.ConfirmEmailAsync(userId, code); + return View(result.Succeeded ? "ConfirmEmail" : "Error"); + } + + // + // GET: /Account/ForgotPassword + [AllowAnonymous] + public ActionResult ForgotPassword() + { + return View(); + } - // - // GET: /Account/ConfirmEmail - [AllowAnonymous] - public async Task ConfirmEmail(string userId, string code) + // + // POST: /Account/ForgotPassword + [HttpPost] + [AllowAnonymous] + [ValidateAntiForgeryToken] + public async Task ForgotPassword(ForgotPasswordViewModel model) + { + if (ModelState.IsValid) { - if (userId == null || code == null) + var user = await UserManager.FindByNameAsync(model.Email); + if (user == null || !(await UserManager.IsEmailConfirmedAsync(user.Id))) { - return View("Error"); + // Ne révélez pas que l'utilisateur n'existe pas ou qu'il n'est pas confirmé + return View("ForgotPasswordConfirmation"); } - var result = await UserManager.ConfirmEmailAsync(userId, code); - return View(result.Succeeded ? "ConfirmEmail" : "Error"); - } - // - // GET: /Account/ForgotPassword - [AllowAnonymous] - public ActionResult ForgotPassword() - { - return View(); + // Pour plus d'informations sur l'activation de la confirmation de compte et de la réinitialisation de mot de passe, visitez https://go.microsoft.com/fwlink/?LinkID=320771 + // Envoyer un e-mail avec ce lien + // string code = await UserManager.GeneratePasswordResetTokenAsync(user.Id); + // var callbackUrl = Url.Action("ResetPassword", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme); + // await UserManager.SendEmailAsync(user.Id, "Réinitialiser le mot de passe", "Réinitialisez votre mot de passe en cliquant ici"); + // return RedirectToAction("ForgotPasswordConfirmation", "Account"); } - // - // POST: /Account/ForgotPassword - [HttpPost] - [AllowAnonymous] - [ValidateAntiForgeryToken] - public async Task ForgotPassword(ForgotPasswordViewModel model) - { - if (ModelState.IsValid) - { - var user = await UserManager.FindByNameAsync(model.Email); - if (user == null || !(await UserManager.IsEmailConfirmedAsync(user.Id))) - { - // Ne révélez pas que l'utilisateur n'existe pas ou qu'il n'est pas confirmé - return View("ForgotPasswordConfirmation"); - } + // Si nous sommes arrivés là, quelque chose a échoué, réafficher le formulaire + return View(model); + } - // Pour plus d'informations sur l'activation de la confirmation de compte et de la réinitialisation de mot de passe, visitez https://go.microsoft.com/fwlink/?LinkID=320771 - // Envoyer un e-mail avec ce lien - // string code = await UserManager.GeneratePasswordResetTokenAsync(user.Id); - // var callbackUrl = Url.Action("ResetPassword", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme); - // await UserManager.SendEmailAsync(user.Id, "Réinitialiser le mot de passe", "Réinitialisez votre mot de passe en cliquant ici"); - // return RedirectToAction("ForgotPasswordConfirmation", "Account"); - } + // + // GET: /Account/ForgotPasswordConfirmation + [AllowAnonymous] + public ActionResult ForgotPasswordConfirmation() + { + return View(); + } - // Si nous sommes arrivés là, quelque chose a échoué, réafficher le formulaire + // + // GET: /Account/ResetPassword + [AllowAnonymous] + public ActionResult ResetPassword(string code) + { + return code == null ? View("Error") : View(); + } + + // + // POST: /Account/ResetPassword + [HttpPost] + [AllowAnonymous] + [ValidateAntiForgeryToken] + public async Task ResetPassword(ResetPasswordViewModel model) + { + if (!ModelState.IsValid) + { return View(model); } - - // - // GET: /Account/ForgotPasswordConfirmation - [AllowAnonymous] - public ActionResult ForgotPasswordConfirmation() + var user = await UserManager.FindByNameAsync(model.Email); + if (user == null) { - return View(); + // Ne révélez pas que l'utilisateur n'existe pas + return RedirectToAction("ResetPasswordConfirmation", "Account"); } - - // - // GET: /Account/ResetPassword - [AllowAnonymous] - public ActionResult ResetPassword(string code) + var result = await UserManager.ResetPasswordAsync(user.Id, model.Code, model.Password); + if (result.Succeeded) { - return code == null ? View("Error") : View(); + return RedirectToAction("ResetPasswordConfirmation", "Account"); } + AddErrors(result); + return View(); + } + + // + // GET: /Account/ResetPasswordConfirmation + [AllowAnonymous] + public ActionResult ResetPasswordConfirmation() + { + return View(); + } + + // + // POST: /Account/ExternalLogin + [HttpPost] + [AllowAnonymous] + [ValidateAntiForgeryToken] + public ActionResult ExternalLogin(string provider, string returnUrl) + { + // Demander une redirection vers le fournisseur de connexion externe + return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl })); + } - // - // POST: /Account/ResetPassword - [HttpPost] - [AllowAnonymous] - [ValidateAntiForgeryToken] - public async Task ResetPassword(ResetPasswordViewModel model) + // + // GET: /Account/SendCode + [AllowAnonymous] + public async Task SendCode(string returnUrl, bool rememberMe) + { + var userId = await SignInManager.GetVerifiedUserIdAsync(); + if (userId == null) { - if (!ModelState.IsValid) - { - return View(model); - } - var user = await UserManager.FindByNameAsync(model.Email); - if (user == null) - { - // Ne révélez pas que l'utilisateur n'existe pas - return RedirectToAction("ResetPasswordConfirmation", "Account"); - } - var result = await UserManager.ResetPasswordAsync(user.Id, model.Code, model.Password); - if (result.Succeeded) - { - return RedirectToAction("ResetPasswordConfirmation", "Account"); - } - AddErrors(result); - return View(); + return View("Error"); } + var userFactors = await UserManager.GetValidTwoFactorProvidersAsync(userId); + var factorOptions = userFactors.Select(purpose => new SelectListItem { Text = purpose, Value = purpose }).ToList(); + return View(new SendCodeViewModel { Providers = factorOptions, ReturnUrl = returnUrl, RememberMe = rememberMe }); + } - // - // GET: /Account/ResetPasswordConfirmation - [AllowAnonymous] - public ActionResult ResetPasswordConfirmation() + // + // POST: /Account/SendCode + [HttpPost] + [AllowAnonymous] + [ValidateAntiForgeryToken] + public async Task SendCode(SendCodeViewModel model) + { + if (!ModelState.IsValid) { return View(); } - // - // POST: /Account/ExternalLogin - [HttpPost] - [AllowAnonymous] - [ValidateAntiForgeryToken] - public ActionResult ExternalLogin(string provider, string returnUrl) + // Générer le jeton et l'envoyer + if (!await SignInManager.SendTwoFactorCodeAsync(model.SelectedProvider)) { - // Demander une redirection vers le fournisseur de connexion externe - return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl })); + return View("Error"); } + return RedirectToAction("VerifyCode", new { Provider = model.SelectedProvider, ReturnUrl = model.ReturnUrl, RememberMe = model.RememberMe }); + } - // - // GET: /Account/SendCode - [AllowAnonymous] - public async Task SendCode(string returnUrl, bool rememberMe) + // + // GET: /Account/ExternalLoginCallback + [AllowAnonymous] + public async Task ExternalLoginCallback(string returnUrl) + { + var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync(); + if (loginInfo == null) { - var userId = await SignInManager.GetVerifiedUserIdAsync(); - if (userId == null) - { - return View("Error"); - } - var userFactors = await UserManager.GetValidTwoFactorProvidersAsync(userId); - var factorOptions = userFactors.Select(purpose => new SelectListItem { Text = purpose, Value = purpose }).ToList(); - return View(new SendCodeViewModel { Providers = factorOptions, ReturnUrl = returnUrl, RememberMe = rememberMe }); + return RedirectToAction("Login"); } - // - // POST: /Account/SendCode - [HttpPost] - [AllowAnonymous] - [ValidateAntiForgeryToken] - public async Task SendCode(SendCodeViewModel model) + // Connecter cet utilisateur à ce fournisseur de connexion externe si l'utilisateur possède déjà une connexion + var result = await SignInManager.ExternalSignInAsync(loginInfo, isPersistent: false); + switch (result) { - if (!ModelState.IsValid) - { - return View(); - } - - // Générer le jeton et l'envoyer - if (!await SignInManager.SendTwoFactorCodeAsync(model.SelectedProvider)) - { - return View("Error"); - } - return RedirectToAction("VerifyCode", new { Provider = model.SelectedProvider, ReturnUrl = model.ReturnUrl, RememberMe = model.RememberMe }); + case SignInStatus.Success: + return RedirectToLocal(returnUrl); + case SignInStatus.LockedOut: + return View("Lockout"); + case SignInStatus.RequiresVerification: + return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = false }); + case SignInStatus.Failure: + default: + // Si l'utilisateur n'a pas de compte, invitez alors celui-ci à créer un compte + ViewBag.ReturnUrl = returnUrl; + ViewBag.LoginProvider = loginInfo.Login.LoginProvider; + return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = loginInfo.Email }); } + } - // - // GET: /Account/ExternalLoginCallback - [AllowAnonymous] - public async Task ExternalLoginCallback(string returnUrl) + // + // POST: /Account/ExternalLoginConfirmation + [HttpPost] + [AllowAnonymous] + [ValidateAntiForgeryToken] + public async Task ExternalLoginConfirmation(ExternalLoginConfirmationViewModel model, string returnUrl) + { + if (User.Identity.IsAuthenticated) { - var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync(); - if (loginInfo == null) - { - return RedirectToAction("Login"); - } - - // Connecter cet utilisateur à ce fournisseur de connexion externe si l'utilisateur possède déjà une connexion - var result = await SignInManager.ExternalSignInAsync(loginInfo, isPersistent: false); - switch (result) - { - case SignInStatus.Success: - return RedirectToLocal(returnUrl); - case SignInStatus.LockedOut: - return View("Lockout"); - case SignInStatus.RequiresVerification: - return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = false }); - case SignInStatus.Failure: - default: - // Si l'utilisateur n'a pas de compte, invitez alors celui-ci à créer un compte - ViewBag.ReturnUrl = returnUrl; - ViewBag.LoginProvider = loginInfo.Login.LoginProvider; - return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = loginInfo.Email }); - } + return RedirectToAction("Index", "Manage"); } - // - // POST: /Account/ExternalLoginConfirmation - [HttpPost] - [AllowAnonymous] - [ValidateAntiForgeryToken] - public async Task ExternalLoginConfirmation(ExternalLoginConfirmationViewModel model, string returnUrl) + if (ModelState.IsValid) { - if (User.Identity.IsAuthenticated) + // Obtenir des informations sur l'utilisateur à partir du fournisseur de connexion externe + var info = await AuthenticationManager.GetExternalLoginInfoAsync(); + if (info == null) { - return RedirectToAction("Index", "Manage"); + return View("ExternalLoginFailure"); } - - if (ModelState.IsValid) + var user = new ApplicationUser { UserName = model.Email, Email = model.Email }; + var result = await UserManager.CreateAsync(user); + if (result.Succeeded) { - // Obtenir des informations sur l'utilisateur à partir du fournisseur de connexion externe - var info = await AuthenticationManager.GetExternalLoginInfoAsync(); - if (info == null) - { - return View("ExternalLoginFailure"); - } - var user = new ApplicationUser { UserName = model.Email, Email = model.Email }; - var result = await UserManager.CreateAsync(user); + result = await UserManager.AddLoginAsync(user.Id, info.Login); if (result.Succeeded) { - result = await UserManager.AddLoginAsync(user.Id, info.Login); - if (result.Succeeded) - { - await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false); - return RedirectToLocal(returnUrl); - } + await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false); + return RedirectToLocal(returnUrl); } - AddErrors(result); } - - ViewBag.ReturnUrl = returnUrl; - return View(model); + AddErrors(result); } - // - // POST: /Account/LogOff - [HttpPost] - [ValidateAntiForgeryToken] - public ActionResult LogOff() - { - AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie); - return RedirectToAction("Index", "Home"); - } + ViewBag.ReturnUrl = returnUrl; + return View(model); + } - // - // GET: /Account/ExternalLoginFailure - [AllowAnonymous] - public ActionResult ExternalLoginFailure() - { - return View(); - } + // + // POST: /Account/LogOff + [HttpPost] + [ValidateAntiForgeryToken] + public ActionResult LogOff() + { + AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie); + return RedirectToAction("Index", "Home"); + } + + // + // GET: /Account/ExternalLoginFailure + [AllowAnonymous] + public ActionResult ExternalLoginFailure() + { + return View(); + } - protected override void Dispose(bool disposing) + protected override void Dispose(bool disposing) + { + if (disposing) { - if (disposing) + if (_userManager != null) { - if (_userManager != null) - { - _userManager.Dispose(); - _userManager = null; - } - - if (_signInManager != null) - { - _signInManager.Dispose(); - _signInManager = null; - } + _userManager.Dispose(); + _userManager = null; } - base.Dispose(disposing); + if (_signInManager != null) + { + _signInManager.Dispose(); + _signInManager = null; + } } - #region Applications auxiliaires - // Utilisé(e) pour la protection XSRF lors de l'ajout de connexions externes - private const string XsrfKey = "XsrfId"; + base.Dispose(disposing); + } - private IAuthenticationManager AuthenticationManager + #region Applications auxiliaires + // Utilisé(e) pour la protection XSRF lors de l'ajout de connexions externes + private const string XsrfKey = "XsrfId"; + + private IAuthenticationManager AuthenticationManager + { + get { - get - { - return HttpContext.GetOwinContext().Authentication; - } + return HttpContext.GetOwinContext().Authentication; } + } - private void AddErrors(IdentityResult result) + private void AddErrors(IdentityResult result) + { + foreach (var error in result.Errors) { - foreach (var error in result.Errors) - { - ModelState.AddModelError("", error); - } + ModelState.AddModelError("", error); } + } - private ActionResult RedirectToLocal(string returnUrl) + private ActionResult RedirectToLocal(string returnUrl) + { + if (Url.IsLocalUrl(returnUrl)) { - if (Url.IsLocalUrl(returnUrl)) - { - return Redirect(returnUrl); - } - return RedirectToAction("Index", "Home"); + return Redirect(returnUrl); } + return RedirectToAction("Index", "Home"); + } - internal class ChallengeResult : HttpUnauthorizedResult + internal class ChallengeResult : HttpUnauthorizedResult + { + public ChallengeResult(string provider, string redirectUri) + : this(provider, redirectUri, null) { - public ChallengeResult(string provider, string redirectUri) - : this(provider, redirectUri, null) - { - } + } - public ChallengeResult(string provider, string redirectUri, string userId) - { - LoginProvider = provider; - RedirectUri = redirectUri; - UserId = userId; - } + public ChallengeResult(string provider, string redirectUri, string userId) + { + LoginProvider = provider; + RedirectUri = redirectUri; + UserId = userId; + } - public string LoginProvider { get; set; } - public string RedirectUri { get; set; } - public string UserId { get; set; } + public string LoginProvider { get; set; } + public string RedirectUri { get; set; } + public string UserId { get; set; } - public override void ExecuteResult(ControllerContext context) + public override void ExecuteResult(ControllerContext context) + { + var properties = new AuthenticationProperties { RedirectUri = RedirectUri }; + if (UserId != null) { - var properties = new AuthenticationProperties { RedirectUri = RedirectUri }; - if (UserId != null) - { - properties.Dictionary[XsrfKey] = UserId; - } - context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider); + properties.Dictionary[XsrfKey] = UserId; } + context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider); } - #endregion } + #endregion } \ No newline at end of file diff --git a/samples/Mortis/Mortis.Server/Controllers/AuthorizationController.cs b/samples/Mortis/Mortis.Server/Controllers/AuthorizationController.cs index 821a9e462..b1d85b651 100644 --- a/samples/Mortis/Mortis.Server/Controllers/AuthorizationController.cs +++ b/samples/Mortis/Mortis.Server/Controllers/AuthorizationController.cs @@ -22,382 +22,381 @@ using Owin; using static OpenIddict.Abstractions.OpenIddictConstants; -namespace Mortis.Server.Controllers +namespace Mortis.Server.Controllers; + +public class AuthorizationController : Controller { - public class AuthorizationController : Controller + private readonly IOpenIddictApplicationManager _applicationManager; + private readonly IOpenIddictAuthorizationManager _authorizationManager; + private readonly IOpenIddictScopeManager _scopeManager; + + public AuthorizationController( + IOpenIddictApplicationManager applicationManager, + IOpenIddictAuthorizationManager authorizationManager, + IOpenIddictScopeManager scopeManager) + { + _applicationManager = applicationManager; + _authorizationManager = authorizationManager; + _scopeManager = scopeManager; + } + + [HttpGet, Route("~/connect/authorize")] + public async Task Authorize() { - private readonly IOpenIddictApplicationManager _applicationManager; - private readonly IOpenIddictAuthorizationManager _authorizationManager; - private readonly IOpenIddictScopeManager _scopeManager; - - public AuthorizationController( - IOpenIddictApplicationManager applicationManager, - IOpenIddictAuthorizationManager authorizationManager, - IOpenIddictScopeManager scopeManager) + var context = HttpContext.GetOwinContext(); + var request = context.GetOpenIddictServerRequest() ?? + throw new InvalidOperationException("The OpenID Connect request cannot be retrieved."); + + // Retrieve the user principal stored in the authentication cookie. + // If a max_age parameter was provided, ensure that the cookie is not too old. + // If the user principal can't be extracted or the cookie is too old, redirect the user to the login page. + var result = await context.Authentication.AuthenticateAsync(DefaultAuthenticationTypes.ApplicationCookie); + if (result?.Identity == null || (request.MaxAge != null && result.Properties?.IssuedUtc != null && + DateTimeOffset.UtcNow - result.Properties.IssuedUtc > TimeSpan.FromSeconds(request.MaxAge.Value))) { - _applicationManager = applicationManager; - _authorizationManager = authorizationManager; - _scopeManager = scopeManager; + context.Authentication.Challenge(DefaultAuthenticationTypes.ApplicationCookie); + + return new EmptyResult(); } - [HttpGet, Route("~/connect/authorize")] - public async Task Authorize() + // Retrieve the profile of the logged in user. + var user = await context.GetUserManager().FindByIdAsync(result.Identity.GetUserId()) ?? + throw new InvalidOperationException("The user details cannot be retrieved."); + + // Retrieve the application details from the database. + var application = await _applicationManager.FindByClientIdAsync(request.ClientId) ?? + throw new InvalidOperationException("Details concerning the calling client application cannot be found."); + + // Retrieve the permanent authorizations associated with the user and the calling client application. + var authorizations = await _authorizationManager.FindAsync( + subject: user.Id, + client : await _applicationManager.GetIdAsync(application), + status : Statuses.Valid, + type : AuthorizationTypes.Permanent, + scopes : request.GetScopes()).ToListAsync(); + + switch (await _applicationManager.GetConsentTypeAsync(application)) { - var context = HttpContext.GetOwinContext(); - var request = context.GetOpenIddictServerRequest() ?? - throw new InvalidOperationException("The OpenID Connect request cannot be retrieved."); - - // Retrieve the user principal stored in the authentication cookie. - // If a max_age parameter was provided, ensure that the cookie is not too old. - // If the user principal can't be extracted or the cookie is too old, redirect the user to the login page. - var result = await context.Authentication.AuthenticateAsync(DefaultAuthenticationTypes.ApplicationCookie); - if (result?.Identity == null || (request.MaxAge != null && result.Properties?.IssuedUtc != null && - DateTimeOffset.UtcNow - result.Properties.IssuedUtc > TimeSpan.FromSeconds(request.MaxAge.Value))) - { - context.Authentication.Challenge(DefaultAuthenticationTypes.ApplicationCookie); + // If the consent is external (e.g when authorizations are granted by a sysadmin), + // immediately return an error if no authorization can be found in the database. + case ConsentTypes.External when authorizations.Count is 0: + context.Authentication.Challenge( + authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType, + properties: new AuthenticationProperties(new Dictionary + { + [OpenIddictServerOwinConstants.Properties.Error] = Errors.ConsentRequired, + [OpenIddictServerOwinConstants.Properties.ErrorDescription] = + "The logged in user is not allowed to access this client application." + })); return new EmptyResult(); - } - // Retrieve the profile of the logged in user. - var user = await context.GetUserManager().FindByIdAsync(result.Identity.GetUserId()) ?? - throw new InvalidOperationException("The user details cannot be retrieved."); + // If the consent is implicit or if an authorization was found, + // return an authorization response without displaying the consent form. + case ConsentTypes.Implicit: + case ConsentTypes.External when authorizations.Count is not 0: + case ConsentTypes.Explicit when authorizations.Count is not 0 && !request.HasPrompt(Prompts.Consent): + // Create the claims-based identity that will be used by OpenIddict to generate tokens. + var identity = new ClaimsIdentity( + authenticationType: OpenIddictServerOwinDefaults.AuthenticationType, + nameType: Claims.Name, + roleType: Claims.Role); - // Retrieve the application details from the database. - var application = await _applicationManager.FindByClientIdAsync(request.ClientId) ?? - throw new InvalidOperationException("Details concerning the calling client application cannot be found."); + // Add the claims that will be persisted in the tokens. + identity.SetClaim(Claims.Subject, user.Id) + .SetClaim(Claims.Email, user.Email) + .SetClaim(Claims.Name, user.UserName) + .SetClaim(Claims.PreferredUsername, user.UserName) + .SetClaims(Claims.Role, (await context.Get().GetRolesAsync(user.Id)).ToImmutableArray()); - // Retrieve the permanent authorizations associated with the user and the calling client application. - var authorizations = await _authorizationManager.FindAsync( - subject: user.Id, - client : await _applicationManager.GetIdAsync(application), - status : Statuses.Valid, - type : AuthorizationTypes.Permanent, - scopes : request.GetScopes()).ToListAsync(); + // Note: in this sample, the granted scopes match the requested scope + // but you may want to allow the user to uncheck specific scopes. + // For that, simply restrict the list of scopes before calling SetScopes. + identity.SetScopes(request.GetScopes()); + identity.SetResources(await _scopeManager.ListResourcesAsync(identity.GetScopes()).ToListAsync()); + + // Automatically create a permanent authorization to avoid requiring explicit consent + // for future authorization or token requests containing the same scopes. + var authorization = authorizations.LastOrDefault(); + authorization ??= await _authorizationManager.CreateAsync( + identity: identity, + subject : user.Id, + client : await _applicationManager.GetIdAsync(application), + type : AuthorizationTypes.Permanent, + scopes : identity.GetScopes()); + + identity.SetAuthorizationId(await _authorizationManager.GetIdAsync(authorization)); + identity.SetDestinations(GetDestinations); - switch (await _applicationManager.GetConsentTypeAsync(application)) + context.Authentication.SignIn(identity); + + return new EmptyResult(); + + // At this point, no authorization was found in the database and an error must be returned + // if the client application specified prompt=none in the authorization request. + case ConsentTypes.Explicit when request.HasPrompt(Prompts.None): + case ConsentTypes.Systematic when request.HasPrompt(Prompts.None): + context.Authentication.Challenge( + authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType, + properties: new AuthenticationProperties(new Dictionary + { + [OpenIddictServerOwinConstants.Properties.Error] = Errors.ConsentRequired, + [OpenIddictServerOwinConstants.Properties.ErrorDescription] = + "Interactive user consent is required." + })); + + return new EmptyResult(); + + // In every other case, render the consent form. + default: return View(new AuthorizeViewModel { - // If the consent is external (e.g when authorizations are granted by a sysadmin), - // immediately return an error if no authorization can be found in the database. - case ConsentTypes.External when authorizations.Count is 0: - context.Authentication.Challenge( - authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType, - properties: new AuthenticationProperties(new Dictionary - { - [OpenIddictServerOwinConstants.Properties.Error] = Errors.ConsentRequired, - [OpenIddictServerOwinConstants.Properties.ErrorDescription] = - "The logged in user is not allowed to access this client application." - })); - - return new EmptyResult(); - - // If the consent is implicit or if an authorization was found, - // return an authorization response without displaying the consent form. - case ConsentTypes.Implicit: - case ConsentTypes.External when authorizations.Count is not 0: - case ConsentTypes.Explicit when authorizations.Count is not 0 && !request.HasPrompt(Prompts.Consent): - // Create the claims-based identity that will be used by OpenIddict to generate tokens. - var identity = new ClaimsIdentity( - authenticationType: OpenIddictServerOwinDefaults.AuthenticationType, - nameType: Claims.Name, - roleType: Claims.Role); - - // Add the claims that will be persisted in the tokens. - identity.SetClaim(Claims.Subject, user.Id) - .SetClaim(Claims.Email, user.Email) - .SetClaim(Claims.Name, user.UserName) - .SetClaim(Claims.PreferredUsername, user.UserName) - .SetClaims(Claims.Role, (await context.Get().GetRolesAsync(user.Id)).ToImmutableArray()); - - // Note: in this sample, the granted scopes match the requested scope - // but you may want to allow the user to uncheck specific scopes. - // For that, simply restrict the list of scopes before calling SetScopes. - identity.SetScopes(request.GetScopes()); - identity.SetResources(await _scopeManager.ListResourcesAsync(identity.GetScopes()).ToListAsync()); - - // Automatically create a permanent authorization to avoid requiring explicit consent - // for future authorization or token requests containing the same scopes. - var authorization = authorizations.LastOrDefault(); - authorization ??= await _authorizationManager.CreateAsync( - identity: identity, - subject : user.Id, - client : await _applicationManager.GetIdAsync(application), - type : AuthorizationTypes.Permanent, - scopes : identity.GetScopes()); - - identity.SetAuthorizationId(await _authorizationManager.GetIdAsync(authorization)); - identity.SetDestinations(GetDestinations); - - context.Authentication.SignIn(identity); - - return new EmptyResult(); - - // At this point, no authorization was found in the database and an error must be returned - // if the client application specified prompt=none in the authorization request. - case ConsentTypes.Explicit when request.HasPrompt(Prompts.None): - case ConsentTypes.Systematic when request.HasPrompt(Prompts.None): - context.Authentication.Challenge( - authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType, - properties: new AuthenticationProperties(new Dictionary - { - [OpenIddictServerOwinConstants.Properties.Error] = Errors.ConsentRequired, - [OpenIddictServerOwinConstants.Properties.ErrorDescription] = - "Interactive user consent is required." - })); - - return new EmptyResult(); - - // In every other case, render the consent form. - default: return View(new AuthorizeViewModel + ApplicationName = await _applicationManager.GetDisplayNameAsync(application), + Scope = request.Scope, + + // Flow the request parameters so they can be received by the Accept/Reject actions. + Parameters = string.Equals(Request.HttpMethod, "POST", StringComparison.OrdinalIgnoreCase) ? + from name in Request.Form.AllKeys + from value in Request.Form.GetValues(name) + select new KeyValuePair(name, value) : + from name in Request.QueryString.AllKeys + from value in Request.QueryString.GetValues(name) + select new KeyValuePair(name, value) + }); + } + } + + [Authorize, FormValueRequired("submit.Accept")] + [HttpPost, Route("~/connect/authorize"), ValidateAntiForgeryToken] + public async Task Accept() + { + var context = HttpContext.GetOwinContext(); + var request = context.GetOpenIddictServerRequest() ?? + throw new InvalidOperationException("The OpenID Connect request cannot be retrieved."); + + // Retrieve the user principal stored in the authentication cookie. + var result = await context.Authentication.AuthenticateAsync(DefaultAuthenticationTypes.ApplicationCookie); + if (result == null || result.Identity == null) + { + context.Authentication.Challenge(DefaultAuthenticationTypes.ApplicationCookie); + + return new EmptyResult(); + } + + // Retrieve the profile of the logged in user. + var user = await context.GetUserManager().FindByIdAsync(result.Identity.GetUserId()) ?? + throw new InvalidOperationException("The user details cannot be retrieved."); + + // Retrieve the application details from the database. + var application = await _applicationManager.FindByClientIdAsync(request.ClientId) ?? + throw new InvalidOperationException("Details concerning the calling client application cannot be found."); + + // Retrieve the permanent authorizations associated with the user and the calling client application. + var authorizations = await _authorizationManager.FindAsync( + subject: user.Id, + client : await _applicationManager.GetIdAsync(application), + status : Statuses.Valid, + type : AuthorizationTypes.Permanent, + scopes : request.GetScopes()).ToListAsync(); + + // Note: the same check is already made in the other action but is repeated + // here to ensure a malicious user can't abuse this POST-only endpoint and + // force it to return a valid response without the external authorization. + if (authorizations.Count is 0 && await _applicationManager.HasConsentTypeAsync(application, ConsentTypes.External)) + { + context.Authentication.Challenge( + authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType, + properties: new AuthenticationProperties(new Dictionary { - ApplicationName = await _applicationManager.GetDisplayNameAsync(application), - Scope = request.Scope, - - // Flow the request parameters so they can be received by the Accept/Reject actions. - Parameters = string.Equals(Request.HttpMethod, "POST", StringComparison.OrdinalIgnoreCase) ? - from name in Request.Form.AllKeys - from value in Request.Form.GetValues(name) - select new KeyValuePair(name, value) : - from name in Request.QueryString.AllKeys - from value in Request.QueryString.GetValues(name) - select new KeyValuePair(name, value) - }); - } + [OpenIddictServerOwinConstants.Properties.Error] = Errors.ConsentRequired, + [OpenIddictServerOwinConstants.Properties.ErrorDescription] = + "The logged in user is not allowed to access this client application." + })); + + return new EmptyResult(); } - [Authorize, FormValueRequired("submit.Accept")] - [HttpPost, Route("~/connect/authorize"), ValidateAntiForgeryToken] - public async Task Accept() + // Create the claims-based identity that will be used by OpenIddict to generate tokens. + var identity = new ClaimsIdentity( + authenticationType: OpenIddictServerOwinDefaults.AuthenticationType, + nameType: Claims.Name, + roleType: Claims.Role); + + // Add the claims that will be persisted in the tokens. + identity.SetClaim(Claims.Subject, user.Id) + .SetClaim(Claims.Email, user.Email) + .SetClaim(Claims.Name, user.UserName) + .SetClaim(Claims.PreferredUsername, user.UserName) + .SetClaims(Claims.Role, (await context.Get().GetRolesAsync(user.Id)).ToImmutableArray()); + + // Note: in this sample, the granted scopes match the requested scope + // but you may want to allow the user to uncheck specific scopes. + // For that, simply restrict the list of scopes before calling SetScopes. + identity.SetScopes(request.GetScopes()); + identity.SetResources(await _scopeManager.ListResourcesAsync(identity.GetScopes()).ToListAsync()); + + // Automatically create a permanent authorization to avoid requiring explicit consent + // for future authorization or token requests containing the same scopes. + var authorization = authorizations.LastOrDefault(); + authorization ??= await _authorizationManager.CreateAsync( + identity: identity, + subject : user.Id, + client : await _applicationManager.GetIdAsync(application), + type : AuthorizationTypes.Permanent, + scopes : identity.GetScopes()); + + identity.SetAuthorizationId(await _authorizationManager.GetIdAsync(authorization)); + identity.SetDestinations(GetDestinations); + + // Returning a SignInResult will ask OpenIddict to issue the appropriate access/identity tokens. + context.Authentication.SignIn(identity); + + return new EmptyResult(); + } + + [Authorize, FormValueRequired("submit.Deny")] + [HttpPost, Route("~/connect/authorize"), ValidateAntiForgeryToken] + // Notify OpenIddict that the authorization grant has been denied by the resource owner + // to redirect the user agent to the client application using the appropriate response_mode. + public ActionResult Deny() + { + var context = HttpContext.GetOwinContext(); + context.Authentication.Challenge(OpenIddictServerOwinDefaults.AuthenticationType); + + return new EmptyResult(); + } + + [HttpGet, Route("~/connect/logout")] + public ActionResult Logout() => View(new AuthorizeViewModel + { + // Flow the request parameters so they can be received by the Accept/Reject actions. + Parameters = string.Equals(Request.HttpMethod, "POST", StringComparison.OrdinalIgnoreCase) ? + from name in Request.Form.AllKeys + from value in Request.Form.GetValues(name) + select new KeyValuePair(name, value) : + from name in Request.QueryString.AllKeys + from value in Request.QueryString.GetValues(name) + select new KeyValuePair(name, value) + }); + + [ActionName(nameof(Logout)), HttpPost, Route("~/connect/logout"), ValidateAntiForgeryToken] + public ActionResult LogoutPost() + { + var context = HttpContext.GetOwinContext(); + context.Authentication.SignOut(DefaultAuthenticationTypes.ApplicationCookie); + + context.Authentication.SignOut( + authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType, + properties: new AuthenticationProperties + { + RedirectUri = "/" + }); + + return new EmptyResult(); + } + + [HttpPost, Route("~/connect/token")] + public async Task Exchange() + { + var context = HttpContext.GetOwinContext(); + var request = context.GetOpenIddictServerRequest() ?? + throw new InvalidOperationException("The OpenID Connect request cannot be retrieved."); + + if (request.IsAuthorizationCodeGrantType() || request.IsRefreshTokenGrantType()) { - var context = HttpContext.GetOwinContext(); - var request = context.GetOpenIddictServerRequest() ?? - throw new InvalidOperationException("The OpenID Connect request cannot be retrieved."); + // Retrieve the claims principal stored in the authorization code/device code/refresh token. + var result = await context.Authentication.AuthenticateAsync(OpenIddictServerOwinDefaults.AuthenticationType); - // Retrieve the user principal stored in the authentication cookie. - var result = await context.Authentication.AuthenticateAsync(DefaultAuthenticationTypes.ApplicationCookie); - if (result == null || result.Identity == null) + // Retrieve the user profile corresponding to the authorization code/refresh token. + var user = await context.GetUserManager().FindByIdAsync(result.Identity.GetClaim(Claims.Subject)); + if (user == null) { - context.Authentication.Challenge(DefaultAuthenticationTypes.ApplicationCookie); + context.Authentication.Challenge( + authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType, + properties: new AuthenticationProperties(new Dictionary + { + [OpenIddictServerOwinConstants.Properties.Error] = Errors.InvalidGrant, + [OpenIddictServerOwinConstants.Properties.ErrorDescription] = "The token is no longer valid." + })); return new EmptyResult(); } - // Retrieve the profile of the logged in user. - var user = await context.GetUserManager().FindByIdAsync(result.Identity.GetUserId()) ?? - throw new InvalidOperationException("The user details cannot be retrieved."); - - // Retrieve the application details from the database. - var application = await _applicationManager.FindByClientIdAsync(request.ClientId) ?? - throw new InvalidOperationException("Details concerning the calling client application cannot be found."); - - // Retrieve the permanent authorizations associated with the user and the calling client application. - var authorizations = await _authorizationManager.FindAsync( - subject: user.Id, - client : await _applicationManager.GetIdAsync(application), - status : Statuses.Valid, - type : AuthorizationTypes.Permanent, - scopes : request.GetScopes()).ToListAsync(); - - // Note: the same check is already made in the other action but is repeated - // here to ensure a malicious user can't abuse this POST-only endpoint and - // force it to return a valid response without the external authorization. - if (authorizations.Count is 0 && await _applicationManager.HasConsentTypeAsync(application, ConsentTypes.External)) + // Ensure the user is still allowed to sign in. + if (context.GetUserManager().IsLockedOut(user.Id)) { context.Authentication.Challenge( authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType, properties: new AuthenticationProperties(new Dictionary { - [OpenIddictServerOwinConstants.Properties.Error] = Errors.ConsentRequired, - [OpenIddictServerOwinConstants.Properties.ErrorDescription] = - "The logged in user is not allowed to access this client application." + [OpenIddictServerOwinConstants.Properties.Error] = Errors.InvalidGrant, + [OpenIddictServerOwinConstants.Properties.ErrorDescription] = "The user is no longer allowed to sign in." })); return new EmptyResult(); } - // Create the claims-based identity that will be used by OpenIddict to generate tokens. - var identity = new ClaimsIdentity( + var identity = new ClaimsIdentity(result.Identity.Claims, authenticationType: OpenIddictServerOwinDefaults.AuthenticationType, nameType: Claims.Name, roleType: Claims.Role); - // Add the claims that will be persisted in the tokens. + // Override the user claims present in the principal in case they + // changed since the authorization code/refresh token was issued. identity.SetClaim(Claims.Subject, user.Id) .SetClaim(Claims.Email, user.Email) .SetClaim(Claims.Name, user.UserName) .SetClaim(Claims.PreferredUsername, user.UserName) .SetClaims(Claims.Role, (await context.Get().GetRolesAsync(user.Id)).ToImmutableArray()); - // Note: in this sample, the granted scopes match the requested scope - // but you may want to allow the user to uncheck specific scopes. - // For that, simply restrict the list of scopes before calling SetScopes. - identity.SetScopes(request.GetScopes()); - identity.SetResources(await _scopeManager.ListResourcesAsync(identity.GetScopes()).ToListAsync()); - - // Automatically create a permanent authorization to avoid requiring explicit consent - // for future authorization or token requests containing the same scopes. - var authorization = authorizations.LastOrDefault(); - authorization ??= await _authorizationManager.CreateAsync( - identity: identity, - subject : user.Id, - client : await _applicationManager.GetIdAsync(application), - type : AuthorizationTypes.Permanent, - scopes : identity.GetScopes()); - - identity.SetAuthorizationId(await _authorizationManager.GetIdAsync(authorization)); identity.SetDestinations(GetDestinations); - // Returning a SignInResult will ask OpenIddict to issue the appropriate access/identity tokens. + // Ask OpenIddict to issue the appropriate access/identity tokens. context.Authentication.SignIn(identity); return new EmptyResult(); } - [Authorize, FormValueRequired("submit.Deny")] - [HttpPost, Route("~/connect/authorize"), ValidateAntiForgeryToken] - // Notify OpenIddict that the authorization grant has been denied by the resource owner - // to redirect the user agent to the client application using the appropriate response_mode. - public ActionResult Deny() - { - var context = HttpContext.GetOwinContext(); - context.Authentication.Challenge(OpenIddictServerOwinDefaults.AuthenticationType); - - return new EmptyResult(); - } - - [HttpGet, Route("~/connect/logout")] - public ActionResult Logout() => View(new AuthorizeViewModel - { - // Flow the request parameters so they can be received by the Accept/Reject actions. - Parameters = string.Equals(Request.HttpMethod, "POST", StringComparison.OrdinalIgnoreCase) ? - from name in Request.Form.AllKeys - from value in Request.Form.GetValues(name) - select new KeyValuePair(name, value) : - from name in Request.QueryString.AllKeys - from value in Request.QueryString.GetValues(name) - select new KeyValuePair(name, value) - }); - - [ActionName(nameof(Logout)), HttpPost, Route("~/connect/logout"), ValidateAntiForgeryToken] - public ActionResult LogoutPost() - { - var context = HttpContext.GetOwinContext(); - context.Authentication.SignOut(DefaultAuthenticationTypes.ApplicationCookie); - - context.Authentication.SignOut( - authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType, - properties: new AuthenticationProperties - { - RedirectUri = "/" - }); - - return new EmptyResult(); - } - - [HttpPost, Route("~/connect/token")] - public async Task Exchange() - { - var context = HttpContext.GetOwinContext(); - var request = context.GetOpenIddictServerRequest() ?? - throw new InvalidOperationException("The OpenID Connect request cannot be retrieved."); - - if (request.IsAuthorizationCodeGrantType() || request.IsRefreshTokenGrantType()) - { - // Retrieve the claims principal stored in the authorization code/device code/refresh token. - var result = await context.Authentication.AuthenticateAsync(OpenIddictServerOwinDefaults.AuthenticationType); - - // Retrieve the user profile corresponding to the authorization code/refresh token. - var user = await context.GetUserManager().FindByIdAsync(result.Identity.GetClaim(Claims.Subject)); - if (user == null) - { - context.Authentication.Challenge( - authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType, - properties: new AuthenticationProperties(new Dictionary - { - [OpenIddictServerOwinConstants.Properties.Error] = Errors.InvalidGrant, - [OpenIddictServerOwinConstants.Properties.ErrorDescription] = "The token is no longer valid." - })); - - return new EmptyResult(); - } - - // Ensure the user is still allowed to sign in. - if (context.GetUserManager().IsLockedOut(user.Id)) - { - context.Authentication.Challenge( - authenticationTypes: OpenIddictServerOwinDefaults.AuthenticationType, - properties: new AuthenticationProperties(new Dictionary - { - [OpenIddictServerOwinConstants.Properties.Error] = Errors.InvalidGrant, - [OpenIddictServerOwinConstants.Properties.ErrorDescription] = "The user is no longer allowed to sign in." - })); - - return new EmptyResult(); - } - - var identity = new ClaimsIdentity(result.Identity.Claims, - authenticationType: OpenIddictServerOwinDefaults.AuthenticationType, - nameType: Claims.Name, - roleType: Claims.Role); - - // Override the user claims present in the principal in case they - // changed since the authorization code/refresh token was issued. - identity.SetClaim(Claims.Subject, user.Id) - .SetClaim(Claims.Email, user.Email) - .SetClaim(Claims.Name, user.UserName) - .SetClaim(Claims.PreferredUsername, user.UserName) - .SetClaims(Claims.Role, (await context.Get().GetRolesAsync(user.Id)).ToImmutableArray()); - - identity.SetDestinations(GetDestinations); - - // Ask OpenIddict to issue the appropriate access/identity tokens. - context.Authentication.SignIn(identity); - - return new EmptyResult(); - } + throw new InvalidOperationException("The specified grant type is not supported."); + } - throw new InvalidOperationException("The specified grant type is not supported."); - } + private static IEnumerable GetDestinations(Claim claim) + { + // Note: by default, claims are NOT automatically included in the access and identity tokens. + // To allow OpenIddict to serialize them, you must attach them a destination, that specifies + // whether they should be included in access tokens, in identity tokens or in both. - private static IEnumerable GetDestinations(Claim claim) + switch (claim.Type) { - // Note: by default, claims are NOT automatically included in the access and identity tokens. - // To allow OpenIddict to serialize them, you must attach them a destination, that specifies - // whether they should be included in access tokens, in identity tokens or in both. + case Claims.Name or Claims.PreferredUsername: + yield return Destinations.AccessToken; - switch (claim.Type) - { - case Claims.Name or Claims.PreferredUsername: - yield return Destinations.AccessToken; - - if (claim.Subject.HasScope(Scopes.Profile)) - yield return Destinations.IdentityToken; + if (claim.Subject.HasScope(Scopes.Profile)) + yield return Destinations.IdentityToken; - yield break; + yield break; - case Claims.Email: - yield return Destinations.AccessToken; + case Claims.Email: + yield return Destinations.AccessToken; - if (claim.Subject.HasScope(Scopes.Email)) - yield return Destinations.IdentityToken; + if (claim.Subject.HasScope(Scopes.Email)) + yield return Destinations.IdentityToken; - yield break; + yield break; - case Claims.Role: - yield return Destinations.AccessToken; + case Claims.Role: + yield return Destinations.AccessToken; - if (claim.Subject.HasScope(Scopes.Roles)) - yield return Destinations.IdentityToken; + if (claim.Subject.HasScope(Scopes.Roles)) + yield return Destinations.IdentityToken; - yield break; + yield break; - // Never include the security stamp in the access and identity tokens, as it's a secret value. - case "AspNet.Identity.SecurityStamp": yield break; + // Never include the security stamp in the access and identity tokens, as it's a secret value. + case "AspNet.Identity.SecurityStamp": yield break; - default: - yield return Destinations.AccessToken; - yield break; - } + default: + yield return Destinations.AccessToken; + yield break; } } } diff --git a/samples/Mortis/Mortis.Server/Controllers/HomeController.cs b/samples/Mortis/Mortis.Server/Controllers/HomeController.cs index 0fdd8d56a..24e3e2dc1 100644 --- a/samples/Mortis/Mortis.Server/Controllers/HomeController.cs +++ b/samples/Mortis/Mortis.Server/Controllers/HomeController.cs @@ -1,26 +1,25 @@ using System.Web.Mvc; -namespace Mortis.Server.Controllers +namespace Mortis.Server.Controllers; + +public class HomeController : Controller { - public class HomeController : Controller + public ActionResult Index() { - public ActionResult Index() - { - return View(); - } + return View(); + } - public ActionResult About() - { - ViewBag.Message = "Your application description page."; + public ActionResult About() + { + ViewBag.Message = "Your application description page."; - return View(); - } + return View(); + } - public ActionResult Contact() - { - ViewBag.Message = "Your contact page."; + public ActionResult Contact() + { + ViewBag.Message = "Your contact page."; - return View(); - } + return View(); } } \ No newline at end of file diff --git a/samples/Mortis/Mortis.Server/Controllers/ManageController.cs b/samples/Mortis/Mortis.Server/Controllers/ManageController.cs index 3819c4ddc..8ff21d766 100644 --- a/samples/Mortis/Mortis.Server/Controllers/ManageController.cs +++ b/samples/Mortis/Mortis.Server/Controllers/ManageController.cs @@ -7,229 +7,258 @@ using Microsoft.Owin.Security; using Mortis.Server.Models; -namespace Mortis.Server.Controllers +namespace Mortis.Server.Controllers; + +[Authorize] +public class ManageController : Controller { - [Authorize] - public class ManageController : Controller + private ApplicationSignInManager _signInManager; + private ApplicationUserManager _userManager; + + public ManageController() + { + } + + public ManageController(ApplicationUserManager userManager, ApplicationSignInManager signInManager) { - private ApplicationSignInManager _signInManager; - private ApplicationUserManager _userManager; + UserManager = userManager; + SignInManager = signInManager; + } - public ManageController() + public ApplicationSignInManager SignInManager + { + get { + return _signInManager ?? HttpContext.GetOwinContext().Get(); + } + private set + { + _signInManager = value; } + } - public ManageController(ApplicationUserManager userManager, ApplicationSignInManager signInManager) + public ApplicationUserManager UserManager + { + get { - UserManager = userManager; - SignInManager = signInManager; + return _userManager ?? HttpContext.GetOwinContext().GetUserManager(); } - - public ApplicationSignInManager SignInManager + private set { - get - { - return _signInManager ?? HttpContext.GetOwinContext().Get(); - } - private set - { - _signInManager = value; - } + _userManager = value; } + } - public ApplicationUserManager UserManager + // + // GET: /Manage/Index + public async Task Index(ManageMessageId? message) + { + ViewBag.StatusMessage = + message == ManageMessageId.ChangePasswordSuccess ? "Votre mot de passe a été changé." + : message == ManageMessageId.SetPasswordSuccess ? "Votre mot de passe a été défini." + : message == ManageMessageId.SetTwoFactorSuccess ? "Votre fournisseur d'authentification à 2 facteurs a été défini." + : message == ManageMessageId.Error ? "Une erreur s'est produite." + : message == ManageMessageId.AddPhoneSuccess ? "Votre numéro de téléphone a été ajouté." + : message == ManageMessageId.RemovePhoneSuccess ? "Votre numéro de téléphone a été supprimé." + : ""; + + var userId = User.Identity.GetUserId(); + var model = new IndexViewModel { - get - { - return _userManager ?? HttpContext.GetOwinContext().GetUserManager(); - } - private set + HasPassword = HasPassword(), + PhoneNumber = await UserManager.GetPhoneNumberAsync(userId), + TwoFactor = await UserManager.GetTwoFactorEnabledAsync(userId), + Logins = await UserManager.GetLoginsAsync(userId), + BrowserRemembered = await AuthenticationManager.TwoFactorBrowserRememberedAsync(userId) + }; + return View(model); + } + + // + // POST: /Manage/RemoveLogin + [HttpPost] + [ValidateAntiForgeryToken] + public async Task RemoveLogin(string loginProvider, string providerKey) + { + ManageMessageId? message; + var result = await UserManager.RemoveLoginAsync(User.Identity.GetUserId(), new UserLoginInfo(loginProvider, providerKey)); + if (result.Succeeded) + { + var user = await UserManager.FindByIdAsync(User.Identity.GetUserId()); + if (user != null) { - _userManager = value; + await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false); } + message = ManageMessageId.RemoveLoginSuccess; + } + else + { + message = ManageMessageId.Error; } + return RedirectToAction("ManageLogins", new { Message = message }); + } - // - // GET: /Manage/Index - public async Task Index(ManageMessageId? message) + // + // GET: /Manage/AddPhoneNumber + public ActionResult AddPhoneNumber() + { + return View(); + } + + // + // POST: /Manage/AddPhoneNumber + [HttpPost] + [ValidateAntiForgeryToken] + public async Task AddPhoneNumber(AddPhoneNumberViewModel model) + { + if (!ModelState.IsValid) { - ViewBag.StatusMessage = - message == ManageMessageId.ChangePasswordSuccess ? "Votre mot de passe a été changé." - : message == ManageMessageId.SetPasswordSuccess ? "Votre mot de passe a été défini." - : message == ManageMessageId.SetTwoFactorSuccess ? "Votre fournisseur d'authentification à 2 facteurs a été défini." - : message == ManageMessageId.Error ? "Une erreur s'est produite." - : message == ManageMessageId.AddPhoneSuccess ? "Votre numéro de téléphone a été ajouté." - : message == ManageMessageId.RemovePhoneSuccess ? "Votre numéro de téléphone a été supprimé." - : ""; - - var userId = User.Identity.GetUserId(); - var model = new IndexViewModel - { - HasPassword = HasPassword(), - PhoneNumber = await UserManager.GetPhoneNumberAsync(userId), - TwoFactor = await UserManager.GetTwoFactorEnabledAsync(userId), - Logins = await UserManager.GetLoginsAsync(userId), - BrowserRemembered = await AuthenticationManager.TwoFactorBrowserRememberedAsync(userId) - }; return View(model); } - - // - // POST: /Manage/RemoveLogin - [HttpPost] - [ValidateAntiForgeryToken] - public async Task RemoveLogin(string loginProvider, string providerKey) + // Générer le jeton et l'envoyer + var code = await UserManager.GenerateChangePhoneNumberTokenAsync(User.Identity.GetUserId(), model.Number); + if (UserManager.SmsService != null) { - ManageMessageId? message; - var result = await UserManager.RemoveLoginAsync(User.Identity.GetUserId(), new UserLoginInfo(loginProvider, providerKey)); - if (result.Succeeded) - { - var user = await UserManager.FindByIdAsync(User.Identity.GetUserId()); - if (user != null) - { - await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false); - } - message = ManageMessageId.RemoveLoginSuccess; - } - else + var message = new IdentityMessage { - message = ManageMessageId.Error; - } - return RedirectToAction("ManageLogins", new { Message = message }); + Destination = model.Number, + Body = "Votre code de sécurité est : " + code + }; + await UserManager.SmsService.SendAsync(message); } + return RedirectToAction("VerifyPhoneNumber", new { PhoneNumber = model.Number }); + } - // - // GET: /Manage/AddPhoneNumber - public ActionResult AddPhoneNumber() + // + // POST: /Manage/EnableTwoFactorAuthentication + [HttpPost] + [ValidateAntiForgeryToken] + public async Task EnableTwoFactorAuthentication() + { + await UserManager.SetTwoFactorEnabledAsync(User.Identity.GetUserId(), true); + var user = await UserManager.FindByIdAsync(User.Identity.GetUserId()); + if (user != null) { - return View(); + await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false); } + return RedirectToAction("Index", "Manage"); + } - // - // POST: /Manage/AddPhoneNumber - [HttpPost] - [ValidateAntiForgeryToken] - public async Task AddPhoneNumber(AddPhoneNumberViewModel model) + // + // POST: /Manage/DisableTwoFactorAuthentication + [HttpPost] + [ValidateAntiForgeryToken] + public async Task DisableTwoFactorAuthentication() + { + await UserManager.SetTwoFactorEnabledAsync(User.Identity.GetUserId(), false); + var user = await UserManager.FindByIdAsync(User.Identity.GetUserId()); + if (user != null) { - if (!ModelState.IsValid) - { - return View(model); - } - // Générer le jeton et l'envoyer - var code = await UserManager.GenerateChangePhoneNumberTokenAsync(User.Identity.GetUserId(), model.Number); - if (UserManager.SmsService != null) - { - var message = new IdentityMessage - { - Destination = model.Number, - Body = "Votre code de sécurité est : " + code - }; - await UserManager.SmsService.SendAsync(message); - } - return RedirectToAction("VerifyPhoneNumber", new { PhoneNumber = model.Number }); + await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false); } + return RedirectToAction("Index", "Manage"); + } + + // + // GET: /Manage/VerifyPhoneNumber + public async Task VerifyPhoneNumber(string phoneNumber) + { + var code = await UserManager.GenerateChangePhoneNumberTokenAsync(User.Identity.GetUserId(), phoneNumber); + // Envoyer un SMS via le fournisseur SMS afin de vérifier le numéro de téléphone + return phoneNumber == null ? View("Error") : View(new VerifyPhoneNumberViewModel { PhoneNumber = phoneNumber }); + } - // - // POST: /Manage/EnableTwoFactorAuthentication - [HttpPost] - [ValidateAntiForgeryToken] - public async Task EnableTwoFactorAuthentication() + // + // POST: /Manage/VerifyPhoneNumber + [HttpPost] + [ValidateAntiForgeryToken] + public async Task VerifyPhoneNumber(VerifyPhoneNumberViewModel model) + { + if (!ModelState.IsValid) { - await UserManager.SetTwoFactorEnabledAsync(User.Identity.GetUserId(), true); - var user = await UserManager.FindByIdAsync(User.Identity.GetUserId()); - if (user != null) - { - await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false); - } - return RedirectToAction("Index", "Manage"); + return View(model); } - - // - // POST: /Manage/DisableTwoFactorAuthentication - [HttpPost] - [ValidateAntiForgeryToken] - public async Task DisableTwoFactorAuthentication() + var result = await UserManager.ChangePhoneNumberAsync(User.Identity.GetUserId(), model.PhoneNumber, model.Code); + if (result.Succeeded) { - await UserManager.SetTwoFactorEnabledAsync(User.Identity.GetUserId(), false); var user = await UserManager.FindByIdAsync(User.Identity.GetUserId()); if (user != null) { await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false); } - return RedirectToAction("Index", "Manage"); + return RedirectToAction("Index", new { Message = ManageMessageId.AddPhoneSuccess }); } + // Si nous sommes arrivés là, quelque chose a échoué, réafficher le formulaire + ModelState.AddModelError("", "La vérification du téléphone a échoué"); + return View(model); + } - // - // GET: /Manage/VerifyPhoneNumber - public async Task VerifyPhoneNumber(string phoneNumber) + // + // POST: /Manage/RemovePhoneNumber + [HttpPost] + [ValidateAntiForgeryToken] + public async Task RemovePhoneNumber() + { + var result = await UserManager.SetPhoneNumberAsync(User.Identity.GetUserId(), null); + if (!result.Succeeded) + { + return RedirectToAction("Index", new { Message = ManageMessageId.Error }); + } + var user = await UserManager.FindByIdAsync(User.Identity.GetUserId()); + if (user != null) { - var code = await UserManager.GenerateChangePhoneNumberTokenAsync(User.Identity.GetUserId(), phoneNumber); - // Envoyer un SMS via le fournisseur SMS afin de vérifier le numéro de téléphone - return phoneNumber == null ? View("Error") : View(new VerifyPhoneNumberViewModel { PhoneNumber = phoneNumber }); + await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false); } + return RedirectToAction("Index", new { Message = ManageMessageId.RemovePhoneSuccess }); + } - // - // POST: /Manage/VerifyPhoneNumber - [HttpPost] - [ValidateAntiForgeryToken] - public async Task VerifyPhoneNumber(VerifyPhoneNumberViewModel model) + // + // GET: /Manage/ChangePassword + public ActionResult ChangePassword() + { + return View(); + } + + // + // POST: /Manage/ChangePassword + [HttpPost] + [ValidateAntiForgeryToken] + public async Task ChangePassword(ChangePasswordViewModel model) + { + if (!ModelState.IsValid) { - if (!ModelState.IsValid) - { - return View(model); - } - var result = await UserManager.ChangePhoneNumberAsync(User.Identity.GetUserId(), model.PhoneNumber, model.Code); - if (result.Succeeded) - { - var user = await UserManager.FindByIdAsync(User.Identity.GetUserId()); - if (user != null) - { - await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false); - } - return RedirectToAction("Index", new { Message = ManageMessageId.AddPhoneSuccess }); - } - // Si nous sommes arrivés là, quelque chose a échoué, réafficher le formulaire - ModelState.AddModelError("", "La vérification du téléphone a échoué"); return View(model); } - - // - // POST: /Manage/RemovePhoneNumber - [HttpPost] - [ValidateAntiForgeryToken] - public async Task RemovePhoneNumber() + var result = await UserManager.ChangePasswordAsync(User.Identity.GetUserId(), model.OldPassword, model.NewPassword); + if (result.Succeeded) { - var result = await UserManager.SetPhoneNumberAsync(User.Identity.GetUserId(), null); - if (!result.Succeeded) - { - return RedirectToAction("Index", new { Message = ManageMessageId.Error }); - } var user = await UserManager.FindByIdAsync(User.Identity.GetUserId()); if (user != null) { await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false); } - return RedirectToAction("Index", new { Message = ManageMessageId.RemovePhoneSuccess }); + return RedirectToAction("Index", new { Message = ManageMessageId.ChangePasswordSuccess }); } + AddErrors(result); + return View(model); + } - // - // GET: /Manage/ChangePassword - public ActionResult ChangePassword() - { - return View(); - } + // + // GET: /Manage/SetPassword + public ActionResult SetPassword() + { + return View(); + } - // - // POST: /Manage/ChangePassword - [HttpPost] - [ValidateAntiForgeryToken] - public async Task ChangePassword(ChangePasswordViewModel model) + // + // POST: /Manage/SetPassword + [HttpPost] + [ValidateAntiForgeryToken] + public async Task SetPassword(SetPasswordViewModel model) + { + if (ModelState.IsValid) { - if (!ModelState.IsValid) - { - return View(model); - } - var result = await UserManager.ChangePasswordAsync(User.Identity.GetUserId(), model.OldPassword, model.NewPassword); + var result = await UserManager.AddPasswordAsync(User.Identity.GetUserId(), model.NewPassword); if (result.Succeeded) { var user = await UserManager.FindByIdAsync(User.Identity.GetUserId()); @@ -237,152 +266,122 @@ public async Task ChangePassword(ChangePasswordViewModel model) { await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false); } - return RedirectToAction("Index", new { Message = ManageMessageId.ChangePasswordSuccess }); + return RedirectToAction("Index", new { Message = ManageMessageId.SetPasswordSuccess }); } AddErrors(result); - return View(model); } - // - // GET: /Manage/SetPassword - public ActionResult SetPassword() - { - return View(); - } + // Si nous sommes arrivés là, quelque chose a échoué, réafficher le formulaire + return View(model); + } - // - // POST: /Manage/SetPassword - [HttpPost] - [ValidateAntiForgeryToken] - public async Task SetPassword(SetPasswordViewModel model) + // + // GET: /Manage/ManageLogins + public async Task ManageLogins(ManageMessageId? message) + { + ViewBag.StatusMessage = + message == ManageMessageId.RemoveLoginSuccess ? "La connexion externe a été supprimée." + : message == ManageMessageId.Error ? "Une erreur s'est produite." + : ""; + var user = await UserManager.FindByIdAsync(User.Identity.GetUserId()); + if (user == null) { - if (ModelState.IsValid) - { - var result = await UserManager.AddPasswordAsync(User.Identity.GetUserId(), model.NewPassword); - if (result.Succeeded) - { - var user = await UserManager.FindByIdAsync(User.Identity.GetUserId()); - if (user != null) - { - await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false); - } - return RedirectToAction("Index", new { Message = ManageMessageId.SetPasswordSuccess }); - } - AddErrors(result); - } - - // Si nous sommes arrivés là, quelque chose a échoué, réafficher le formulaire - return View(model); + return View("Error"); } - - // - // GET: /Manage/ManageLogins - public async Task ManageLogins(ManageMessageId? message) + var userLogins = await UserManager.GetLoginsAsync(User.Identity.GetUserId()); + var otherLogins = AuthenticationManager.GetExternalAuthenticationTypes().Where(auth => userLogins.All(ul => auth.AuthenticationType != ul.LoginProvider)).ToList(); + ViewBag.ShowRemoveButton = user.PasswordHash != null || userLogins.Count > 1; + return View(new ManageLoginsViewModel { - ViewBag.StatusMessage = - message == ManageMessageId.RemoveLoginSuccess ? "La connexion externe a été supprimée." - : message == ManageMessageId.Error ? "Une erreur s'est produite." - : ""; - var user = await UserManager.FindByIdAsync(User.Identity.GetUserId()); - if (user == null) - { - return View("Error"); - } - var userLogins = await UserManager.GetLoginsAsync(User.Identity.GetUserId()); - var otherLogins = AuthenticationManager.GetExternalAuthenticationTypes().Where(auth => userLogins.All(ul => auth.AuthenticationType != ul.LoginProvider)).ToList(); - ViewBag.ShowRemoveButton = user.PasswordHash != null || userLogins.Count > 1; - return View(new ManageLoginsViewModel - { - CurrentLogins = userLogins, - OtherLogins = otherLogins - }); - } + CurrentLogins = userLogins, + OtherLogins = otherLogins + }); + } - // - // POST: /Manage/LinkLogin - [HttpPost] - [ValidateAntiForgeryToken] - public ActionResult LinkLogin(string provider) - { - // Demander une redirection vers le fournisseur de connexion externe afin de lier une connexion pour l'utilisateur actuel - return new AccountController.ChallengeResult(provider, Url.Action("LinkLoginCallback", "Manage"), User.Identity.GetUserId()); - } + // + // POST: /Manage/LinkLogin + [HttpPost] + [ValidateAntiForgeryToken] + public ActionResult LinkLogin(string provider) + { + // Demander une redirection vers le fournisseur de connexion externe afin de lier une connexion pour l'utilisateur actuel + return new AccountController.ChallengeResult(provider, Url.Action("LinkLoginCallback", "Manage"), User.Identity.GetUserId()); + } - // - // GET: /Manage/LinkLoginCallback - public async Task LinkLoginCallback() + // + // GET: /Manage/LinkLoginCallback + public async Task LinkLoginCallback() + { + var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync(XsrfKey, User.Identity.GetUserId()); + if (loginInfo == null) { - var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync(XsrfKey, User.Identity.GetUserId()); - if (loginInfo == null) - { - return RedirectToAction("ManageLogins", new { Message = ManageMessageId.Error }); - } - var result = await UserManager.AddLoginAsync(User.Identity.GetUserId(), loginInfo.Login); - return result.Succeeded ? RedirectToAction("ManageLogins") : RedirectToAction("ManageLogins", new { Message = ManageMessageId.Error }); + return RedirectToAction("ManageLogins", new { Message = ManageMessageId.Error }); } + var result = await UserManager.AddLoginAsync(User.Identity.GetUserId(), loginInfo.Login); + return result.Succeeded ? RedirectToAction("ManageLogins") : RedirectToAction("ManageLogins", new { Message = ManageMessageId.Error }); + } - protected override void Dispose(bool disposing) + protected override void Dispose(bool disposing) + { + if (disposing && _userManager != null) { - if (disposing && _userManager != null) - { - _userManager.Dispose(); - _userManager = null; - } - - base.Dispose(disposing); + _userManager.Dispose(); + _userManager = null; } + base.Dispose(disposing); + } + #region Applications d'assistance - // Utilisé(e) pour la protection XSRF lors de l'ajout de connexions externes - private const string XsrfKey = "XsrfId"; + // Utilisé(e) pour la protection XSRF lors de l'ajout de connexions externes + private const string XsrfKey = "XsrfId"; - private IAuthenticationManager AuthenticationManager + private IAuthenticationManager AuthenticationManager + { + get { - get - { - return HttpContext.GetOwinContext().Authentication; - } + return HttpContext.GetOwinContext().Authentication; } + } - private void AddErrors(IdentityResult result) + private void AddErrors(IdentityResult result) + { + foreach (var error in result.Errors) { - foreach (var error in result.Errors) - { - ModelState.AddModelError("", error); - } + ModelState.AddModelError("", error); } + } - private bool HasPassword() + private bool HasPassword() + { + var user = UserManager.FindById(User.Identity.GetUserId()); + if (user != null) { - var user = UserManager.FindById(User.Identity.GetUserId()); - if (user != null) - { - return user.PasswordHash != null; - } - return false; + return user.PasswordHash != null; } + return false; + } - private bool HasPhoneNumber() + private bool HasPhoneNumber() + { + var user = UserManager.FindById(User.Identity.GetUserId()); + if (user != null) { - var user = UserManager.FindById(User.Identity.GetUserId()); - if (user != null) - { - return user.PhoneNumber != null; - } - return false; + return user.PhoneNumber != null; } + return false; + } - public enum ManageMessageId - { - AddPhoneSuccess, - ChangePasswordSuccess, - SetTwoFactorSuccess, - SetPasswordSuccess, - RemoveLoginSuccess, - RemovePhoneSuccess, - Error - } + public enum ManageMessageId + { + AddPhoneSuccess, + ChangePasswordSuccess, + SetTwoFactorSuccess, + SetPasswordSuccess, + RemoveLoginSuccess, + RemovePhoneSuccess, + Error + } #endregion - } } \ No newline at end of file diff --git a/samples/Mortis/Mortis.Server/Controllers/ResourceController.cs b/samples/Mortis/Mortis.Server/Controllers/ResourceController.cs index ec172df27..bbd718b47 100644 --- a/samples/Mortis/Mortis.Server/Controllers/ResourceController.cs +++ b/samples/Mortis/Mortis.Server/Controllers/ResourceController.cs @@ -9,35 +9,34 @@ using OpenIddict.Validation.Owin; using static OpenIddict.Abstractions.OpenIddictConstants; -namespace Mortis.Server.Controllers +namespace Mortis.Server.Controllers; + +[HostAuthentication(OpenIddictValidationOwinDefaults.AuthenticationType)] +public class ResourceController : ApiController { - [HostAuthentication(OpenIddictValidationOwinDefaults.AuthenticationType)] - public class ResourceController : ApiController + [Authorize, HttpGet, Route("~/api/message")] + public async Task GetMessage() { - [Authorize, HttpGet, Route("~/api/message")] - public async Task GetMessage() - { - var context = Request.GetOwinContext(); - - var user = await context.GetUserManager().FindByIdAsync( - ((ClaimsPrincipal) User).FindFirst(Claims.Subject).Value); - if (user is null) - { - context.Authentication.Challenge( - authenticationTypes: OpenIddictValidationOwinDefaults.AuthenticationType, - properties: new AuthenticationProperties(new Dictionary - { - [OpenIddictValidationOwinConstants.Properties.Error] = Errors.InvalidToken, - [OpenIddictValidationOwinConstants.Properties.ErrorDescription] = - "The specified access token is bound to an account that no longer exists." - })); - return Unauthorized(); - } + var context = Request.GetOwinContext(); - return ResponseMessage(new HttpResponseMessage(HttpStatusCode.OK) - { - Content = new StringContent($"{user.UserName} has been successfully authenticated.") - }); + var user = await context.GetUserManager().FindByIdAsync( + ((ClaimsPrincipal) User).FindFirst(Claims.Subject).Value); + if (user is null) + { + context.Authentication.Challenge( + authenticationTypes: OpenIddictValidationOwinDefaults.AuthenticationType, + properties: new AuthenticationProperties(new Dictionary + { + [OpenIddictValidationOwinConstants.Properties.Error] = Errors.InvalidToken, + [OpenIddictValidationOwinConstants.Properties.ErrorDescription] = + "The specified access token is bound to an account that no longer exists." + })); + return Unauthorized(); } + + return ResponseMessage(new HttpResponseMessage(HttpStatusCode.OK) + { + Content = new StringContent($"{user.UserName} has been successfully authenticated.") + }); } } diff --git a/samples/Mortis/Mortis.Server/Global.asax.cs b/samples/Mortis/Mortis.Server/Global.asax.cs index 519c19ca6..77bfadcba 100644 --- a/samples/Mortis/Mortis.Server/Global.asax.cs +++ b/samples/Mortis/Mortis.Server/Global.asax.cs @@ -3,16 +3,15 @@ using System.Web.Optimization; using System.Web.Routing; -namespace Mortis.Server +namespace Mortis.Server; + +public class MvcApplication : HttpApplication { - public class MvcApplication : HttpApplication + protected void Application_Start() { - protected void Application_Start() - { - AreaRegistration.RegisterAllAreas(); - FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); - RouteConfig.RegisterRoutes(RouteTable.Routes); - BundleConfig.RegisterBundles(BundleTable.Bundles); - } + AreaRegistration.RegisterAllAreas(); + FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); + RouteConfig.RegisterRoutes(RouteTable.Routes); + BundleConfig.RegisterBundles(BundleTable.Bundles); } } diff --git a/samples/Mortis/Mortis.Server/Helpers/AsyncEnumerableExtensions.cs b/samples/Mortis/Mortis.Server/Helpers/AsyncEnumerableExtensions.cs index 3f3d33c26..e57b38b61 100644 --- a/samples/Mortis/Mortis.Server/Helpers/AsyncEnumerableExtensions.cs +++ b/samples/Mortis/Mortis.Server/Helpers/AsyncEnumerableExtensions.cs @@ -2,30 +2,29 @@ using System.Collections.Generic; using System.Threading.Tasks; -namespace Mortis.Server.Helpers +namespace Mortis.Server.Helpers; + +public static class AsyncEnumerableExtensions { - public static class AsyncEnumerableExtensions + public static Task> ToListAsync(this IAsyncEnumerable source) { - public static Task> ToListAsync(this IAsyncEnumerable source) + if (source == null) { - if (source == null) - { - throw new ArgumentNullException(nameof(source)); - } + throw new ArgumentNullException(nameof(source)); + } - return ExecuteAsync(); + return ExecuteAsync(); - async Task> ExecuteAsync() - { - var list = new List(); - - await foreach (var element in source) - { - list.Add(element); - } + async Task> ExecuteAsync() + { + var list = new List(); - return list; + await foreach (var element in source) + { + list.Add(element); } + + return list; } } } diff --git a/samples/Mortis/Mortis.Server/Helpers/FormValueRequiredAttribute.cs b/samples/Mortis/Mortis.Server/Helpers/FormValueRequiredAttribute.cs index f721aa0b0..4c239e598 100644 --- a/samples/Mortis/Mortis.Server/Helpers/FormValueRequiredAttribute.cs +++ b/samples/Mortis/Mortis.Server/Helpers/FormValueRequiredAttribute.cs @@ -2,38 +2,37 @@ using System.Reflection; using System.Web.Mvc; -namespace Mortis.Server.Helpers +namespace Mortis.Server.Helpers; + +public sealed class FormValueRequiredAttribute : ActionMethodSelectorAttribute { - public sealed class FormValueRequiredAttribute : ActionMethodSelectorAttribute + private readonly string _name; + + public FormValueRequiredAttribute(string name) { - private readonly string _name; + _name = name; + } - public FormValueRequiredAttribute(string name) + public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo) + { + if (string.Equals(controllerContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase) || + string.Equals(controllerContext.HttpContext.Request.HttpMethod, "HEAD", StringComparison.OrdinalIgnoreCase) || + string.Equals(controllerContext.HttpContext.Request.HttpMethod, "DELETE", StringComparison.OrdinalIgnoreCase) || + string.Equals(controllerContext.HttpContext.Request.HttpMethod, "TRACE", StringComparison.OrdinalIgnoreCase)) { - _name = name; + return false; } - public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo) + if (string.IsNullOrEmpty(controllerContext.HttpContext.Request.ContentType)) { - if (string.Equals(controllerContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase) || - string.Equals(controllerContext.HttpContext.Request.HttpMethod, "HEAD", StringComparison.OrdinalIgnoreCase) || - string.Equals(controllerContext.HttpContext.Request.HttpMethod, "DELETE", StringComparison.OrdinalIgnoreCase) || - string.Equals(controllerContext.HttpContext.Request.HttpMethod, "TRACE", StringComparison.OrdinalIgnoreCase)) - { - return false; - } - - if (string.IsNullOrEmpty(controllerContext.HttpContext.Request.ContentType)) - { - return false; - } - - if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/x-www-form-urlencoded", StringComparison.OrdinalIgnoreCase)) - { - return false; - } + return false; + } - return !string.IsNullOrEmpty(controllerContext.HttpContext.Request.Form[_name]); + if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/x-www-form-urlencoded", StringComparison.OrdinalIgnoreCase)) + { + return false; } + + return !string.IsNullOrEmpty(controllerContext.HttpContext.Request.Form[_name]); } } diff --git a/samples/Mortis/Mortis.Server/Models/AccountViewModels.cs b/samples/Mortis/Mortis.Server/Models/AccountViewModels.cs index 1eb05ef60..ed9d55e1b 100644 --- a/samples/Mortis/Mortis.Server/Models/AccountViewModels.cs +++ b/samples/Mortis/Mortis.Server/Models/AccountViewModels.cs @@ -1,112 +1,111 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -namespace Mortis.Server.Models +namespace Mortis.Server.Models; + +public class ExternalLoginConfirmationViewModel +{ + [Required] + [Display(Name = "Courrier électronique")] + public string Email { get; set; } +} + +public class ExternalLoginListViewModel +{ + public string ReturnUrl { get; set; } +} + +public class SendCodeViewModel +{ + public string SelectedProvider { get; set; } + public ICollection Providers { get; set; } + public string ReturnUrl { get; set; } + public bool RememberMe { get; set; } +} + +public class VerifyCodeViewModel +{ + [Required] + public string Provider { get; set; } + + [Required] + [Display(Name = "Code")] + public string Code { get; set; } + public string ReturnUrl { get; set; } + + [Display(Name = "Mémoriser ce navigateur ?")] + public bool RememberBrowser { get; set; } + + public bool RememberMe { get; set; } +} + +public class ForgotViewModel +{ + [Required] + [Display(Name = "Courrier électronique")] + public string Email { get; set; } +} + +public class LoginViewModel +{ + [Required] + [Display(Name = "Courrier électronique")] + [EmailAddress] + public string Email { get; set; } + + [Required] + [DataType(DataType.Password)] + [Display(Name = "Mot de passe")] + public string Password { get; set; } + + [Display(Name = "Mémoriser mes informations")] + public bool RememberMe { get; set; } +} + +public class RegisterViewModel +{ + [Required] + [EmailAddress] + [Display(Name = "Courrier électronique")] + public string Email { get; set; } + + [Required] + [StringLength(100, ErrorMessage = "{0} doit contenir au moins {2} caractères.", MinimumLength = 6)] + [DataType(DataType.Password)] + [Display(Name = "Mot de passe")] + public string Password { get; set; } + + [DataType(DataType.Password)] + [Display(Name = "Confirmer le mot de passe")] + [Compare("Password", ErrorMessage = "Le nouveau mot de passe et le mot de passe de confirmation ne correspondent pas.")] + public string ConfirmPassword { get; set; } +} + +public class ResetPasswordViewModel +{ + [Required] + [EmailAddress] + [Display(Name = "Courrier électronique")] + public string Email { get; set; } + + [Required] + [StringLength(100, ErrorMessage = "{0} doit contenir au moins {2} caractères.", MinimumLength = 6)] + [DataType(DataType.Password)] + [Display(Name = "Mot de passe")] + public string Password { get; set; } + + [DataType(DataType.Password)] + [Display(Name = "Confirmer le mot de passe")] + [Compare("Password", ErrorMessage = "Le nouveau mot de passe et le mot de passe de confirmation ne correspondent pas.")] + public string ConfirmPassword { get; set; } + + public string Code { get; set; } +} + +public class ForgotPasswordViewModel { - public class ExternalLoginConfirmationViewModel - { - [Required] - [Display(Name = "Courrier électronique")] - public string Email { get; set; } - } - - public class ExternalLoginListViewModel - { - public string ReturnUrl { get; set; } - } - - public class SendCodeViewModel - { - public string SelectedProvider { get; set; } - public ICollection Providers { get; set; } - public string ReturnUrl { get; set; } - public bool RememberMe { get; set; } - } - - public class VerifyCodeViewModel - { - [Required] - public string Provider { get; set; } - - [Required] - [Display(Name = "Code")] - public string Code { get; set; } - public string ReturnUrl { get; set; } - - [Display(Name = "Mémoriser ce navigateur ?")] - public bool RememberBrowser { get; set; } - - public bool RememberMe { get; set; } - } - - public class ForgotViewModel - { - [Required] - [Display(Name = "Courrier électronique")] - public string Email { get; set; } - } - - public class LoginViewModel - { - [Required] - [Display(Name = "Courrier électronique")] - [EmailAddress] - public string Email { get; set; } - - [Required] - [DataType(DataType.Password)] - [Display(Name = "Mot de passe")] - public string Password { get; set; } - - [Display(Name = "Mémoriser mes informations")] - public bool RememberMe { get; set; } - } - - public class RegisterViewModel - { - [Required] - [EmailAddress] - [Display(Name = "Courrier électronique")] - public string Email { get; set; } - - [Required] - [StringLength(100, ErrorMessage = "{0} doit contenir au moins {2} caractères.", MinimumLength = 6)] - [DataType(DataType.Password)] - [Display(Name = "Mot de passe")] - public string Password { get; set; } - - [DataType(DataType.Password)] - [Display(Name = "Confirmer le mot de passe")] - [Compare("Password", ErrorMessage = "Le nouveau mot de passe et le mot de passe de confirmation ne correspondent pas.")] - public string ConfirmPassword { get; set; } - } - - public class ResetPasswordViewModel - { - [Required] - [EmailAddress] - [Display(Name = "Courrier électronique")] - public string Email { get; set; } - - [Required] - [StringLength(100, ErrorMessage = "{0} doit contenir au moins {2} caractères.", MinimumLength = 6)] - [DataType(DataType.Password)] - [Display(Name = "Mot de passe")] - public string Password { get; set; } - - [DataType(DataType.Password)] - [Display(Name = "Confirmer le mot de passe")] - [Compare("Password", ErrorMessage = "Le nouveau mot de passe et le mot de passe de confirmation ne correspondent pas.")] - public string ConfirmPassword { get; set; } - - public string Code { get; set; } - } - - public class ForgotPasswordViewModel - { - [Required] - [EmailAddress] - [Display(Name = "E-mail")] - public string Email { get; set; } - } + [Required] + [EmailAddress] + [Display(Name = "E-mail")] + public string Email { get; set; } } diff --git a/samples/Mortis/Mortis.Server/Models/IdentityModels.cs b/samples/Mortis/Mortis.Server/Models/IdentityModels.cs index 0622f5af3..9aa54011b 100644 --- a/samples/Mortis/Mortis.Server/Models/IdentityModels.cs +++ b/samples/Mortis/Mortis.Server/Models/IdentityModels.cs @@ -4,37 +4,36 @@ using Microsoft.AspNet.Identity; using Microsoft.AspNet.Identity.EntityFramework; -namespace Mortis.Server.Models +namespace Mortis.Server.Models; + +// Vous pouvez ajouter des données de profil pour l'utilisateur en ajoutant d'autres propriétés à votre classe ApplicationUser. Pour en savoir plus, consultez https://go.microsoft.com/fwlink/?LinkID=317594. +public class ApplicationUser : IdentityUser { - // Vous pouvez ajouter des données de profil pour l'utilisateur en ajoutant d'autres propriétés à votre classe ApplicationUser. Pour en savoir plus, consultez https://go.microsoft.com/fwlink/?LinkID=317594. - public class ApplicationUser : IdentityUser + public async Task GenerateUserIdentityAsync(UserManager manager) { - public async Task GenerateUserIdentityAsync(UserManager manager) - { - // Notez que l'authenticationType doit correspondre à celui défini dans CookieAuthenticationOptions.AuthenticationType - var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie); - // Ajouter des revendications utilisateur personnalisées ici - return userIdentity; - } + // Notez que l'authenticationType doit correspondre à celui défini dans CookieAuthenticationOptions.AuthenticationType + var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie); + // Ajouter des revendications utilisateur personnalisées ici + return userIdentity; } +} - public class ApplicationDbContext : IdentityDbContext +public class ApplicationDbContext : IdentityDbContext +{ + public ApplicationDbContext() + : base("DefaultConnection", throwIfV1Schema: false) { - public ApplicationDbContext() - : base("DefaultConnection", throwIfV1Schema: false) - { - } + } - public static ApplicationDbContext Create() - { - return new ApplicationDbContext(); - } + public static ApplicationDbContext Create() + { + return new ApplicationDbContext(); + } - protected override void OnModelCreating(DbModelBuilder modelBuilder) - { - base.OnModelCreating(modelBuilder); + protected override void OnModelCreating(DbModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); - modelBuilder.UseOpenIddict(); - } + modelBuilder.UseOpenIddict(); } } \ No newline at end of file diff --git a/samples/Mortis/Mortis.Server/Models/ManageViewModels.cs b/samples/Mortis/Mortis.Server/Models/ManageViewModels.cs index 35b7eb6dd..429a97535 100644 --- a/samples/Mortis/Mortis.Server/Models/ManageViewModels.cs +++ b/samples/Mortis/Mortis.Server/Models/ManageViewModels.cs @@ -3,84 +3,83 @@ using Microsoft.AspNet.Identity; using Microsoft.Owin.Security; -namespace Mortis.Server.Models +namespace Mortis.Server.Models; + +public class IndexViewModel { - public class IndexViewModel - { - public bool HasPassword { get; set; } - public IList Logins { get; set; } - public string PhoneNumber { get; set; } - public bool TwoFactor { get; set; } - public bool BrowserRemembered { get; set; } - } + public bool HasPassword { get; set; } + public IList Logins { get; set; } + public string PhoneNumber { get; set; } + public bool TwoFactor { get; set; } + public bool BrowserRemembered { get; set; } +} - public class ManageLoginsViewModel - { - public IList CurrentLogins { get; set; } - public IList OtherLogins { get; set; } - } +public class ManageLoginsViewModel +{ + public IList CurrentLogins { get; set; } + public IList OtherLogins { get; set; } +} - public class FactorViewModel - { - public string Purpose { get; set; } - } +public class FactorViewModel +{ + public string Purpose { get; set; } +} - public class SetPasswordViewModel - { - [Required] - [StringLength(100, ErrorMessage = "La chaîne {0} doit comporter au moins {2} caractères.", MinimumLength = 6)] - [DataType(DataType.Password)] - [Display(Name = "Nouveau mot de passe")] - public string NewPassword { get; set; } +public class SetPasswordViewModel +{ + [Required] + [StringLength(100, ErrorMessage = "La chaîne {0} doit comporter au moins {2} caractères.", MinimumLength = 6)] + [DataType(DataType.Password)] + [Display(Name = "Nouveau mot de passe")] + public string NewPassword { get; set; } - [DataType(DataType.Password)] - [Display(Name = "Confirmer le nouveau mot de passe")] - [Compare("NewPassword", ErrorMessage = "Le nouveau mot de passe et le mot de passe de confirmation ne correspondent pas.")] - public string ConfirmPassword { get; set; } - } + [DataType(DataType.Password)] + [Display(Name = "Confirmer le nouveau mot de passe")] + [Compare("NewPassword", ErrorMessage = "Le nouveau mot de passe et le mot de passe de confirmation ne correspondent pas.")] + public string ConfirmPassword { get; set; } +} - public class ChangePasswordViewModel - { - [Required] - [DataType(DataType.Password)] - [Display(Name = "Mot de passe actuel")] - public string OldPassword { get; set; } +public class ChangePasswordViewModel +{ + [Required] + [DataType(DataType.Password)] + [Display(Name = "Mot de passe actuel")] + public string OldPassword { get; set; } - [Required] - [StringLength(100, ErrorMessage = "La chaîne {0} doit comporter au moins {2} caractères.", MinimumLength = 6)] - [DataType(DataType.Password)] - [Display(Name = "Nouveau mot de passe")] - public string NewPassword { get; set; } + [Required] + [StringLength(100, ErrorMessage = "La chaîne {0} doit comporter au moins {2} caractères.", MinimumLength = 6)] + [DataType(DataType.Password)] + [Display(Name = "Nouveau mot de passe")] + public string NewPassword { get; set; } - [DataType(DataType.Password)] - [Display(Name = "Confirmer le nouveau mot de passe")] - [Compare("NewPassword", ErrorMessage = "Le nouveau mot de passe et le mot de passe de confirmation ne correspondent pas.")] - public string ConfirmPassword { get; set; } - } + [DataType(DataType.Password)] + [Display(Name = "Confirmer le nouveau mot de passe")] + [Compare("NewPassword", ErrorMessage = "Le nouveau mot de passe et le mot de passe de confirmation ne correspondent pas.")] + public string ConfirmPassword { get; set; } +} - public class AddPhoneNumberViewModel - { - [Required] - [Phone] - [Display(Name = "Numéro de téléphone")] - public string Number { get; set; } - } +public class AddPhoneNumberViewModel +{ + [Required] + [Phone] + [Display(Name = "Numéro de téléphone")] + public string Number { get; set; } +} - public class VerifyPhoneNumberViewModel - { - [Required] - [Display(Name = "Code")] - public string Code { get; set; } +public class VerifyPhoneNumberViewModel +{ + [Required] + [Display(Name = "Code")] + public string Code { get; set; } - [Required] - [Phone] - [Display(Name = "Numéro de téléphone")] - public string PhoneNumber { get; set; } - } + [Required] + [Phone] + [Display(Name = "Numéro de téléphone")] + public string PhoneNumber { get; set; } +} - public class ConfigureTwoFactorViewModel - { - public string SelectedProvider { get; set; } - public ICollection Providers { get; set; } - } +public class ConfigureTwoFactorViewModel +{ + public string SelectedProvider { get; set; } + public ICollection Providers { get; set; } } \ No newline at end of file diff --git a/samples/Mortis/Mortis.Server/Startup.cs b/samples/Mortis/Mortis.Server/Startup.cs index 693f99373..a5d5e1b41 100644 --- a/samples/Mortis/Mortis.Server/Startup.cs +++ b/samples/Mortis/Mortis.Server/Startup.cs @@ -19,164 +19,163 @@ using static OpenIddict.Abstractions.OpenIddictConstants; [assembly: OwinStartup(typeof(Mortis.Server.Startup))] -namespace Mortis.Server +namespace Mortis.Server; + +public class Startup { - public class Startup + public void Configuration(IAppBuilder app) { - public void Configuration(IAppBuilder app) - { - var services = new ServiceCollection(); + var services = new ServiceCollection(); - services.AddOpenIddict() + services.AddOpenIddict() - // Register the OpenIddict core components. - .AddCore(options => - { - // Configure OpenIddict to use the Entity Framework 6.x stores and models. - // Note: call ReplaceDefaultEntities() to replace the default OpenIddict entities. - options.UseEntityFramework() - .UseDbContext(); - }) - - // Register the OpenIddict server components. - .AddServer(options => - { - // Enable the authorization, logout and token endpoints. - options.SetAuthorizationEndpointUris("connect/authorize") - .SetLogoutEndpointUris("connect/logout") - .SetTokenEndpointUris("connect/token"); - - // Mark the "email", "profile" and "roles" scopes as supported scopes. - options.RegisterScopes(Scopes.Email, Scopes.Profile, Scopes.Roles); - - // Note: this sample only uses the authorization code flow but you can enable - // the other flows if you need to support implicit, password or client credentials. - options.AllowAuthorizationCodeFlow(); - - // Register the signing and encryption credentials. - options.AddDevelopmentEncryptionCertificate() - .AddDevelopmentSigningCertificate(); - - // Register the OWIN host and configure the OWIN-specific options. - options.UseOwin() - .EnableAuthorizationEndpointPassthrough() - .EnableLogoutEndpointPassthrough() - .EnableTokenEndpointPassthrough(); - }) - - // Register the OpenIddict validation components. - .AddValidation(options => - { - // Import the configuration from the local OpenIddict server instance. - options.UseLocalServer(); + // Register the OpenIddict core components. + .AddCore(options => + { + // Configure OpenIddict to use the Entity Framework 6.x stores and models. + // Note: call ReplaceDefaultEntities() to replace the default OpenIddict entities. + options.UseEntityFramework() + .UseDbContext(); + }) + + // Register the OpenIddict server components. + .AddServer(options => + { + // Enable the authorization, logout and token endpoints. + options.SetAuthorizationEndpointUris("connect/authorize") + .SetLogoutEndpointUris("connect/logout") + .SetTokenEndpointUris("connect/token"); + + // Mark the "email", "profile" and "roles" scopes as supported scopes. + options.RegisterScopes(Scopes.Email, Scopes.Profile, Scopes.Roles); + + // Note: this sample only uses the authorization code flow but you can enable + // the other flows if you need to support implicit, password or client credentials. + options.AllowAuthorizationCodeFlow(); + + // Register the signing and encryption credentials. + options.AddDevelopmentEncryptionCertificate() + .AddDevelopmentSigningCertificate(); + + // Register the OWIN host and configure the OWIN-specific options. + options.UseOwin() + .EnableAuthorizationEndpointPassthrough() + .EnableLogoutEndpointPassthrough() + .EnableTokenEndpointPassthrough(); + }) + + // Register the OpenIddict validation components. + .AddValidation(options => + { + // Import the configuration from the local OpenIddict server instance. + options.UseLocalServer(); - // Register the OWIN host. - options.UseOwin(); - }); + // Register the OWIN host. + options.UseOwin(); + }); - // Create a new Autofac container and import the OpenIddict services. - var builder = new ContainerBuilder(); - builder.Populate(services); + // Create a new Autofac container and import the OpenIddict services. + var builder = new ContainerBuilder(); + builder.Populate(services); - // Register the MVC controllers. - builder.RegisterControllers(typeof(Startup).Assembly); + // Register the MVC controllers. + builder.RegisterControllers(typeof(Startup).Assembly); - // Register the Web API controllers. - builder.RegisterApiControllers(typeof(Startup).Assembly); + // Register the Web API controllers. + builder.RegisterApiControllers(typeof(Startup).Assembly); - var container = builder.Build(); + var container = builder.Build(); - // Register the Entity Framework context and the user/sign-in managers used by ASP.NET Identity. - app.CreatePerOwinContext(ApplicationDbContext.Create); - app.CreatePerOwinContext(ApplicationUserManager.Create); - app.CreatePerOwinContext(ApplicationSignInManager.Create); + // Register the Entity Framework context and the user/sign-in managers used by ASP.NET Identity. + app.CreatePerOwinContext(ApplicationDbContext.Create); + app.CreatePerOwinContext(ApplicationUserManager.Create); + app.CreatePerOwinContext(ApplicationSignInManager.Create); - // Register the cookie middleware used by ASP.NET Identity. - app.UseCookieAuthentication(new CookieAuthenticationOptions + // Register the cookie middleware used by ASP.NET Identity. + app.UseCookieAuthentication(new CookieAuthenticationOptions + { + AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, + LoginPath = new PathString("/Account/Login"), + Provider = new CookieAuthenticationProvider { - AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, - LoginPath = new PathString("/Account/Login"), - Provider = new CookieAuthenticationProvider - { - OnValidateIdentity = SecurityStampValidator.OnValidateIdentity( - validateInterval: TimeSpan.FromMinutes(30), - regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager)) - } - }); + OnValidateIdentity = SecurityStampValidator.OnValidateIdentity( + validateInterval: TimeSpan.FromMinutes(30), + regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager)) + } + }); - app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie); - app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5)); - app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie); + app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie); + app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5)); + app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie); - // Register the Autofac scope injector middleware. - app.UseAutofacLifetimeScopeInjector(container); + // Register the Autofac scope injector middleware. + app.UseAutofacLifetimeScopeInjector(container); - // Register the two OpenIddict server/validation middleware. - app.UseMiddlewareFromContainer(); - app.UseMiddlewareFromContainer(); + // Register the two OpenIddict server/validation middleware. + app.UseMiddlewareFromContainer(); + app.UseMiddlewareFromContainer(); - // Configure ASP.NET MVC 5.2 to use Autofac when activating controller instances. - DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); + // Configure ASP.NET MVC to use Autofac when activating controller instances. + DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); - // Configure ASP.NET MVC 5.2 to use Autofac when activating controller instances - // and infer the Web API routes using the HTTP attributes used in the controllers. - var configuration = new HttpConfiguration - { - DependencyResolver = new AutofacWebApiDependencyResolver(container) - }; + // Configure ASP.NET Web API to use Autofac when activating controller instances + // and infer the Web API routes using the HTTP attributes used in the controllers. + var configuration = new HttpConfiguration + { + DependencyResolver = new AutofacWebApiDependencyResolver(container) + }; - configuration.MapHttpAttributeRoutes(); - configuration.SuppressDefaultHostAuthentication(); + configuration.MapHttpAttributeRoutes(); + configuration.SuppressDefaultHostAuthentication(); - // Register the Autofac Web API integration and Web API middleware. - app.UseAutofacWebApi(configuration); - app.UseWebApi(configuration); + // Register the Autofac Web API integration and Web API middleware. + app.UseAutofacWebApi(configuration); + app.UseWebApi(configuration); - // Seed the database with the sample client using the OpenIddict application manager. - // Note: in a real world application, this step should be part of a setup script. - Task.Run(async delegate - { - await using var scope = container.BeginLifetimeScope(); + // Seed the database with the sample client using the OpenIddict application manager. + // Note: in a real world application, this step should be part of a setup script. + Task.Run(async delegate + { + await using var scope = container.BeginLifetimeScope(); - var context = scope.Resolve(); - context.Database.CreateIfNotExists(); + var context = scope.Resolve(); + context.Database.CreateIfNotExists(); - var manager = scope.Resolve(); + var manager = scope.Resolve(); - if (await manager.FindByClientIdAsync("mvc") == null) + if (await manager.FindByClientIdAsync("mvc") == null) + { + await manager.CreateAsync(new OpenIddictApplicationDescriptor { - await manager.CreateAsync(new OpenIddictApplicationDescriptor + ClientId = "mvc", + ClientSecret = "901564A5-E7FE-42CB-B10D-61EF6A8F3654", + ConsentType = ConsentTypes.Explicit, + DisplayName = "MVC client application", + RedirectUris = + { + new Uri("https://localhost:44378/callback/login/local") + }, + PostLogoutRedirectUris = + { + new Uri("https://localhost:44378/callback/logout/local") + }, + Permissions = { - ClientId = "mvc", - ClientSecret = "901564A5-E7FE-42CB-B10D-61EF6A8F3654", - ConsentType = ConsentTypes.Explicit, - DisplayName = "MVC client application", - RedirectUris = - { - new Uri("https://localhost:44378/callback/login/local") - }, - PostLogoutRedirectUris = - { - new Uri("https://localhost:44378/callback/logout/local") - }, - Permissions = - { - Permissions.Endpoints.Authorization, - Permissions.Endpoints.Logout, - Permissions.Endpoints.Token, - Permissions.GrantTypes.AuthorizationCode, - Permissions.ResponseTypes.Code, - Permissions.Scopes.Email, - Permissions.Scopes.Profile, - Permissions.Scopes.Roles - }, - Requirements = - { - Requirements.Features.ProofKeyForCodeExchange - } - }); - } - }).GetAwaiter().GetResult(); - } + Permissions.Endpoints.Authorization, + Permissions.Endpoints.Logout, + Permissions.Endpoints.Token, + Permissions.GrantTypes.AuthorizationCode, + Permissions.ResponseTypes.Code, + Permissions.Scopes.Email, + Permissions.Scopes.Profile, + Permissions.Scopes.Roles + }, + Requirements = + { + Requirements.Features.ProofKeyForCodeExchange + } + }); + } + }).GetAwaiter().GetResult(); } } diff --git a/samples/Mortis/Mortis.Server/ViewModels/Authorization/AuthorizeViewModel.cs b/samples/Mortis/Mortis.Server/ViewModels/Authorization/AuthorizeViewModel.cs index 38c4c7159..7d3dfc2a7 100644 --- a/samples/Mortis/Mortis.Server/ViewModels/Authorization/AuthorizeViewModel.cs +++ b/samples/Mortis/Mortis.Server/ViewModels/Authorization/AuthorizeViewModel.cs @@ -1,11 +1,10 @@ using System.Collections.Generic; using System.Web.Mvc; -namespace Mortis.Server.ViewModels.Authorization +namespace Mortis.Server.ViewModels.Authorization; + +[Bind(Exclude = nameof(Parameters))] +public class LogoutViewModel { - [Bind(Exclude = nameof(Parameters))] - public class LogoutViewModel - { - public IEnumerable> Parameters { get; internal set; } - } + public IEnumerable> Parameters { get; internal set; } } diff --git a/samples/Mortis/Mortis.Server/ViewModels/Authorization/LogoutViewModel.cs b/samples/Mortis/Mortis.Server/ViewModels/Authorization/LogoutViewModel.cs index b79a99992..5d7892364 100644 --- a/samples/Mortis/Mortis.Server/ViewModels/Authorization/LogoutViewModel.cs +++ b/samples/Mortis/Mortis.Server/ViewModels/Authorization/LogoutViewModel.cs @@ -2,17 +2,16 @@ using System.ComponentModel.DataAnnotations; using System.Web.Mvc; -namespace Mortis.Server.ViewModels.Authorization +namespace Mortis.Server.ViewModels.Authorization; + +[Bind(Exclude = nameof(Parameters))] +public class AuthorizeViewModel { - [Bind(Exclude = nameof(Parameters))] - public class AuthorizeViewModel - { - [Display(Name = "Application")] - public string ApplicationName { get; set; } + [Display(Name = "Application")] + public string ApplicationName { get; set; } - [Display(Name = "Scope")] - public string Scope { get; set; } + [Display(Name = "Scope")] + public string Scope { get; set; } - public IEnumerable> Parameters { get; internal set; } - } + public IEnumerable> Parameters { get; internal set; } }