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
{