From d51ba8f6dd88bcf89e3ecbcaea7d39858fcf30df Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Mon, 14 Mar 2022 22:28:41 -0400 Subject: [PATCH] Improve Principal handling for OIDC and resolve Logout issue (caused by AntiForgeryToken) --- .../Themes/Controls/Theme/LoginBase.cs | 18 +++++++++-------- ...taneSiteAuthenticationBuilderExtensions.cs | 20 ++++++++++--------- Oqtane.Server/Pages/Logout.cshtml.cs | 2 +- 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/Oqtane.Client/Themes/Controls/Theme/LoginBase.cs b/Oqtane.Client/Themes/Controls/Theme/LoginBase.cs index 5a1b34521..1d456565d 100644 --- a/Oqtane.Client/Themes/Controls/Theme/LoginBase.cs +++ b/Oqtane.Client/Themes/Controls/Theme/LoginBase.cs @@ -1,4 +1,5 @@ using System; +using System.Net; using System.Threading.Tasks; using Microsoft.AspNetCore.Components; using Microsoft.JSInterop; @@ -34,24 +35,25 @@ protected async Task LogoutUser() { await UserService.LogoutUserAsync(PageState.User); await LoggingService.Log(PageState.Alias, PageState.Page.PageId, PageState.ModuleId, PageState.User.UserId, GetType().AssemblyQualifiedName, "Logout", LogFunction.Security, LogLevel.Information, null, "User Logout For Username {Username}", PageState.User.Username); - PageState.User = null; - bool authorizedtoviewpage = UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, PageState.Page.Permissions); + + var url = PageState.Alias.Path + "/" + PageState.Page.Path; + if (!UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, PageState.Page.Permissions)) + { + url = PageState.Alias.Path; + } if (PageState.Runtime == Shared.Runtime.Server) { - // server-side Blazor needs to post to the Logout page - var fields = new { __RequestVerificationToken = SiteState.AntiForgeryToken, returnurl = !authorizedtoviewpage ? PageState.Alias.Path : PageState.Alias.Path + "/" + PageState.Page.Path }; - string url = Utilities.TenantUrl(PageState.Alias, "/pages/logout/"); - var interop = new Interop(jsRuntime); - await interop.SubmitForm(url, fields); + // server-side Blazor needs to redirect to the Logout page + NavigationManager.NavigateTo(Utilities.TenantUrl(PageState.Alias, "/pages/logout/") + "?returnurl=" + WebUtility.UrlEncode(url), true); } else { // client-side Blazor var authstateprovider = (IdentityAuthenticationStateProvider)ServiceProvider.GetService(typeof(IdentityAuthenticationStateProvider)); authstateprovider.NotifyAuthenticationChanged(); - NavigationManager.NavigateTo(NavigateUrl(!authorizedtoviewpage ? PageState.Alias.Path : PageState.Page.Path, true)); + NavigationManager.NavigateTo(NavigateUrl(url, true)); } } } diff --git a/Oqtane.Server/Extensions/OqtaneSiteAuthenticationBuilderExtensions.cs b/Oqtane.Server/Extensions/OqtaneSiteAuthenticationBuilderExtensions.cs index dc60fb74b..66137c16b 100644 --- a/Oqtane.Server/Extensions/OqtaneSiteAuthenticationBuilderExtensions.cs +++ b/Oqtane.Server/Extensions/OqtaneSiteAuthenticationBuilderExtensions.cs @@ -104,7 +104,7 @@ private static async Task OnTokenValidated(TokenValidatedContext context) identityuser.UserName = email; identityuser.Email = email; identityuser.EmailConfirmed = true; - var result = await _identityUserManager.CreateAsync(identityuser, Guid.NewGuid().ToString("N") + "-Xx!"); + var result = await _identityUserManager.CreateAsync(identityuser, DateTime.UtcNow.ToString("yyyy-MMM-dd-HH-mm-ss")); if (result.Succeeded) { user = new User(); @@ -164,17 +164,19 @@ private static async Task OnTokenValidated(TokenValidatedContext context) user = _users.GetUser(email); if (user != null) { - List userroles = _userRoles.GetUserRoles(user.UserId, context.HttpContext.GetAlias().SiteId).ToList(); - var identity = UserSecurity.CreateClaimsIdentity(context.HttpContext.GetAlias(), user, userroles); + var principal = (ClaimsIdentity)context.Principal.Identity; - var principalIdentity = (ClaimsIdentity)context.Principal.Identity; - foreach (var claim in identity.Claims) + // remove the name claim if it exists in the principal + var nameclaim = principal.Claims.FirstOrDefault(item => item.Type == ClaimTypes.Name); + if (nameclaim != null) { - if (!principalIdentity.Claims.Contains(claim)) - { - principalIdentity.AddClaim(claim); - } + principal.RemoveClaim(nameclaim); } + + // add Oqtane claims + List userroles = _userRoles.GetUserRoles(user.UserId, context.HttpContext.GetAlias().SiteId).ToList(); + var identity = UserSecurity.CreateClaimsIdentity(context.HttpContext.GetAlias(), user, userroles); + principal.AddClaims(identity.Claims); } } else diff --git a/Oqtane.Server/Pages/Logout.cshtml.cs b/Oqtane.Server/Pages/Logout.cshtml.cs index fc9691b81..eef4dfb70 100644 --- a/Oqtane.Server/Pages/Logout.cshtml.cs +++ b/Oqtane.Server/Pages/Logout.cshtml.cs @@ -10,7 +10,7 @@ namespace Oqtane.Pages [AllowAnonymous] public class LogoutModel : PageModel { - public async Task OnPostAsync(string returnurl) + public async Task OnGetAsync(string returnurl) { if (HttpContext.User.Identity.IsAuthenticated) {