mirror of
https://github.com/DuendeSoftware/products
synced 2026-05-24 09:28:24 +00:00
Merge pull request #2259 from DuendeSoftware/pg/without-context
Avoid relying on an active Http Context
This commit is contained in:
commit
ba91078275
2 changed files with 96 additions and 5 deletions
|
|
@ -6,11 +6,13 @@ using Duende.Bff.Configuration;
|
|||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Duende.Bff.DynamicFrontends.Internal;
|
||||
|
||||
internal class BffAuthenticationSchemeProvider(
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
CurrentFrontendAccessor currentFrontendAccessor,
|
||||
IOptions<AuthenticationOptions> options,
|
||||
IOptions<BffOptions> bffOptions) : AuthenticationSchemeProvider(options)
|
||||
|
|
@ -19,9 +21,13 @@ internal class BffAuthenticationSchemeProvider(
|
|||
{
|
||||
var defaultSchemes = await base.GetRequestHandlerSchemesAsync();
|
||||
|
||||
if (!currentFrontendAccessor.TryGet(out _) && bffOptions.Value.ConfigureOpenIdConnectDefaults != null)
|
||||
if (httpContextAccessor.HttpContext != null
|
||||
&& !currentFrontendAccessor.TryGet(out _)
|
||||
&& bffOptions.Value.ConfigureOpenIdConnectDefaults != null)
|
||||
{
|
||||
defaultSchemes = defaultSchemes.Append(new BffAuthenticationScheme(BffAuthenticationSchemes.BffOpenIdConnect, "Default Duende Bff OpenIdConnect", typeof(OpenIdConnectHandler)));
|
||||
defaultSchemes = defaultSchemes.Append(new BffAuthenticationScheme(
|
||||
BffAuthenticationSchemes.BffOpenIdConnect, "Default Duende Bff OpenIdConnect",
|
||||
typeof(OpenIdConnectHandler)));
|
||||
}
|
||||
|
||||
return defaultSchemes;
|
||||
|
|
@ -36,16 +42,22 @@ internal class BffAuthenticationSchemeProvider(
|
|||
|
||||
private BffAuthenticationScheme? GetBffAuthenticationScheme(string name)
|
||||
{
|
||||
currentFrontendAccessor.TryGet(out var frontend);
|
||||
BffFrontend? frontend = null;
|
||||
if (httpContextAccessor.HttpContext != null)
|
||||
{
|
||||
currentFrontendAccessor.TryGet(out frontend);
|
||||
}
|
||||
|
||||
if (name == frontend?.CookieSchemeName || name == BffAuthenticationSchemes.BffCookie)
|
||||
{
|
||||
return new BffAuthenticationScheme(frontend?.CookieSchemeName ?? BffAuthenticationSchemes.BffCookie, "Duende Bff Cookie", typeof(CookieAuthenticationHandler));
|
||||
return new BffAuthenticationScheme(frontend?.CookieSchemeName ?? BffAuthenticationSchemes.BffCookie,
|
||||
"Duende Bff Cookie", typeof(CookieAuthenticationHandler));
|
||||
}
|
||||
|
||||
if (name == frontend?.OidcSchemeName || name == BffAuthenticationSchemes.BffOpenIdConnect)
|
||||
{
|
||||
return new BffAuthenticationScheme(frontend?.OidcSchemeName ?? BffAuthenticationSchemes.BffOpenIdConnect, "Duende Bff OpenIdConnect", typeof(OpenIdConnectHandler));
|
||||
return new BffAuthenticationScheme(frontend?.OidcSchemeName ?? BffAuthenticationSchemes.BffOpenIdConnect,
|
||||
"Duende Bff OpenIdConnect", typeof(OpenIdConnectHandler));
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
|||
79
bff/test/Bff.Tests/BffScenarioTests.cs
Normal file
79
bff/test/Bff.Tests/BffScenarioTests.cs
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
// Copyright (c) Duende Software. All rights reserved.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
using Duende.AccessTokenManagement;
|
||||
using Duende.Bff.Tests.TestInfra;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Duende.Bff.Tests;
|
||||
|
||||
public class BffScenarioTests(ITestOutputHelper output) : BffTestBase(output)
|
||||
{
|
||||
[Fact]
|
||||
public async Task When_using_bff_as_host_and_client_credentials_token_manager_with_no_http_context_still_works()
|
||||
{
|
||||
var workerClientId = "worker.client.id";
|
||||
IdentityServer.AddClient(workerClientId, Bff.Url());
|
||||
var contentReceived = new TaskCompletionSource<string>();
|
||||
var workerStarted = new TaskCompletionSource();
|
||||
|
||||
Bff.OnConfigureServices += services =>
|
||||
{
|
||||
services.AddClientCredentialsTokenManagement()
|
||||
.AddClient(ClientCredentialsClientName.Parse("worker.client"), client =>
|
||||
{
|
||||
client.TokenEndpoint = new Uri(IdentityServer.Url(), "/connect/token");
|
||||
client.ClientId = ClientId.Parse(workerClientId);
|
||||
client.ClientSecret = ClientSecret.Parse(The.ClientSecret);
|
||||
client.Scope = Scope.Parse(The.Scope);
|
||||
client.HttpClient = new HttpClient(Internet, disposeHandler: false);
|
||||
});
|
||||
|
||||
services.AddClientCredentialsHttpClient("worker",
|
||||
ClientCredentialsClientName.Parse("worker.client"),
|
||||
client => { client.BaseAddress = Api.Url(); })
|
||||
.ConfigurePrimaryHttpMessageHandler(() => Internet);
|
||||
|
||||
services.AddSingleton(contentReceived);
|
||||
services.AddSingleton(workerStarted);
|
||||
services.AddHostedService<BackgroundWorker>();
|
||||
};
|
||||
await InitializeAsync();
|
||||
workerStarted.SetResult();
|
||||
var content = await contentReceived.Task.WaitAsync(TimeSpan.FromSeconds(5));
|
||||
content.ShouldNotBeNullOrEmpty();
|
||||
}
|
||||
|
||||
internal class BackgroundWorker(
|
||||
IHttpClientFactory httpClientFactory,
|
||||
TaskCompletionSource<string> contentReceived,
|
||||
TaskCompletionSource workerIsAllowedToStart) : BackgroundService
|
||||
{
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
await workerIsAllowedToStart.Task;
|
||||
|
||||
var client = httpClientFactory.CreateClient("worker");
|
||||
|
||||
try
|
||||
{
|
||||
var response = await client.GetAsync("/", stoppingToken);
|
||||
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
var content = await response.Content.ReadAsStringAsync(stoppingToken);
|
||||
contentReceived.TrySetResult(content);
|
||||
}
|
||||
else
|
||||
{
|
||||
contentReceived.TrySetException(
|
||||
new Exception($"Request failed with status code: {response.StatusCode}"));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
contentReceived.TrySetException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue