From 1c8debd894949f09186a272194997e8508387edc Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Thu, 31 Mar 2022 08:35:11 -0400 Subject: [PATCH] better seperation of concerns --- Oqtane.Client/Modules/Admin/Users/Index.razor | 19 ++++++++++------- .../Resources/Modules/Admin/Users/Index.resx | 2 +- .../Middleware/JwtMiddleware.cs | 17 +++++++++++---- Oqtane.Server/Security/JwtManager.cs | 21 +++++++++---------- 4 files changed, 35 insertions(+), 24 deletions(-) diff --git a/Oqtane.Client/Modules/Admin/Users/Index.razor b/Oqtane.Client/Modules/Admin/Users/Index.razor index 21154914..c6e6d237 100644 --- a/Oqtane.Client/Modules/Admin/Users/Index.razor +++ b/Oqtane.Client/Modules/Admin/Users/Index.razor @@ -95,15 +95,18 @@ else -
- -
- + @if (!string.IsNullOrEmpty(PageState.Alias.Path)) + { +
+ +
+ +
-
+ }
diff --git a/Oqtane.Client/Resources/Modules/Admin/Users/Index.resx b/Oqtane.Client/Resources/Modules/Admin/Users/Index.resx index 01cb2c95..a5c8c285 100644 --- a/Oqtane.Client/Resources/Modules/Admin/Users/Index.resx +++ b/Oqtane.Client/Resources/Modules/Admin/Users/Index.resx @@ -319,7 +319,7 @@ User Settings - Login cookies are usually managed per domain. However you can also choose to have distinct cookies for each site. + Cookies are usually managed per domain. However you can also choose to have distinct cookies for each site (this option is only applicable to micro-sites). Login Cookie Type: diff --git a/Oqtane.Server/Infrastructure/Middleware/JwtMiddleware.cs b/Oqtane.Server/Infrastructure/Middleware/JwtMiddleware.cs index 4297981c..baba6085 100644 --- a/Oqtane.Server/Infrastructure/Middleware/JwtMiddleware.cs +++ b/Oqtane.Server/Infrastructure/Middleware/JwtMiddleware.cs @@ -3,6 +3,7 @@ using System.Security.Claims; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Oqtane.Extensions; +using Oqtane.Models; using Oqtane.Repository; using Oqtane.Security; using Oqtane.Shared; @@ -33,14 +34,22 @@ namespace Oqtane.Infrastructure var jwtManager = context.RequestServices.GetService(typeof(IJwtManager)) as IJwtManager; var token = context.Request.Headers["Authorization"].First().Split(" ").Last(); - var user = jwtManager.ValidateToken(token, secret, sitesettings.GetValue("JwtOptions:Issuer", ""), sitesettings.GetValue("JwtOptions:Audience", "")); - if (user != null) + var identity = jwtManager.ValidateToken(token, secret, sitesettings.GetValue("JwtOptions:Issuer", ""), sitesettings.GetValue("JwtOptions:Audience", "")); + if (identity != null && identity.Claims.Any()) { - // populate principal (reload user roles to ensure most accurate permissions) + // create user identity using jwt claims (note the difference in claimtype names) + var user = new User + { + UserId = int.Parse(identity.Claims.FirstOrDefault(item => item.Type == "nameid")?.Value), + Username = identity.Claims.FirstOrDefault(item => item.Type == "name")?.Value + }; + // jwt already contains the roles - we are reloading to ensure most accurate permissions var _userRoles = context.RequestServices.GetService(typeof(IUserRoleRepository)) as IUserRoleRepository; + identity = UserSecurity.CreateClaimsIdentity(alias, user, _userRoles.GetUserRoles(user.UserId, alias.SiteId).ToList()); + + // populate principal var principal = (ClaimsIdentity)context.User.Identity; UserSecurity.ResetClaimsIdentity(principal); - var identity = UserSecurity.CreateClaimsIdentity(alias, user, _userRoles.GetUserRoles(user.UserId, alias.SiteId).ToList()); principal.AddClaims(identity.Claims); logger.Log(alias.SiteId, LogLevel.Information, "TokenValidation", Enums.LogFunction.Security, "Token Validated For User {Username}", user.Username); } diff --git a/Oqtane.Server/Security/JwtManager.cs b/Oqtane.Server/Security/JwtManager.cs index 9a426fc3..a73a3d6c 100644 --- a/Oqtane.Server/Security/JwtManager.cs +++ b/Oqtane.Server/Security/JwtManager.cs @@ -1,6 +1,5 @@ using System; using System.IdentityModel.Tokens.Jwt; -using System.Linq; using System.Security.Claims; using System.Text; using Microsoft.IdentityModel.Tokens; @@ -10,19 +9,19 @@ namespace Oqtane.Security { public interface IJwtManager { - string GenerateToken(Alias alias, ClaimsIdentity user, string secret, string issuer, string audience, int lifetime); - User ValidateToken(string token, string secret, string issuer, string audience); + string GenerateToken(Alias alias, ClaimsIdentity identity, string secret, string issuer, string audience, int lifetime); + ClaimsIdentity ValidateToken(string token, string secret, string issuer, string audience); } public class JwtManager : IJwtManager { - public string GenerateToken(Alias alias, ClaimsIdentity user, string secret, string issuer, string audience, int lifetime) + public string GenerateToken(Alias alias, ClaimsIdentity identity, string secret, string issuer, string audience, int lifetime) { var tokenHandler = new JwtSecurityTokenHandler(); var key = Encoding.ASCII.GetBytes(secret); var tokenDescriptor = new SecurityTokenDescriptor { - Subject = new ClaimsIdentity(user), + Subject = new ClaimsIdentity(identity), Issuer = issuer, Audience = audience, Expires = DateTime.UtcNow.AddMinutes(lifetime), @@ -32,7 +31,7 @@ namespace Oqtane.Security return tokenHandler.WriteToken(token); } - public User ValidateToken(string token, string secret, string issuer, string audience) + public ClaimsIdentity ValidateToken(string token, string secret, string issuer, string audience) { if (!string.IsNullOrEmpty(token)) { @@ -53,12 +52,12 @@ namespace Oqtane.Security }, out SecurityToken validatedToken); var jwtToken = (JwtSecurityToken)validatedToken; - var user = new User + var identity = new ClaimsIdentity(); + foreach (var claim in jwtToken.Claims) { - UserId = int.Parse(jwtToken.Claims.FirstOrDefault(item => item.Type == "nameid")?.Value), - Username = jwtToken.Claims.FirstOrDefault(item => item.Type == "name")?.Value - }; - return user; + identity.AddClaim(claim); + } + return identity; } catch {