diff --git a/bff/migrations/Directory.Build.props b/bff/migrations/Directory.Build.props
index 90f2c11d2..e2167e09a 100644
--- a/bff/migrations/Directory.Build.props
+++ b/bff/migrations/Directory.Build.props
@@ -1,4 +1,7 @@
+
+ net9.0
+
diff --git a/bff/migrations/UserSessionDb/UserSessionDb.csproj b/bff/migrations/UserSessionDb/UserSessionDb.csproj
index 3f8805859..69f93e7ac 100644
--- a/bff/migrations/UserSessionDb/UserSessionDb.csproj
+++ b/bff/migrations/UserSessionDb/UserSessionDb.csproj
@@ -1,11 +1,11 @@
- net9.0
+ net9.0
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/bff/samples/Apis/Api.DPoP/Api.DPoP.csproj b/bff/samples/Apis/Api.DPoP/Api.DPoP.csproj
index b6b74ea47..af4bfa95e 100644
--- a/bff/samples/Apis/Api.DPoP/Api.DPoP.csproj
+++ b/bff/samples/Apis/Api.DPoP/Api.DPoP.csproj
@@ -1,7 +1,7 @@
- net9.0
+ net9.0
diff --git a/bff/samples/Bff.EF/Duende.BFF.db b/bff/samples/Bff.EF/Duende.BFF.db
new file mode 100644
index 000000000..96ce58885
Binary files /dev/null and b/bff/samples/Bff.EF/Duende.BFF.db differ
diff --git a/bff/samples/Bff/Bff.csproj b/bff/samples/Bff/Bff.csproj
index 73ef15fda..210c8bf88 100644
--- a/bff/samples/Bff/Bff.csproj
+++ b/bff/samples/Bff/Bff.csproj
@@ -1,7 +1,7 @@
- net9.0
+ net9.0
Bff
enable
diff --git a/bff/samples/Directory.Build.props b/bff/samples/Directory.Build.props
index 90f2c11d2..7e64d18da 100644
--- a/bff/samples/Directory.Build.props
+++ b/bff/samples/Directory.Build.props
@@ -1,4 +1,23 @@
+
+
+ net9.0
+
diff --git a/bff/samples/Hosts.Tests/Hosts.Tests.csproj b/bff/samples/Hosts.Tests/Hosts.Tests.csproj
index 153ba681f..dea8c45b4 100644
--- a/bff/samples/Hosts.Tests/Hosts.Tests.csproj
+++ b/bff/samples/Hosts.Tests/Hosts.Tests.csproj
@@ -1,7 +1,7 @@
- net9.0
+ net9.0
enable
enable
false
diff --git a/bff/src/Duende.Bff.Blazor.Client/ClaimRecord.cs b/bff/src/Duende.Bff.Blazor.Client/ClaimRecord.cs
new file mode 100644
index 000000000..4ef129550
--- /dev/null
+++ b/bff/src/Duende.Bff.Blazor.Client/ClaimRecord.cs
@@ -0,0 +1,41 @@
+using System.Text.Json.Serialization;
+
+namespace Duende.Bff;
+
+///
+/// Serialization friendly claim.
+///
+/// Note, this is a copy of the ClaimRecord class from Duende.Bff, but since we can't create a reference to it, we need to copy it here.
+/// We also can't link to it (as we do with the extensions) because we had to make it public.
+///
+internal class ClaimRecord()
+{
+ ///
+ /// Serialization friendly claim
+ ///
+ /// The type
+ /// The Value
+ internal ClaimRecord(string type, object value) : this()
+ {
+ Type = type;
+ Value = value;
+ }
+
+ ///
+ /// The type
+ ///
+ [JsonPropertyName("type")]
+ public string Type { get; init; } = default!;
+
+ ///
+ /// The value
+ ///
+ [JsonPropertyName("value")]
+ public object Value { get; init; } = default!;
+
+ ///
+ /// The value type
+ ///
+ [JsonPropertyName("valueType")]
+ public string? ValueType { get; init; }
+}
diff --git a/bff/src/Duende.Bff.Blazor.Client/Duende.Bff.Blazor.Client.csproj b/bff/src/Duende.Bff.Blazor.Client/Duende.Bff.Blazor.Client.csproj
index d575ef270..ec07ac15b 100644
--- a/bff/src/Duende.Bff.Blazor.Client/Duende.Bff.Blazor.Client.csproj
+++ b/bff/src/Duende.Bff.Blazor.Client/Duende.Bff.Blazor.Client.csproj
@@ -8,9 +8,8 @@
-
-
-
+
+
diff --git a/bff/src/Duende.Bff.Blazor.Client/Internals/GetUserService.cs b/bff/src/Duende.Bff.Blazor.Client/Internals/GetUserService.cs
index b5629fc15..59b6b06c3 100644
--- a/bff/src/Duende.Bff.Blazor.Client/Internals/GetUserService.cs
+++ b/bff/src/Duende.Bff.Blazor.Client/Internals/GetUserService.cs
@@ -58,9 +58,6 @@ public async ValueTask GetUserAsync(bool useCache = true)
return _cachedUser;
}
- // TODO - Consider using ClaimLite instead here
- record ClaimRecord(string Type, object Value);
-
internal async Task FetchUser()
{
try
diff --git a/bff/src/Duende.Bff.Blazor.Client/Internals/PersistentUserService.cs b/bff/src/Duende.Bff.Blazor.Client/Internals/PersistentUserService.cs
index af2d98ddc..27205cf44 100644
--- a/bff/src/Duende.Bff.Blazor.Client/Internals/PersistentUserService.cs
+++ b/bff/src/Duende.Bff.Blazor.Client/Internals/PersistentUserService.cs
@@ -17,7 +17,7 @@ internal class PersistentUserService(PersistentComponentState state, ILogger
public ClaimsPrincipal GetPersistedUser()
{
- if (!state.TryTakeFromJson(nameof(ClaimsPrincipalLite), out var lite) || lite is null)
+ if (!state.TryTakeFromJson(nameof(ClaimsPrincipalRecord), out var lite) || lite is null)
{
logger.LogDebug("Failed to load persisted user.");
return new ClaimsPrincipal(new ClaimsIdentity());
diff --git a/bff/src/Duende.Bff.Blazor/BffServerAuthenticationStateProvider.cs b/bff/src/Duende.Bff.Blazor/BffServerAuthenticationStateProvider.cs
index ade0a888c..89760b5e9 100644
--- a/bff/src/Duende.Bff.Blazor/BffServerAuthenticationStateProvider.cs
+++ b/bff/src/Duende.Bff.Blazor/BffServerAuthenticationStateProvider.cs
@@ -73,14 +73,14 @@ private async Task OnPersistingAsync()
var authenticationState = await _authenticationStateTask;
var claims = authenticationState.User.Claims
- .Select(c => new ClaimLite
+ .Select(c => new ClaimRecord
{
Type = c.Type,
Value = c.Value?.ToString() ?? string.Empty,
ValueType = c.ValueType == ClaimValueTypes.String ? null : c.ValueType
}).ToArray();
- var principal = new ClaimsPrincipalLite
+ var principal = new ClaimsPrincipalRecord
{
AuthenticationType = authenticationState.User.Identity!.AuthenticationType,
NameClaimType = authenticationState.User.Identities.First().NameClaimType,
@@ -90,7 +90,7 @@ private async Task OnPersistingAsync()
_logger.LogDebug("Persisting Authentication State");
- _state.PersistAsJson(nameof(ClaimsPrincipalLite), principal);
+ _state.PersistAsJson(nameof(ClaimsPrincipalRecord), principal);
}
diff --git a/bff/src/Duende.Bff/EndpointServices/User/DefaultUserService.cs b/bff/src/Duende.Bff/EndpointServices/User/DefaultUserService.cs
index c15a3957b..a057b662b 100644
--- a/bff/src/Duende.Bff/EndpointServices/User/DefaultUserService.cs
+++ b/bff/src/Duende.Bff/EndpointServices/User/DefaultUserService.cs
@@ -8,6 +8,7 @@
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using System;
using System.Collections.Generic;
+using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.Encodings.Web;
@@ -134,20 +135,5 @@ protected virtual Task> GetManagementClaimsAsync(HttpCo
return Task.FromResult((IEnumerable)claims);
}
-
- ///
- /// Serialization-friendly claim
- ///
- ///
- ///
- protected record ClaimRecord(string Type, object Value)
- {
- ///
- [JsonPropertyName("type")]
- public string Type { get; init; } = Type;
- ///
- [JsonPropertyName("value")]
- public object Value { get; init; } = Value;
- }
}
\ No newline at end of file
diff --git a/bff/src/Duende.Bff/Extensions/AuthenticationTicketExtensions.cs b/bff/src/Duende.Bff/Extensions/AuthenticationTicketExtensions.cs
index 2464667be..b23cdcfe3 100644
--- a/bff/src/Duende.Bff/Extensions/AuthenticationTicketExtensions.cs
+++ b/bff/src/Duende.Bff/Extensions/AuthenticationTicketExtensions.cs
@@ -149,7 +149,7 @@ internal class AuthenticationTicketLite
///
/// The user
///
- public ClaimsPrincipalLite User { get; set; } = default!;
+ public ClaimsPrincipalRecord User { get; set; } = default!;
///
/// The items
diff --git a/bff/src/Duende.Bff/Shared/ClaimLite.cs b/bff/src/Duende.Bff/Shared/ClaimRecord.cs
similarity index 50%
rename from bff/src/Duende.Bff/Shared/ClaimLite.cs
rename to bff/src/Duende.Bff/Shared/ClaimRecord.cs
index 6a1189c45..426b0ee01 100644
--- a/bff/src/Duende.Bff/Shared/ClaimLite.cs
+++ b/bff/src/Duende.Bff/Shared/ClaimRecord.cs
@@ -1,25 +1,41 @@
// Copyright (c) Duende Software. All rights reserved.
// See LICENSE in the project root for license information.
+using System.Text.Json.Serialization;
+
namespace Duende.Bff;
///
/// Serialization friendly claim
///
-internal class ClaimLite
+public class ClaimRecord()
{
+ ///
+ ///
+ ///
+ ///
+ ///
+ public ClaimRecord(string type, object value) : this()
+ {
+ Type = type;
+ Value = value;
+ }
+
///
/// The type
///
+ [JsonPropertyName("type")]
public string Type { get; init; } = default!;
///
/// The value
///
- public string Value { get; init; } = default!;
+ [JsonPropertyName("value")]
+ public object Value { get; init; } = default!;
///
/// The value type
///
+ [JsonPropertyName("valueType")]
public string? ValueType { get; init; }
}
\ No newline at end of file
diff --git a/bff/src/Duende.Bff/Shared/ClaimsLiteExtensions.cs b/bff/src/Duende.Bff/Shared/ClaimRecordExtensions.cs
similarity index 79%
rename from bff/src/Duende.Bff/Shared/ClaimsLiteExtensions.cs
rename to bff/src/Duende.Bff/Shared/ClaimRecordExtensions.cs
index da7073af4..dafb25eda 100644
--- a/bff/src/Duende.Bff/Shared/ClaimsLiteExtensions.cs
+++ b/bff/src/Duende.Bff/Shared/ClaimRecordExtensions.cs
@@ -1,19 +1,18 @@
// Copyright (c) Duende Software. All rights reserved.
// See LICENSE in the project root for license information.
-using System.Linq;
using System.Security.Claims;
namespace Duende.Bff;
-internal static class ClaimsLiteExtensions
+internal static class ClaimRecordExtensions
{
///
/// Converts a ClaimsPrincipalLite to ClaimsPrincipal
///
- public static ClaimsPrincipal ToClaimsPrincipal(this ClaimsPrincipalLite principal)
+ public static ClaimsPrincipal ToClaimsPrincipal(this ClaimsPrincipalRecord principal)
{
- var claims = principal.Claims.Select(x => new Claim(x.Type, x.Value, x.ValueType ?? ClaimValueTypes.String))
+ var claims = principal.Claims.Select(x => new Claim(x.Type, x.Value.ToString() ?? string.Empty, x.ValueType ?? ClaimValueTypes.String))
.ToArray();
var id = new ClaimsIdentity(claims, principal.AuthenticationType, principal.NameClaimType,
principal.RoleClaimType);
@@ -24,17 +23,17 @@ public static ClaimsPrincipal ToClaimsPrincipal(this ClaimsPrincipalLite princip
///
/// Converts a ClaimsPrincipal to ClaimsPrincipalLite
///
- public static ClaimsPrincipalLite ToClaimsPrincipalLite(this ClaimsPrincipal principal)
+ public static ClaimsPrincipalRecord ToClaimsPrincipalLite(this ClaimsPrincipal principal)
{
var claims = principal.Claims.Select(
- x => new ClaimLite
+ x => new ClaimRecord
{
Type = x.Type,
Value = x.Value,
ValueType = x.ValueType == ClaimValueTypes.String ? null : x.ValueType
}).ToArray();
- return new ClaimsPrincipalLite
+ return new ClaimsPrincipalRecord
{
AuthenticationType = principal.Identity!.AuthenticationType,
NameClaimType = principal.Identities.First().NameClaimType,
diff --git a/bff/src/Duende.Bff/Shared/ClaimsPrincipalLite.cs b/bff/src/Duende.Bff/Shared/ClaimsPrincipalRecord.cs
similarity index 86%
rename from bff/src/Duende.Bff/Shared/ClaimsPrincipalLite.cs
rename to bff/src/Duende.Bff/Shared/ClaimsPrincipalRecord.cs
index cfe2f9c2e..2d6a2b3aa 100644
--- a/bff/src/Duende.Bff/Shared/ClaimsPrincipalLite.cs
+++ b/bff/src/Duende.Bff/Shared/ClaimsPrincipalRecord.cs
@@ -6,7 +6,7 @@ namespace Duende.Bff;
///
/// Serialization friendly ClaimsPrincipal
///
-internal class ClaimsPrincipalLite
+internal class ClaimsPrincipalRecord
{
///
/// The authentication type
@@ -26,5 +26,5 @@ internal class ClaimsPrincipalLite
///
/// The claims
///
- public ClaimLite[] Claims { get; init; } = default!;
+ public ClaimRecord[] Claims { get; init; } = default!;
}
\ No newline at end of file
diff --git a/bff/test/Duende.Bff.Tests/Endpoints/DpopRemoteEndpointTests.cs b/bff/test/Duende.Bff.Tests/Endpoints/DpopRemoteEndpointTests.cs
index a4a184da5..b1d73d9dd 100644
--- a/bff/test/Duende.Bff.Tests/Endpoints/DpopRemoteEndpointTests.cs
+++ b/bff/test/Duende.Bff.Tests/Endpoints/DpopRemoteEndpointTests.cs
@@ -5,6 +5,7 @@
using System.Security.Cryptography;
using System.Text.Json;
using System.Threading.Tasks;
+using Duende.Bff.Tests.TestFramework;
using Duende.Bff.Tests.TestHosts;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
@@ -35,7 +36,7 @@ public DpopRemoteEndpointTests(ITestOutputHelper output) : base(output)
[Fact]
public async Task test_dpop()
{
- var apiResult = await BffHost.BrowserClient.CallBffHostApi(
+ ApiResponse apiResult = await BffHost.BrowserClient.CallBffHostApi(
url: BffHost.Url("/api_client/test")
);
diff --git a/bff/test/Duende.Bff.Tests/Endpoints/RemoteEndpointTests.cs b/bff/test/Duende.Bff.Tests/Endpoints/RemoteEndpointTests.cs
index adf7596f6..00cd4e956 100644
--- a/bff/test/Duende.Bff.Tests/Endpoints/RemoteEndpointTests.cs
+++ b/bff/test/Duende.Bff.Tests/Endpoints/RemoteEndpointTests.cs
@@ -3,14 +3,9 @@
using Duende.Bff.Tests.TestFramework;
using Duende.Bff.Tests.TestHosts;
-using System;
-using System.Linq;
using System.Net;
-using System.Net.Http;
using System.Net.Http.Json;
-using System.Threading.Tasks;
-using Shouldly;
-using Xunit;
+using System.Text.Json;
using Xunit.Abstractions;
namespace Duende.Bff.Tests.Endpoints
diff --git a/bff/test/Duende.Bff.Tests/TestFramework/Records.cs b/bff/test/Duende.Bff.Tests/TestFramework/Records.cs
index be74df303..80b7e4d14 100644
--- a/bff/test/Duende.Bff.Tests/TestFramework/Records.cs
+++ b/bff/test/Duende.Bff.Tests/TestFramework/Records.cs
@@ -14,13 +14,4 @@ public record JsonRecord(string Type, JsonElement Value)
[JsonPropertyName("value")]
public JsonElement Value { get; } = Value;
}
-
- public record ClaimRecord(string Type, string Value)
- {
- [JsonPropertyName("type")]
- public string Type { get; } = Type;
-
- [JsonPropertyName("value")]
- public string Value { get; } = Value;
- }
}