diff --git a/Directory.Packages.props b/Directory.Packages.props
index d911c69d3..d5c161ffd 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -40,7 +40,7 @@ that supports the target frameworks our products target (8, 9, 10) -->
-
+
@@ -136,4 +136,4 @@ that supports the target frameworks our products target (8, 9, 10) -->
-
+
\ No newline at end of file
diff --git a/bff/bff.slnf b/bff/bff.slnf
index 1b9761854..dda74c9af 100644
--- a/bff/bff.slnf
+++ b/bff/bff.slnf
@@ -2,8 +2,6 @@
"solution": {
"path": "..\\products.slnx",
"projects": [
- "bff\\performance\\Bff.Benchmarks\\Bff.Benchmarks.csproj",
- "bff\\performance\\Bff.Performance\\Bff.Performance.csproj",
".github\\workflow-gen\\workflow-gen.csproj",
"bff\\hosts\\Blazor\\PerComponent\\Hosts.Bff.Blazor.PerComponent.Client\\Hosts.Bff.Blazor.PerComponent.Client.csproj",
"bff\\hosts\\Blazor\\PerComponent\\Hosts.Bff.Blazor.PerComponent\\Hosts.Bff.Blazor.PerComponent.csproj",
@@ -13,8 +11,8 @@
"bff\\hosts\\Hosts.Bff.DPoP\\Hosts.Bff.DPoP.csproj",
"bff\\hosts\\Hosts.Bff.EF\\Hosts.Bff.EF.csproj",
"bff\\hosts\\Hosts.Bff.InMemory\\Hosts.Bff.InMemory.csproj",
- "bff\\hosts\\Hosts.Bff.Performance\\Hosts.Bff.Performance.csproj",
"bff\\hosts\\Hosts.Bff.MultiFrontend\\Hosts.Bff.MultiFrontend.csproj",
+ "bff\\hosts\\Hosts.Bff.Performance\\Hosts.Bff.Performance.csproj",
"bff\\hosts\\Hosts.IdentityServer\\Hosts.IdentityServer.csproj",
"bff\\hosts\\Hosts.ServiceDefaults\\Hosts.ServiceDefaults.csproj",
"bff\\hosts\\RemoteApis\\Hosts.RemoteApi.DPoP\\Hosts.RemoteApi.DPoP.csproj",
@@ -22,6 +20,7 @@
"bff\\hosts\\RemoteApis\\Hosts.RemoteApi\\Hosts.RemoteApi.csproj",
"bff\\migrations\\UserSessionDb\\UserSessionDb.csproj",
"bff\\performance\\Bff.Benchmarks\\Bff.Benchmarks.csproj",
+ "bff\\performance\\Bff.Performance\\Bff.Performance.csproj",
"bff\\src\\Bff.Blazor.Client\\Bff.Blazor.Client.csproj",
"bff\\src\\Bff.Blazor\\Bff.Blazor.csproj",
"bff\\src\\Bff.EntityFramework\\Bff.EntityFramework.csproj",
@@ -33,8 +32,8 @@
"bff\\templates\\src\\BffRemoteApi\\BffRemoteApi.csproj",
"bff\\test\\Bff.Tests\\Bff.Tests.csproj",
"bff\\test\\Hosts.Tests\\Hosts.Tests.csproj",
- "shared\\Xunit.Playwright\\Duende.Xunit.Playwright.csproj",
- "shared\\ShouldlyExtensions\\ShouldlyExtensions.csproj"
+ "shared\\ShouldlyExtensions\\ShouldlyExtensions.csproj",
+ "shared\\Xunit.Playwright\\Duende.Xunit.Playwright.csproj"
]
}
-}
+}
\ No newline at end of file
diff --git a/bff/src/Bff/HttpContextExtensions.cs b/bff/src/Bff/HttpContextExtensions.cs
index 7be3a4da8..f2254abac 100644
--- a/bff/src/Bff/HttpContextExtensions.cs
+++ b/bff/src/Bff/HttpContextExtensions.cs
@@ -95,7 +95,7 @@ internal static class HttpContextExtensions
return new DPoPTokenResult()
{
- AccessToken = AccessToken.Parse(userToken.ToString()),
+ AccessToken = AccessToken.Parse(userToken.AccessToken.ToString()),
DPoPJsonWebKey = DPoPProofKey.Parse(userToken.DPoPJsonWebKey!.ToString()!)
};
}
@@ -156,7 +156,7 @@ internal static class HttpContextExtensions
return new DPoPTokenResult()
{
- AccessToken = AccessToken.Parse(clientToken.ToString()),
+ AccessToken = AccessToken.Parse(clientToken.AccessToken.ToString()),
DPoPJsonWebKey = DPoPProofKey.Parse(clientToken.DPoPJsonWebKey!.ToString()!)
};
diff --git a/bff/test/Bff.Tests/Bff.Tests.csproj b/bff/test/Bff.Tests/Bff.Tests.csproj
index c3374d6b3..a88f859af 100644
--- a/bff/test/Bff.Tests/Bff.Tests.csproj
+++ b/bff/test/Bff.Tests/Bff.Tests.csproj
@@ -7,6 +7,7 @@
+
diff --git a/bff/test/Bff.Tests/Endpoints/DpopRemoteEndpointTests.cs b/bff/test/Bff.Tests/Endpoints/DPoPRemoteEndpointTests.cs
similarity index 51%
rename from bff/test/Bff.Tests/Endpoints/DpopRemoteEndpointTests.cs
rename to bff/test/Bff.Tests/Endpoints/DPoPRemoteEndpointTests.cs
index bb51785d2..58d8f4fcb 100644
--- a/bff/test/Bff.Tests/Endpoints/DpopRemoteEndpointTests.cs
+++ b/bff/test/Bff.Tests/Endpoints/DPoPRemoteEndpointTests.cs
@@ -1,6 +1,7 @@
// Copyright (c) Duende Software. All rights reserved.
// See LICENSE in the project root for license information.
+using Duende.AspNetCore.Authentication.JwtBearer.DPoP;
using Duende.Bff.AccessTokenManagement;
using Duende.Bff.Tests.TestFramework;
using Duende.Bff.Tests.TestInfra;
@@ -9,7 +10,7 @@ using Xunit.Abstractions;
namespace Duende.Bff.Tests.Endpoints;
-public class DpopRemoteEndpointTests(ITestOutputHelper output) : BffTestBase(output), IAsyncLifetime
+public class DPoPRemoteEndpointTests(ITestOutputHelper output) : BffTestBase(output)
{
public override async Task InitializeAsync()
{
@@ -18,11 +19,7 @@ public class DpopRemoteEndpointTests(ITestOutputHelper output) : BffTestBase(out
idSrvClient.RequireDPoP = true;
Bff.OnConfigureBff += bff => bff.AddRemoteApis();
- Bff.OnConfigureApp += app =>
- {
- app.MapRemoteBffApiEndpoint(The.Path, Api.Url())
- .WithAccessToken(RequiredTokenType.Client);
- };
+
await base.InitializeAsync();
Bff.BffOptions.DPoPJsonWebKey = The.DPoPJsonWebKey;
@@ -34,17 +31,55 @@ public class DpopRemoteEndpointTests(ITestOutputHelper output) : BffTestBase(out
}
[Fact]
- public async Task Can_login_with_dpop_enabled() => await Bff.BrowserClient.Login()
- .CheckHttpStatusCode();
-
- [Fact]
- public async Task When_calling_api_endpoint_with_dpop_enabled_then_dpop_headers_are_sent()
+ public async Task Can_call_dpop_protected_api_with_user_token()
{
+ Api.OnConfigureServices += services =>
+ {
+ services.ConfigureDPoPTokensForScheme("token");
+ };
+
+ Bff.OnConfigureApp += app =>
+ {
+ app.MapRemoteBffApiEndpoint(The.Path, Api.Url())
+ .WithAccessToken(RequiredTokenType.User);
+ };
+
+ await InitializeAsync();
+
+ await Bff.BrowserClient.Login()
+ .CheckHttpStatusCode();
+
ApiCallDetails callToApi = await Bff.BrowserClient.CallBffHostApi(
url: Bff.Url(The.PathAndSubPath)
);
callToApi.RequestHeaders["DPoP"].First().ShouldNotBeNullOrEmpty();
callToApi.RequestHeaders["Authorization"].First().StartsWith("DPoP ").ShouldBeTrue();
+ callToApi.Sub.ShouldNotBeNullOrEmpty();
+ }
+
+ [Fact]
+ public async Task Can_call_dpop_protected_api_with_client_token()
+ {
+ Api.OnConfigureServices += services =>
+ {
+ services.ConfigureDPoPTokensForScheme("token");
+ };
+
+ Bff.OnConfigureApp += app =>
+ {
+ app.MapRemoteBffApiEndpoint(The.Path, Api.Url())
+ .WithAccessToken(RequiredTokenType.Client);
+ };
+
+ await InitializeAsync();
+
+ ApiCallDetails callToApi = await Bff.BrowserClient.CallBffHostApi(
+ url: Bff.Url(The.PathAndSubPath)
+ );
+
+ callToApi.RequestHeaders["DPoP"].First().ShouldNotBeNullOrEmpty();
+ callToApi.RequestHeaders["Authorization"].First().StartsWith("DPoP ").ShouldBeTrue();
+ callToApi.ClientId.ShouldNotBeNullOrEmpty();
}
}