diff --git a/src/Duende.Bff.Yarp/AccessTokenRequestTransform.cs b/src/Duende.Bff.Yarp/AccessTokenRequestTransform.cs index 4244c6b9..5bb346c5 100644 --- a/src/Duende.Bff.Yarp/AccessTokenRequestTransform.cs +++ b/src/Duende.Bff.Yarp/AccessTokenRequestTransform.cs @@ -98,7 +98,8 @@ private async Task ApplyDPoPToken(RequestTransformContext context, DPoPTokenResu context.ProxyRequest.Headers.Add(OidcConstants.HttpHeaders.DPoP, proofToken.ProofToken); context.ProxyRequest.Headers.Authorization = new AuthenticationHeaderValue(OidcConstants.AuthenticationSchemes.AuthorizationHeaderDPoP, token.AccessToken); - } else + } + else { // The proof service can opt out of DPoP by returning null. If so, // we just use the access token as a bearer token. diff --git a/src/Duende.Bff.Yarp/AccessTokenTransformProvider.cs b/src/Duende.Bff.Yarp/AccessTokenTransformProvider.cs index bb5b57b9..71ad64eb 100644 --- a/src/Duende.Bff.Yarp/AccessTokenTransformProvider.cs +++ b/src/Duende.Bff.Yarp/AccessTokenTransformProvider.cs @@ -4,12 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Net.Http.Headers; -using System.Threading.Tasks; using Duende.AccessTokenManagement; -using Duende.Bff.Logging; -using Duende.Bff.Yarp.Logging; -using IdentityModel; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Yarp.ReverseProxy.Transforms; diff --git a/src/Duende.Bff.Yarp/IHttpTransformerFactory.cs b/src/Duende.Bff.Yarp/IHttpTransformerFactory.cs index cdfdd71a..13335edc 100644 --- a/src/Duende.Bff.Yarp/IHttpTransformerFactory.cs +++ b/src/Duende.Bff.Yarp/IHttpTransformerFactory.cs @@ -1,7 +1,6 @@ // Copyright (c) Duende Software. All rights reserved. // See LICENSE in the project root for license information. -using Duende.AccessTokenManagement; using Yarp.ReverseProxy.Forwarder; namespace Duende.Bff.Yarp; diff --git a/test/Duende.Bff.Tests/Endpoints/RemoteEndpointTests.cs b/test/Duende.Bff.Tests/Endpoints/RemoteEndpointTests.cs index a95cb3fe..92bff8dc 100644 --- a/test/Duende.Bff.Tests/Endpoints/RemoteEndpointTests.cs +++ b/test/Duende.Bff.Tests/Endpoints/RemoteEndpointTests.cs @@ -4,10 +4,13 @@ using Duende.Bff.Tests.TestFramework; using Duende.Bff.Tests.TestHosts; using FluentAssertions; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.IdentityModel.Tokens; using System; using System.Linq; using System.Net; using System.Net.Http; +using System.Security.Cryptography; using System.Text; using System.Text.Json; using System.Threading.Tasks; @@ -374,5 +377,34 @@ public async Task calls_to_bff_not_in_endpoint_routing_should_fail() Func f = () => BffHost.BrowserClient.SendAsync(req); await f.Should().ThrowAsync(); } + + [Fact] + public async Task test_dpop() + { + var rsaKey = new RsaSecurityKey(RSA.Create(2048)); + var jsonWebKey = JsonWebKeyConverter.ConvertFromRSASecurityKey(rsaKey); + jsonWebKey.Alg = "PS256"; + var jwk = JsonSerializer.Serialize(jsonWebKey); + + BffHost.OnConfigureServices += svcs => + { + svcs.PostConfigure(opts => + { + opts.DPoPJsonWebKey = jwk; + }); + }; + BffHost.InitializeAsync().Wait(); + + var req = new HttpRequestMessage(HttpMethod.Get, BffHost.Url("/api_client/test")); + req.Headers.Add("x-csrf", "1"); + var response = await BffHost.BrowserClient.SendAsync(req); + + response.IsSuccessStatusCode.Should().BeTrue(); + response.Content.Headers.ContentType.MediaType.Should().Be("application/json"); + var json = await response.Content.ReadAsStringAsync(); + var apiResult = JsonSerializer.Deserialize(json); + apiResult.RequestHeaders["DPoP"].First().Should().NotBeNullOrEmpty(); + apiResult.RequestHeaders["Authorization"].First().StartsWith("DPoP ").Should().BeTrue(); + } } }