From dffa57e77a5d25b4ce9e337017b18a973c6551b9 Mon Sep 17 00:00:00 2001 From: Joe DeCock Date: Fri, 6 Dec 2024 12:48:33 -0600 Subject: [PATCH] Persist claim issuers in server side sessions --- .../Pages/Account/Login/Index.cshtml.cs | 1 - .../ClaimsPrincipalLiteExtensions.cs | 6 ++++-- src/Storage/Stores/Serialization/ClaimLite.cs | 3 ++- .../Hosting/ServerSideSessionTests.cs | 21 +++++++++++++++++++ 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/hosts/EntityFramework/Pages/Account/Login/Index.cshtml.cs b/hosts/EntityFramework/Pages/Account/Login/Index.cshtml.cs index 16262bc3e..eec8c4a07 100644 --- a/hosts/EntityFramework/Pages/Account/Login/Index.cshtml.cs +++ b/hosts/EntityFramework/Pages/Account/Login/Index.cshtml.cs @@ -11,7 +11,6 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; -using static System.Runtime.InteropServices.JavaScript.JSType; namespace IdentityServerHost.Pages.Login; diff --git a/src/Storage/Extensions/ClaimsPrincipalLiteExtensions.cs b/src/Storage/Extensions/ClaimsPrincipalLiteExtensions.cs index 8619a43e0..d83fa22f1 100644 --- a/src/Storage/Extensions/ClaimsPrincipalLiteExtensions.cs +++ b/src/Storage/Extensions/ClaimsPrincipalLiteExtensions.cs @@ -19,7 +19,7 @@ public static class ClaimsPrincipalLiteExtensions /// public static ClaimsPrincipal ToClaimsPrincipal(this ClaimsPrincipalLite principal) { - var claims = principal.Claims.Select(x => new Claim(x.Type, x.Value, x.ValueType ?? ClaimValueTypes.String)).ToArray(); + var claims = principal.Claims.Select(x => new Claim(x.Type, x.Value, x.ValueType ?? ClaimValueTypes.String, x.Issuer ?? ClaimsIdentity.DefaultIssuer)).ToArray(); var id = new ClaimsIdentity(claims, principal.AuthenticationType, JwtClaimTypes.Name, JwtClaimTypes.Role); return new ClaimsPrincipal(id); @@ -35,7 +35,9 @@ public static ClaimsPrincipalLite ToClaimsPrincipalLite(this ClaimsPrincipal pri { Type = x.Type, Value = x.Value, - ValueType = x.ValueType == ClaimValueTypes.String ? null : x.ValueType + // Leave out default values, to avoid bloat + ValueType = x.ValueType == ClaimValueTypes.String ? null : x.ValueType, + Issuer = x.Issuer == ClaimsIdentity.DefaultIssuer ? null : x.Issuer }).ToArray(); return new ClaimsPrincipalLite diff --git a/src/Storage/Stores/Serialization/ClaimLite.cs b/src/Storage/Stores/Serialization/ClaimLite.cs index c9bb3df76..34d5c9507 100644 --- a/src/Storage/Stores/Serialization/ClaimLite.cs +++ b/src/Storage/Stores/Serialization/ClaimLite.cs @@ -11,4 +11,5 @@ public class ClaimLite public string Type { get; set; } public string Value { get; set; } public string ValueType { get; set; } -} \ No newline at end of file + public string Issuer { get; set; } +} diff --git a/test/IdentityServer.IntegrationTests/Hosting/ServerSideSessionTests.cs b/test/IdentityServer.IntegrationTests/Hosting/ServerSideSessionTests.cs index 6a0f94d62..9c529e457 100644 --- a/test/IdentityServer.IntegrationTests/Hosting/ServerSideSessionTests.cs +++ b/test/IdentityServer.IntegrationTests/Hosting/ServerSideSessionTests.cs @@ -21,6 +21,7 @@ using Duende.IdentityServer; using Microsoft.AspNetCore.DataProtection; using Duende.IdentityServer.Extensions; +using System.Security.Claims; namespace IntegrationTests.Hosting; @@ -743,4 +744,24 @@ public async Task using_access_token_for_expired_session_should_fail() response.IsError.Should().BeTrue(); } } + + + [Fact] + public async Task claim_issuers_should_be_persisted() + { + var claimWithCustomIssuer = new Claim("Test", "true", ClaimValueTypes.Boolean, "Custom Issuer"); + var claimWithDefaultIssuer = new Claim("Test", "false", ClaimValueTypes.Boolean, ClaimsIdentity.DefaultIssuer); + + var user = new IdentityServerUser("alice").CreatePrincipal(); + user.Identities.First().AddClaim(claimWithCustomIssuer); + user.Identities.First().AddClaim(claimWithDefaultIssuer); + + await _pipeline.LoginAsync(user); + + var ticket = (await _sessionStore.GetSessionsAsync(new SessionFilter { SubjectId = "alice" })).Single() + .Deserialize(_protector, null); + var claims = ticket.Principal.Claims; + claims.Should().Contain(c => c.Issuer == "Custom Issuer" && c.Type == "Test"); + claims.Should().Contain(c => c.Issuer == ClaimsIdentity.DefaultIssuer && c.Type == "Test"); + } }