Skip to content
This repository was archived by the owner on Jan 24, 2025. It is now read-only.

Update to YARP 2.0 #161

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
<PropertyGroup Condition=" '$(TargetFramework)' == 'net6.0'">
<FrameworkVersionRuntime>6.0.0</FrameworkVersionRuntime>
<FrameworkVersionTesting>6.0.11</FrameworkVersionTesting>
<YarpVersion>1.1.0</YarpVersion>
<YarpVersion>2.0.0</YarpVersion>
</PropertyGroup>

<PropertyGroup Condition=" '$(TargetFramework)' == 'net7.0'">
<FrameworkVersionRuntime>7.0.0</FrameworkVersionRuntime>
<FrameworkVersionTesting>7.0.0</FrameworkVersionTesting>
<YarpVersion>1.1.0</YarpVersion>
<YarpVersion>2.0.0</YarpVersion>
</PropertyGroup>

<ItemGroup>
Expand Down
3 changes: 3 additions & 0 deletions src/Duende.Bff.Yarp/AccessTokenTransformProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ public void Apply(TransformBuilderContext transformBuildContext)
}
else
{
// short circuit forwarder and return 401
transformContext.HttpContext.Response.StatusCode = 401;

_logger.AccessTokenMissing(transformBuildContext?.Route?.RouteId ?? "unknown route", tokenType);
}
});
Expand Down
99 changes: 0 additions & 99 deletions src/Duende.Bff.Yarp/InMemoryConfigProvider.cs

This file was deleted.

193 changes: 193 additions & 0 deletions test/Duende.Bff.Tests/Endpoints/YarpRemoteEndpointTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
// Copyright (c) Duende Software. All rights reserved.
// See LICENSE in the project root for license information.

using Duende.Bff.Tests.TestHosts;
using FluentAssertions;
using System.Net;
using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;
using Duende.Bff.Tests.TestFramework;
using Xunit;

namespace Duende.Bff.Tests.Endpoints
{
public class YarpRemoteEndpointTests : YarpBffIntegrationTestBase
{
[Fact]
public async Task anonymous_call_with_no_csrf_header_to_no_token_requirement_no_csrf_route_should_succeed()
{
var req = new HttpRequestMessage(HttpMethod.Get, BffHost.Url("/api_anon_no_csrf/test"));
var response = await BffHost.BrowserClient.SendAsync(req);

response.StatusCode.Should().Be(HttpStatusCode.OK);
}

[Fact]
public async Task anonymous_call_with_no_csrf_header_to_csrf_route_should_fail()
{
var req = new HttpRequestMessage(HttpMethod.Get, BffHost.Url("/api_anon/test"));
var response = await BffHost.BrowserClient.SendAsync(req);

response.StatusCode.Should().Be(HttpStatusCode.Unauthorized);
}

[Fact]
public async Task anonymous_call_to_no_token_requirement_route_should_succeed()
{
var req = new HttpRequestMessage(HttpMethod.Get, BffHost.Url("/api_anon/test"));
req.Headers.Add("x-csrf", "1");
var response = await BffHost.BrowserClient.SendAsync(req);

response.StatusCode.Should().Be(HttpStatusCode.OK);
}

[Fact]
public async Task anonymous_call_to_user_token_requirement_route_should_fail()
{
var req = new HttpRequestMessage(HttpMethod.Get, BffHost.Url("/api_user/test"));
req.Headers.Add("x-csrf", "1");
var response = await BffHost.BrowserClient.SendAsync(req);

response.StatusCode.Should().Be(HttpStatusCode.Unauthorized);
}

[Fact]
public async Task authenticated_GET_should_forward_user_to_api()
{
await BffHost.BffLoginAsync("alice");

var req = new HttpRequestMessage(HttpMethod.Get, BffHost.Url("/api_user/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<ApiResponse>(json);
apiResult.Method.Should().Be("GET");
apiResult.Path.Should().Be("/api_user/test");
apiResult.Sub.Should().Be("alice");
apiResult.ClientId.Should().Be("spa");
}

[Fact]
public async Task authenticated_PUT_should_forward_user_to_api()
{
await BffHost.BffLoginAsync("alice");

var req = new HttpRequestMessage(HttpMethod.Put, BffHost.Url("/api_user/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<ApiResponse>(json);
apiResult.Method.Should().Be("PUT");
apiResult.Path.Should().Be("/api_user/test");
apiResult.Sub.Should().Be("alice");
apiResult.ClientId.Should().Be("spa");
}

[Fact]
public async Task authenticated_POST_should_forward_user_to_api()
{
await BffHost.BffLoginAsync("alice");

var req = new HttpRequestMessage(HttpMethod.Post, BffHost.Url("/api_user/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<ApiResponse>(json);
apiResult.Method.Should().Be("POST");
apiResult.Path.Should().Be("/api_user/test");
apiResult.Sub.Should().Be("alice");
apiResult.ClientId.Should().Be("spa");
}

[Fact]
public async Task call_to_client_token_route_should_forward_client_token_to_api()
{
await BffHost.BffLoginAsync("alice");

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<ApiResponse>(json);
apiResult.Method.Should().Be("GET");
apiResult.Path.Should().Be("/api_client/test");
apiResult.Sub.Should().BeNull();
apiResult.ClientId.Should().Be("spa");
}

[Fact]
public async Task call_to_user_or_client_token_route_should_forward_user_or_client_token_to_api()
{
{
var req = new HttpRequestMessage(HttpMethod.Get, BffHost.Url("/api_user_or_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<ApiResponse>(json);
apiResult.Method.Should().Be("GET");
apiResult.Path.Should().Be("/api_user_or_client/test");
apiResult.Sub.Should().BeNull();
apiResult.ClientId.Should().Be("spa");
}

{
await BffHost.BffLoginAsync("alice");

var req = new HttpRequestMessage(HttpMethod.Get, BffHost.Url("/api_user_or_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<ApiResponse>(json);
apiResult.Method.Should().Be("GET");
apiResult.Path.Should().Be("/api_user_or_client/test");
apiResult.Sub.Should().Be("alice");
apiResult.ClientId.Should().Be("spa");
}
}

[Fact]
public async Task response_status_401_from_remote_endpoint_should_return_401_from_bff()
{
await BffHost.BffLoginAsync("alice");
ApiHost.ApiStatusCodeToReturn = 401;

var req = new HttpRequestMessage(HttpMethod.Get, BffHost.Url("/api_user/test"));
req.Headers.Add("x-csrf", "1");
var response = await BffHost.BrowserClient.SendAsync(req);

response.StatusCode.Should().Be(HttpStatusCode.Unauthorized);
}

[Fact]
public async Task response_status_403_from_remote_endpoint_should_return_403_from_bff()
{
await BffHost.BffLoginAsync("alice");
ApiHost.ApiStatusCodeToReturn = 403;

var req = new HttpRequestMessage(HttpMethod.Get, BffHost.Url("/api_user/test"));
req.Headers.Add("x-csrf", "1");
var response = await BffHost.BrowserClient.SendAsync(req);

response.StatusCode.Should().Be(HttpStatusCode.Forbidden);
}
}
}
Loading