You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Core WebAPI验证Google JWT Token持续返回401问题排查

Hey there! Let's troubleshoot that stubborn 401 error you're facing when validating Google JWT Bearer Tokens in your .NET Core WebAPI. Since you've confirmed the token is valid via jwt.io, the issue is almost certainly in how your code is set up to validate it. Let's break down the key areas to check:

1. Startup.cs Authentication Configuration Gaps

First, double-check that your authentication setup is correctly wired to Google's JWT endpoints. Common missteps here include:

  • Forgetting to set the correct Authority and Audience (your Google OAuth Client ID)
  • Misordering middleware (authentication must run before authorization)
  • Failing to register the custom validator properly

Here's a corrected example of what this should look like:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();

    // Pull your Google Client ID from config (never hardcode!)
    var googleClientId = Configuration["Authentication:Google:ClientId"];

    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.Authority = "https://accounts.google.com";
            options.Audience = googleClientId;
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidIssuer = "https://accounts.google.com",
                ValidateAudience = true,
                ValidAudience = googleClientId,
                ValidateLifetime = true,
                // Hook up your custom validator if you're using one
                TokenValidator = new GoogleTokenValidator()
            };
        });

    services.AddAuthorization();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // ... other middleware like exception handling, static files ...

    // Critical order: Authentication MUST come before Authorization
    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

2. Custom GoogleTokenValidator Issues

If you're using a custom validator, make sure it's not accidentally rejecting valid tokens. Common pitfalls:

  • Not properly validating Google's required claims (like iss and aud)
  • Swallowing exceptions that would tell you why validation failed
  • Not implementing the ISecurityTokenValidator interface correctly

Here's a robust implementation of the validator that adds Google-specific checks:

public class GoogleTokenValidator : ISecurityTokenValidator
{
    private readonly JwtSecurityTokenHandler _tokenHandler = new();

    public bool CanValidateToken => true;
    public int MaximumTokenSizeInBytes { get; set; } = TokenValidationParameters.DefaultMaximumTokenSizeInBytes;

    public bool CanReadToken(string securityToken)
        => _tokenHandler.CanReadToken(securityToken);

    public ClaimsPrincipal ValidateToken(string securityToken, TokenValidationParameters validationParameters, out SecurityToken validatedToken)
    {
        // Let the base handler do initial validation
        var principal = _tokenHandler.ValidateToken(securityToken, validationParameters, out validatedToken);

        // Add Google-specific checks
        var issuerClaim = principal.FindFirst(ClaimTypes.Issuer);
        if (issuerClaim == null || !issuerClaim.Value.Equals("https://accounts.google.com", StringComparison.OrdinalIgnoreCase))
        {
            throw new SecurityTokenInvalidIssuerException("Token is not issued by Google");
        }

        var audienceClaim = principal.FindFirst(JwtRegisteredClaimNames.Aud);
        if (audienceClaim == null || !audienceClaim.Value.Equals(validationParameters.ValidAudience, StringComparison.OrdinalIgnoreCase))
        {
            throw new SecurityTokenInvalidAudienceException("Token audience does not match API client ID");
        }

        return principal;
    }
}

3. Xamarin Forms HttpClient Call Mistakes

Don't overlook the client-side! Even a tiny mistake here can cause a 401:

  • Using the wrong token: Make sure you're passing a Google ID Token, not an Access Token. Access Tokens are for calling Google APIs, ID Tokens are for authentication.
  • Malformed Authorization header: Ensure you're using the format Bearer {token} (note the space between "Bearer" and the token).
  • Missing scopes: When requesting the token from Google, make sure you include the openid scope (required for ID Tokens).

Here's a corrected client-side call example:

private async Task CallProtectedApi()
{
    var httpClient = new HttpClient();
    // Get the ID Token from your Google Auth flow (not Access Token!)
    var googleIdToken = await _googleAuthService.GetIdTokenAsync();

    // Set the Authorization header correctly
    httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", googleIdToken);

    try
    {
        var response = await httpClient.GetAsync("https://your-api-domain/api/protected-endpoint");
        response.EnsureSuccessStatusCode();
        // Handle successful response
    }
    catch (HttpRequestException ex)
    {
        // Log or handle the error
    }
}

Bonus Troubleshooting Tips

  • Enable debug logging: Add this to your appsettings.json to see detailed validation errors:
    {
      "Logging": {
        "LogLevel": {
          "Microsoft.AspNetCore.Authentication.JwtBearer": "Debug"
        }
      }
    }
    
  • Verify token claims: Double-check the aud (audience) claim in your token via jwt.io matches exactly the Client ID you're using in your WebAPI.
  • Check Google Cloud Console: Ensure your WebAPI's Client ID is correctly configured, and your Xamarin app's OAuth Client ID is allowed to request tokens for this audience.

内容的提问来源于stack exchange,提问作者Napoleon Ike Jones

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:04:53