Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HTTP 401 Unauthorized on bff/user call #1073

Closed
ngruson opened this issue Jan 20, 2024 · 3 comments
Closed

HTTP 401 Unauthorized on bff/user call #1073

ngruson opened this issue Jan 20, 2024 · 3 comments
Assignees
Labels

Comments

@ngruson
Copy link

ngruson commented Jan 20, 2024

Which version of Duende BFF are you using?

Duende.BFF 2.2.0

Which version of .NET are you using?

.NET 8

Describe the bug

I'm trying to use Duende BFF in a .NET 8 Blazor server app (not WASM).
I found your article https://docs.duendesoftware.com/identityserver/v6/quickstarts/7_blazor/ which I followed as much as possible.

I get stuck when implementing BffAuthenticationStateProvider.
The login part with Identity Server works, but the call to bff/user results in an HTTP 401 Unauthorized error.

In BffAuthenticationStateProvider, I use a IHttpClientFactory to grab the correct HttpClient instance on init.
Then I do the call with this client to the bff/user endpoint.

this.logger.LogInformation("Fetching user information.");
var response = await this.client.GetAsync($"{this.navigationManager.BaseUri}bff/user?slide=false");

I configured the HttpClient as follows:

builder.Services.AddTransient<AntiForgeryHandler>();

builder.Services.AddHttpClient("bff")
    .AddHttpMessageHandler<AntiForgeryHandler>()
    .AddUserAccessTokenHandler();

I try to add the access token to the client using your AddUserAccessTokenHandler extension method from Duende.AccessTokenManagement.OpenIdConnect package.

The access token is set correctly in the HttpContext, but still I get this Unauthorized error.

What could be wrong here?

Log output/exception with stacktrace

MyBlazorApp.Components.Account.BffAuthenticationStateProvider: Information: Fetching user information.
System.Net.Http.HttpClient.bff.LogicalHandler: Information: Start processing HTTP request GET https://localhost:7278/bff/user?slide=false
System.Net.Http.HttpClient.bff.ClientHandler: Information: Sending HTTP request GET https://localhost:7278/bff/user?slide=false
Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request starting HTTP/1.1 GET https://localhost:7278/bff/user?slide=false - - -
Microsoft.AspNetCore.Routing.EndpointMiddleware: Information: Executing endpoint 'HTTP: GET /bff/user'
Microsoft.AspNetCore.Routing.EndpointMiddleware: Information: Executed endpoint 'HTTP: GET /bff/user'
Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request finished HTTP/1.1 GET https://localhost:7278/bff/user?slide=false - 401 0 - 26.3108ms
System.Net.Http.HttpClient.bff.ClientHandler: Information: Received HTTP response headers after 29.0754ms - 401
System.Net.Http.HttpClient.bff.ClientHandler: Information: Sending HTTP request GET https://localhost:7278/bff/user?slide=false
Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request starting HTTP/1.1 GET https://localhost:7278/bff/user?slide=false - - -
Microsoft.AspNetCore.Routing.EndpointMiddleware: Information: Executing endpoint 'HTTP: GET /bff/user'
Microsoft.AspNetCore.Routing.EndpointMiddleware: Information: Executed endpoint 'HTTP: GET /bff/user'
Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request finished HTTP/1.1 GET https://localhost:7278/bff/user?slide=false - 401 0 - 8.1220ms
System.Net.Http.HttpClient.bff.ClientHandler: Information: Received HTTP response headers after 10.9971ms - 401
Polly: Information: Execution attempt. Source: '-standard//Standard-Retry', Operation Key: '', Result: '401', Handled: 'False', Attempt: '0', Execution Time: '61,3648'
System.Net.Http.HttpClient.bff.LogicalHandler: Information: End processing HTTP request after 66.3396ms - 401
@ngruson ngruson added the BFF label Jan 20, 2024
@ngruson
Copy link
Author

ngruson commented Jan 26, 2024

I've looked a bit more.
The DefaultUserService of BFF logs the following:
Duende.Bff.ManagementEndpoints: Debug: User endpoint indicates the user is not logged in, using status code 401.
So apparently, the context.AuthenticateAsync call didn't properly authenticate.

But when I add the same to my BffAuthenticationStateProvider, the authenticate call succeeds.

private async Task<ClaimsPrincipal> FetchUser()
{
    try
    {
        var context = this.httpContextAccessor.HttpContext;
        var result = await context!.AuthenticateAsync();
        this.logger.LogInformation("Authentication success: {result}", result.Succeeded);

        this.logger.LogInformation("Fetching user information.");
        this.client.BaseAddress = new Uri(this.navigationManager.BaseUri);

        // Returns HTTP 401 Unauthorized
        var response = await this.client.GetAsync("bff/user?slide=false");

        if (response.StatusCode == HttpStatusCode.OK)
        {
            var claims = await response.Content.ReadFromJsonAsync<List<ClaimRecord>>();

            var identity = new ClaimsIdentity(
                nameof(BffAuthenticationStateProvider),
                "name",
                "role");

            foreach (var claim in claims!)
            {
                identity.AddClaim(new Claim(claim.Type, claim.Value.ToString()!));
            }

            return new ClaimsPrincipal(identity);
        }
    }
    catch (Exception ex)
    {
        this.logger.LogWarning(ex, "Fetching user failed.");
    }

    return new ClaimsPrincipal(new ClaimsIdentity());
}

My application logs:

MyApp.Components.Account.BffAuthenticationStateProvider: Information: Authentication success: True
MyApp.Components.Account.BffAuthenticationStateProvider: Information: Fetching user information.
System.Net.Http.HttpClient.bff.LogicalHandler: Information: Start processing HTTP request GET https://localhost:7278/bff/user?slide=false
Polly: Debug: Resilience pipeline executing. Source: '-standard/', Operation Key: '(null)'
System.Net.Http.HttpClient.bff.ClientHandler: Information: Sending HTTP request GET https://localhost:7278/bff/user?slide=false
Duende.Bff.ManagementEndpoints: Debug: Processing user request
Duende.Bff.ManagementEndpoints: Debug: User endpoint indicates the user is not logged in, using status code 401
System.Net.Http.HttpClient.bff.ClientHandler: Information: Received HTTP response headers after 11.1584ms - 401

@josephdecock
Copy link
Member

Hi @ngruson, sorry for the delay getting back to you! We are actively working on an update to the BFF and new samples to show how to solve auth issues in blazor with .NET 8. For more details on my thoughts about the problems we're working on, see this comment, and this open issue in our samples repo. In the interest of keeping things organized, I'm closing this along with some other related issues, but feel free to provide feedback and comments in (DuendeSoftware/Samples#142)

@ngruson
Copy link
Author

ngruson commented Feb 9, 2024

I've got things working now by looking at the samples. I'm using a server-side token store to read/write the access token.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants