ASP.NET Core 3.0 身份服务器 4 (4.0.0) SecurityTokenInvalidAudienceException:IDX10214:受众验证失败。观众:'空'

har*_*ris 8 c# identityserver4 asp.net-core-3.0

我在邮递员和 IdentityServer 4 之间不断收到以下错误

Microsoft.IdentityModel.Tokens.SecurityTokenInvalidAudienceException: IDX10214: Audience validation failed. Audiences: 'empty'. Did not match: validationParameters.ValidAudience: 'MyNumberV2Api' or validationParameters.ValidAudiences: 'null'.
   at Microsoft.IdentityModel.Tokens.Validators.ValidateAudience(IEnumerable`1 audiences, SecurityToken securityToken, TokenValidationParameters validationParameters)
   at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateAudience(IEnumerable`1 audiences, JwtSecurityToken jwtToken, TokenValidationParameters validationParameters)
   at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateTokenPayload(JwtSecurityToken jwtToken, TokenValidationParameters validationParameters)
   at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateToken(String token, TokenValidationParameters validationParameters, SecurityToken& validatedToken)
   at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync()
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler: Information: BearerIdentityServerAuthenticationJwt was not authenticated. Failure message: IDX10214: Audience validation failed. Audiences: 'empty'. Did not match: validationParameters.ValidAudience: 'MyNumberV2Api' or validationParameters.ValidAudiences: 'null'.
IdentityServer4.AccessTokenValidation.IdentityServerAuthenticationHandler: Information: Bearer was not authenticated. Failure message: IDX10214: Audience validation failed. Audiences: 'empty'. Did not match: validationParameters.ValidAudience: 'MyNumberV2Api' or validationParameters.ValidAudiences: 'null'.
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService: Information: Authorization failed.
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler: Information: AuthenticationScheme: BearerIdentityServerAuthenticationJwt was challenged.
IdentityServer4.AccessTokenValidation.IdentityServerAuthenticationHandler: Information: AuthenticationScheme: Bearer was challenged.
Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request finished in 1140.9671ms 401 
The program '[12792] iisexpress.exe: Program Trace' has exited with code 0 (0x0).
The program '[12792] iisexpress.exe' has exited with code -1 (0xffffffff)..
Run Code Online (Sandbox Code Playgroud)
  1. 在我的 Identity Server Startup.cs 中
 public void ConfigureServices(IServiceCollection services)
        {
            services.AddIdentityServer(
                options => { 
                    options.Events.RaiseErrorEvents = true;
                    options.Events.RaiseInformationEvents = true;
                    options.Events.RaiseFailureEvents = true;
                    options.Events.RaiseSuccessEvents = true;
                    options.IssuerUri = "http://localhost:5000";
                }
            )
                .AddDeveloperSigningCredential()
                .AddInMemoryApiResources(Config.GetAllApiResources())
                .AddInMemoryClients(Config.GetClients())
                //.AddInMemoryIdentityResources(Config.GetIdentityResources())
                .AddInMemoryApiScopes(Config.GetApiScopes());
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseIdentityServer();
            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapGet("/", async context =>
                {
                    await context.Response.WriteAsync("Hello World!");
                });
            });
        }
Run Code Online (Sandbox Code Playgroud)
  1. 这是我的 API 的 startup.cs 的核心
 public void ConfigureServices(IServiceCollection services)
        {

            services.AddAuthentication("Bearer")
                .AddIdentityServerAuthentication(options =>
                {
                    options.Authority = "http://localhost:5000";
                    options.RequireHttpsMetadata = false;
                    options.ApiName = "MyNumberV2Api";
                });
            #region AddAuthentication
           
            services.AddDbContext<MyNumberV2.Data.MyNumberV2Context>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
            
            IdentityModelEventSource.ShowPII = true;
           
            services.AddScoped<IAdminUserRepository, AdminUserRepository>();

            services.AddCors(options =>
            {
                options.AddPolicy("Open", builder => builder.AllowAnyOrigin().AllowAnyHeader());
            });
            services.AddMvcCore();
            services.AddControllers();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthorization();

            app.UseAuthentication();

            app.UseCors("Open");

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
Run Code Online (Sandbox Code Playgroud)
  1. 这是我的完整解决方案代码的公共存储库:https : //github.com/zachion/blazor-auth

  2. 这是我在邮递员中生成身份验证令牌的方法: 在此处输入图片说明

  3. 这是我获取令牌的请求的正文部分,我在其中添加了Grant 类型和 Scope在此处输入图片说明

  4. 我从响应中获取令牌并将其添加到尝试访问实际 api 控制器的后续请求中。

  5. 这是我在邮递员中添加身份验证令牌的方法。发行令牌工作正常 在此处输入图片说明

  6. 这是我使用的完整邮递员集合:

Microsoft.IdentityModel.Tokens.SecurityTokenInvalidAudienceException: IDX10214: Audience validation failed. Audiences: 'empty'. Did not match: validationParameters.ValidAudience: 'MyNumberV2Api' or validationParameters.ValidAudiences: 'null'.
   at Microsoft.IdentityModel.Tokens.Validators.ValidateAudience(IEnumerable`1 audiences, SecurityToken securityToken, TokenValidationParameters validationParameters)
   at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateAudience(IEnumerable`1 audiences, JwtSecurityToken jwtToken, TokenValidationParameters validationParameters)
   at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateTokenPayload(JwtSecurityToken jwtToken, TokenValidationParameters validationParameters)
   at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateToken(String token, TokenValidationParameters validationParameters, SecurityToken& validatedToken)
   at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync()
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler: Information: BearerIdentityServerAuthenticationJwt was not authenticated. Failure message: IDX10214: Audience validation failed. Audiences: 'empty'. Did not match: validationParameters.ValidAudience: 'MyNumberV2Api' or validationParameters.ValidAudiences: 'null'.
IdentityServer4.AccessTokenValidation.IdentityServerAuthenticationHandler: Information: Bearer was not authenticated. Failure message: IDX10214: Audience validation failed. Audiences: 'empty'. Did not match: validationParameters.ValidAudience: 'MyNumberV2Api' or validationParameters.ValidAudiences: 'null'.
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService: Information: Authorization failed.
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler: Information: AuthenticationScheme: BearerIdentityServerAuthenticationJwt was challenged.
IdentityServer4.AccessTokenValidation.IdentityServerAuthenticationHandler: Information: AuthenticationScheme: Bearer was challenged.
Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request finished in 1140.9671ms 401 
The program '[12792] iisexpress.exe: Program Trace' has exited with code 0 (0x0).
The program '[12792] iisexpress.exe' has exited with code -1 (0xffffffff)..
Run Code Online (Sandbox Code Playgroud)

小智 26

您的代码中有两个问题,我从简单的一个开始修复:

  1. 在你的API 的启动类上,移动app.UseAuthentication();到之前app.UseAuthorization();。正确的顺序对安全至关重要。在这里阅读更多。类似的问题在这里

  2. 第二个问题是,在 API 上,您要求受众 =MyNumberV2Api但如果您在https://jwt.ms/上检查您当前的令牌,则令牌中没有audas MyNumberV2Api在这里阅读更多。为了解决这个问题,我们有两个选择:

    2.1. 更改 API 以删除受众验证。要在 API 启动类上执行此操作,请使用AddJwtBearer代替AddIdentityServerAuthentication和设置ValidateAudience = false。更改后的代码是这样的:

    services.AddAuthentication("Bearer").AddJwtBearer("Bearer",
                 options =>
                 {
                     options.Authority = "http://localhost:5000";
                     options.Audience = "MyNumberV2Api";
                     options.RequireHttpsMetadata = false;
    
                     options.TokenValidationParameters = new 
    TokenValidationParameters()
                     {
                         ValidateAudience = false
                     };
                 });
    
    Run Code Online (Sandbox Code Playgroud)

    2.2. 将受众添加到令牌。在 IdentityServer - 上Config.cs,将范围添加到 API 资源:

    return new List<ApiResource>()
             {
                 new ApiResource("MyNumberV2Api","Customer API for MyNumberV2")
                 {
                     Scopes = new []{ "MyNumberV2Api" }
                 },
                 new ApiResource("ApiOne","Customer API for MyNumberV2"),
                 new ApiResource("ApiTwo","Customer API for MyNumberV2")
             };
    
    
    Run Code Online (Sandbox Code Playgroud)

    在此更改之后,如果您重新生成令牌,将会有一个属性 asaud的 value as MyNumberV2Api。检查https://jwt.ms/上的令牌

我建议您先在 http 上测试所有内容,然后在 https 上尝试。对于 http,您可能需要app.UseHttpsRedirection();在代码中删除并清理launchSettings.json以删除 https URL,并确保"sslPort": 0.


小智 5

只是添加到已接受的答案中。IdentityServer 4 支持旧版验证,而不是更改AddIdentityServerAuthentication为使用。AddJwtBearer帮助我解决问题的是options.LegacyAudienceValidation = true;在我的AddIdentityServerAuthentication.

例子:

services.AddAuthentication()
            .AddIdentityServerAuthentication("token", options =>
            {
                options.RequireHttpsMetadata = false;
                options.Authority = "https://localhost:5001";
                options.ApiName = "API name";
                options.LegacyAudienceValidation = true;
            });
Run Code Online (Sandbox Code Playgroud)

“令牌作为我的方法中的第一个参数允许我使用“承载”身份验证。它还指定您将使用的身份验证方案。但是,您需要更新属性才能将“令牌”[Authorize]处理为。客户端的设置根本不会改变,并且在与 IdentityServer 4 共同托管 WebApi 时非常有用。更多信息请参见:IdentityServer 4 Release Docs[Authorize(AuthenticationSchemes = "token")]