.net - Implement OAuth 2.0 based authentication on the Blazor Server Side - Stack Overflow

admin2025-04-17  2

I have a .NET 8.0 Blazor web app:

- BlazorApp.Client
- Blazor.Server
- BlazorApp.Shared

The app uses JWT-based auth between client and server. I need to use an external third-party API to fetch some data which needs OAuth 2.0-based authentication. The code to fetch this data is in the Blazor.Server app.

0Auth 2.0 authorization_code flow of third-party API:

  • Redirect the user to the external site using the generated auth login URL.
  • Get the authorization_code in return.
  • Send the authorization_code to another endpoint and exchange it for an access_token and refresh_token.

Then, add this access token to the Bearer <access_token> to every API call towards the third-party's endpoints in the Blazor.Server app. I am using an auth handler:

public class ThirdPartyApiAuthHandler : DelegatingHandler
{    
    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        try
        {
            var accessToken = @"// harcoded access token //";

            if (string.IsNullOrEmpty(accessToken))
            {
                throw new UnauthorizedAccessException("User not authenticated with eBay.");
            }

            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
    
            return await base.SendAsync(request, cancellationToken);
        }
        catch (Exception ex)
        {
            throw new InvalidOperationException($"Error in Authentication Handler while sending request to {request.RequestUri}", ex);
        }
    }
}

I am a bit confused about implementing the OAuth flow in the above handler. How can I redirect the user to the external API's authentication URL in the handler? Is it right to handle this in the auth handler?

I have a .NET 8.0 Blazor web app:

- BlazorApp.Client
- Blazor.Server
- BlazorApp.Shared

The app uses JWT-based auth between client and server. I need to use an external third-party API to fetch some data which needs OAuth 2.0-based authentication. The code to fetch this data is in the Blazor.Server app.

0Auth 2.0 authorization_code flow of third-party API:

  • Redirect the user to the external site using the generated auth login URL.
  • Get the authorization_code in return.
  • Send the authorization_code to another endpoint and exchange it for an access_token and refresh_token.

Then, add this access token to the Bearer <access_token> to every API call towards the third-party's endpoints in the Blazor.Server app. I am using an auth handler:

public class ThirdPartyApiAuthHandler : DelegatingHandler
{    
    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        try
        {
            var accessToken = @"// harcoded access token //";

            if (string.IsNullOrEmpty(accessToken))
            {
                throw new UnauthorizedAccessException("User not authenticated with eBay.");
            }

            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
    
            return await base.SendAsync(request, cancellationToken);
        }
        catch (Exception ex)
        {
            throw new InvalidOperationException($"Error in Authentication Handler while sending request to {request.RequestUri}", ex);
        }
    }
}

I am a bit confused about implementing the OAuth flow in the above handler. How can I redirect the user to the external API's authentication URL in the handler? Is it right to handle this in the auth handler?

Share Improve this question asked Feb 1 at 14:28 JunaidJunaid 1,0202 gold badges21 silver badges44 bronze badges 5
  • 1 You need to request the token outside the handler above, you typically want to use the AddOpenIDConnect authentication handler to get the token, see github.com/dotnet/blazor-samples/blob/main/8.0/… for inspiration and learn.microsoft.com/en-us/aspnet/core/blazor/security/… – Tore Nestenius Commented Feb 1 at 16:08
  • Thanks @ToreNestenius. It means I need to add a new OIDC-based project and make auth requests from the client app to it for all the requests. – Junaid Commented Feb 4 at 14:54
  • The AddOpenIDConnect is only involved during the initial authentication phase, after that, it uses the cookie to identitfy the user. – Tore Nestenius Commented Feb 4 at 15:16
  • @ToreNestenius I am following this guide: learn.microsoft.com/en-us/aspnet/core/blazor/security/…. I have created the CookieOidcServiceCollectionExtensions, CookieOidcRefresher, LoginLogoutEndpointRouteBuilderExtensions, and PersistingAuthenticationStateProvider classes in my MyBlazorApp.Server project. Also, added the AddOpenIdConnect DI call with the required config but I am unsure what to do next. How would the OAuth auth process be automated and only applied on the pages of my choice? – Junaid Commented Feb 18 at 17:21
  • The AddOpenIDConnect component is mainly involved when the user is challenged (using ChallengeAsync) or not authorized when it hits a page that requires authorization (ie. using the [authorization] attribute. – Tore Nestenius Commented Feb 18 at 18:03
Add a comment  | 

1 Answer 1

Reset to default 0

Using a package called Microsoft.Extensions.ServiceDiscovery.Yarp you can configure a “Catch All” route in the Blazor Server application and point it to the external API. It will act as a reverse proxy for the API and you can have it automatically attach additional headers to the requests without the client needing to see them. For me, it looked like this:

app.MapForwarder("/api/{**catch-all}", apiBaseUrl, builder =>
{
    builder.AddXForwardedFor();
    builder.AddRequestTransform(async ctx =>
    {
        var originalPath = ctx.HttpContext.Request.Path.Value;
        
        if (originalPath!.StartsWith("/api"))
        {
            var newPath = originalPath["/api/".Length..]; // Removes "/api"
            ctx.ProxyRequest.RequestUri = new Uri($"{apiBaseUrl}{newPath}");
        }
        
        var accessToken = await ctx.HttpContext.GetTokenAsync("access_token");
        if (!string.IsNullOrEmpty(accessToken))
            ctx.ProxyRequest.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
    });
});

This will add the X-Forwarded-For header to the request to ensure the API sees the end user’s real IP and attaches the Authorization header and access token to the request automatically if the user is logged in.

In this scenario, you handle the authentication only on the server.

Once configured you would have your client call the route on your server and let your server proxy it to the external API.

转载请注明原文地址:http://anycun.com/QandA/1744826318a88153.html