ASP.NET Core 3.0身份服务器4(4.0.0)SecurityTokenInvalidAudienceException:IDX10214:听众验证失败.受众群体:“空" [英] ASP.NET Core 3.0 Identity Server 4 (4.0.0) SecurityTokenInvalidAudienceException: IDX10214: Audience validation failed. Audiences: 'empty'

查看:71
本文介绍了ASP.NET Core 3.0身份服务器4(4.0.0)SecurityTokenInvalidAudienceException:IDX10214:听众验证失败.受众群体:“空"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在邮递员和IdentityServer 4之间收到以下错误消息

  Microsoft.IdentityModel.Tokens.SecurityTokenInvalidAudienceException:IDX10214:听众验证失败.观众:空".不匹配:validationParameters.ValidAudience:"MyNumberV2Api"或validationParameters.ValidAudiences:"null".在Microsoft.IdentityModel.Tokens.Validators.ValidateAudience(IEnumerable`1听众,SecurityToken securityToken,TokenValidationParametersvalidationParameters)在System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateAudience(IEnumerable`1听众,JwtSecurityToken jwtToken,TokenValidationParametersvalidationParameters)在System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateTokenPayload(JwtSecurityToken jwtToken,TokenValidationParametersvalidationParameters)在System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateToken(字符串令牌,TokenValidationParametersvalidationParameters,SecurityToken& validatedToken)处在Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync()Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler:信息:BearerIdentityServerAuthenticationJwt未通过身份验证.失败消息:IDX10214:听众验证失败.观众:空".不匹配:validationParameters.ValidAudience:"MyNumberV2Api"或validationParameters.ValidAudiences:"null".IdentityServer4.AccessTokenValidation.IdentityServerAuthenticationHandler:信息:承载未通过身份验证.失败消息:IDX10214:听众验证失败.观众:空".不匹配:validationParameters.ValidAudience:"MyNumberV2Api"或validationParameters.ValidAudiences:"null".Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:信息:授权失败.Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler:信息:AuthenticationScheme:BearerIdentityServerAuthenticationJwt被质询.IdentityServer4.AccessTokenValidation.IdentityServerAuthenticationHandler:信息:AuthenticationScheme:承载被质询.Microsoft.AspNetCore.Hosting.Diagnostics:信息:请求在1140.9671ms中完成401程序"[12792] iisexpress.exe:程序跟踪"已退出,代码为0(0x0).程序"[12792] iisexpress.exe"已退出,代码为-1(0xffffffff). 

  1. 在我的Identity Server Startup.cs中

  public void ConfigureServices(IServiceCollection服务){services.AddIdentityServer(选项=>{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());}//此方法由运行时调用.使用此方法来配置HTTP请求管道.公共无效配置(IApplicationBuilder应用程序,IWebHostEnvironment env){如果(env.IsDevelopment()){app.UseDeveloperExceptionPage();}app.UseIdentityServer();app.UseRouting();app.UseEndpoints(endpoints =>{endpoints.MapGet("/",异步上下文=>{等待context.Response.WriteAsync("Hello World!");});});} 

  1. 这是我API的startup.cs的核心

  public void ConfigureServices(IServiceCollection服务){services.AddAuthentication(承载者").AddIdentityServerAuthentication(options =>{options.Authority ="http://localhost:5000";options.RequireHttpsMetadata = false;options.ApiName ="MyNumberV2Api";});#region AddAuthenticationservices.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();}//此方法由运行时调用.使用此方法来配置HTTP请求管道.公共无效配置(IApplicationBuilder应用程序,IWebHostEnvironment env){如果(env.IsDevelopment()){app.UseDeveloperExceptionPage();}app.UseHttpsRedirection();app.UseRouting();app.UseAuthorization();app.UseAuthentication();app.UseCors("Open");app.UseEndpoints(endpoints =>{endpoints.MapControllers();}); 

  1. 这是我的完整解决方案代码的公共仓库:

  2. 这是我获取令牌的请求的正文部分,我在其中添加了 Grant类型和范围.

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

  4. 这是我在邮递员中添加身份验证令牌的方式.发行令牌工作正常

  5. 这是我使用的完整邮递员收藏集:

  {信息":{"_postman_id":"089a85df-ae4b-41c3-8d1e-9d2e4ff8f7c8","name":"MYNumberV2.Api复制","schema":"https://schema.getpostman.com/json/collection/v2.1.0/collection.json"},物品": [{"name":"Generate Tokent API One",要求": {身份验证":{"type":基本",基本的": [{"key":密码","value":秘密","type":字符串"},{"key":用户名","value":客户","type":字符串"}]},"method":"POST",标题":[],身体": {"mode":"urlencoded","urlencoded":[{"key":"grant_type","value":"client_credentials","type":文字"},{"key":"scope","value":"MyNumberV2Api","type":文字"}],选项": {"urlencoded":{}}},"url":{"raw":"http://localhost:5000/connect/token","protocol":"http",主持人": [本地主机"],"port":"5000",小路": [连接",令牌"]}},回复": []},{"name":"api/adminuser","protocolProfileBehavior":{"disableBodyPruning":为true},要求": {身份验证":{"type":"noauth"},"method":"GET",标题":[{"key":授权","type":文字",值": 承载eyJhbGciOiJSUzI1NiIsImtpZCI6IjNENDZERDNFQ0NGNTNCNkMyNEZEMjlFOUEzQzE2RjVDIiwidHlwIjoiYXQrand0In0.eyJuYmYiOjE1OTM0NTQyNTQsImV4cCI6MTU5MzQ1Nzg1NCwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo1MDAwIiwiY2xpZW50X2lkIjoiY2xpZW50IiwianRpIjoiQ0QxQzY5QzVGRkI0MTA0RDU5MTUwNERFQkI0MkI3NjgiLCJpYXQiOjE1OTM0NTQyNTQsInNjb3BlIjpbIk15TnVtYmVyVjJBcGkiXX0.xvAs-IYh_sh8RmpNOcy4Rl78Jv2L2-vPE7FYeEVqxES2HBoTEEgPT7uV5MiZrVeK1OaLOrkERzZ4druHrBtKgaeJ-BoC_IUt5Lp_otnJVbmCgGtrPXk8RMKcZguvxQsJdD5rqHLNZaN07kMNQEmmAprSAPpixtErzMK5DEmaAee2PNi430AyiZnObYbUBm_07Un5_6cjpOSFltjzsABBOzsbWfXIbXwvynCUVEiN5_mHhhjgocPcvlzrHdDtUi_PbdBk_hhtouTlveIaCTyNGdhfR4JCTJjO069hVVCXHScrekjNPeRSC4eOFEesmdG-4IbPKWBLsKldc1SrC1DE-W"}],身体": {"mode":"urlencoded","urlencoded":[{"key":"grant_type","value":"client_credentials","type":文字",已禁用":true},{"key":"scope","value":"MyNumberV2Api","type":文字",已禁用":true}],选项": {"urlencoded":{}}},"url":{"raw":"http://localhost:44340/api/adminuser","protocol":"http",主持人": [本地主机"],端口":"44340",小路": ["api","adminuser"]},说明":"https://localhost:44340/api/adminuser"},回复": []},{"name":"api/adminuserdetail/1",要求": {"method":"GET",标题":[],"url":{"raw":"http://localhost:44340/api/adminuserdetail/1","protocol":"http",主持人": [本地主机"],端口":"44340",小路": ["api","adminuserdetail","1"]},说明":"https://localhost:44340/api/adminuser"},回复": []}],"protocolProfileBehavior":{}}  

解决方案

您的代码中有2个问题,我从一个简单的问题开始解决:

  1. 在您的 API的启动类,将 app.UseAuthentication(); 移到 app.UseAuthorization(); 之前.正确的订单对于安全性至关重要.在此处.类似问题此处

  2. 第二个问题是,在API上您要求受众= MyNumberV2Api ,但是如果您在 https://jwt.ms/令牌中没有作为 MyNumberV2Api aud .在此处中了解更多.要解决此问题,我们有两个选择:

    2.1.更改API以删除受众群体验证.要在API启动类上执行此操作,请使用 AddJwtBearer 而不是 AddIdentityServerAuthentication 并设置 ValidateAudience = false .更改后的代码将如下所示:

      services.AddAuthentication("Bearer").AddJwtBearer("Bearer"),选项=>{options.Authority ="http://localhost:5000";options.Audience ="MyNumberV2Api";options.RequireHttpsMetadata = false;options.TokenValidationParameters =新TokenValidationParameters(){ValidateAudience =否};}); 

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

     返回新列表< ApiResource>(){新的ApiResource("MyNumberV2Api","MyNumberV2的客户API"){范围= new [] {"MyNumberV2Api"}},新的ApiResource("ApiOne","MyNumberV2的客户API"),新的ApiResource("ApiTwo","MyNumberV2的客户API")}; 

    此更改之后,如果您重新生成令牌,将有一个属性为 aud ,其值为 MyNumberV2Api .检查 https://jwt.ms/

    上的令牌

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

I keep getting the following error between postman and 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)..

  1. In my 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!");
                });
            });
        }

  1. And here's the core for my API's 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();
            });

  1. Here is my public repo for the full solution code: https://github.com/zachion/blazor-auth

  2. Here is how I generate an auth token in postman:

  3. And here is the body section of my request to get the token where i add the Grant type and Scope.

  4. I get the token from the response and add it to the follow up requests for trying to get to the actual api's controllers.

  5. Here is how I add the auth token in postman. Issuing the token works fine

  6. Here's the complete post man collection I use:

{
    "info": {
        "_postman_id": "089a85df-ae4b-41c3-8d1e-9d2e4ff8f7c8",
        "name": "MYNumberV2.Api Copy",
        "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
    },
    "item": [
        {
            "name": "Generate Tokent API One",
            "request": {
                "auth": {
                    "type": "basic",
                    "basic": [
                        {
                            "key": "password",
                            "value": "secret",
                            "type": "string"
                        },
                        {
                            "key": "username",
                            "value": "client",
                            "type": "string"
                        }
                    ]
                },
                "method": "POST",
                "header": [],
                "body": {
                    "mode": "urlencoded",
                    "urlencoded": [
                        {
                            "key": "grant_type",
                            "value": "client_credentials",
                            "type": "text"
                        },
                        {
                            "key": "scope",
                            "value": "MyNumberV2Api",
                            "type": "text"
                        }
                    ],
                    "options": {
                        "urlencoded": {}
                    }
                },
                "url": {
                    "raw": "http://localhost:5000/connect/token",
                    "protocol": "http",
                    "host": [
                        "localhost"
                    ],
                    "port": "5000",
                    "path": [
                        "connect",
                        "token"
                    ]
                }
            },
            "response": []
        },
        {
            "name": "api/adminuser",
            "protocolProfileBehavior": {
                "disableBodyPruning": true
            },
            "request": {
                "auth": {
                    "type": "noauth"
                },
                "method": "GET",
                "header": [
                    {
                        "key": "Authorization",
                        "type": "text",
                        "value": "Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IjNENDZERDNFQ0NGNTNCNkMyNEZEMjlFOUEzQzE2RjVDIiwidHlwIjoiYXQrand0In0.eyJuYmYiOjE1OTM0NTQyNTQsImV4cCI6MTU5MzQ1Nzg1NCwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo1MDAwIiwiY2xpZW50X2lkIjoiY2xpZW50IiwianRpIjoiQ0QxQzY5QzVGRkI0MTA0RDU5MTUwNERFQkI0MkI3NjgiLCJpYXQiOjE1OTM0NTQyNTQsInNjb3BlIjpbIk15TnVtYmVyVjJBcGkiXX0.xvAs-IYh_sh8RmpNOcy4Rl78Jv2L2-vPE7FYeEVqxES2HBoTEEgPT7uV5MiZrVeK1OaLOrkERzZ4druHrBtKgaeJ-BoC_IUt5Lp_otnJVbmCgGtrPXk8RMKcZguvxQsJdD5rqHLNZaN07kMNQEmmAprSAPpixtErzMK5DEmaAee2PNi430AyiZnObYbUBm_07Un5_6cjpOSFltjzsABBOzsbWfXIbXwvynCUVEiN5_mHhhjgocPcvlzrHdDtUi_PbdBk_hhtouTlveIaCTyNGdhfR4JCTJjO069hVVCXHScrekjNPeRSC4eOFEesmdG-4IbPKWBLsKldc1SrC1DE-w"
                    }
                ],
                "body": {
                    "mode": "urlencoded",
                    "urlencoded": [
                        {
                            "key": "grant_type",
                            "value": "client_credentials",
                            "type": "text",
                            "disabled": true
                        },
                        {
                            "key": "scope",
                            "value": "MyNumberV2Api",
                            "type": "text",
                            "disabled": true
                        }
                    ],
                    "options": {
                        "urlencoded": {}
                    }
                },
                "url": {
                    "raw": "http://localhost:44340/api/adminuser",
                    "protocol": "http",
                    "host": [
                        "localhost"
                    ],
                    "port": "44340",
                    "path": [
                        "api",
                        "adminuser"
                    ]
                },
                "description": "https://localhost:44340/api/adminuser"
            },
            "response": []
        },
        {
            "name": "api/adminuserdetail/1",
            "request": {
                "method": "GET",
                "header": [],
                "url": {
                    "raw": "http://localhost:44340/api/adminuserdetail/1",
                    "protocol": "http",
                    "host": [
                        "localhost"
                    ],
                    "port": "44340",
                    "path": [
                        "api",
                        "adminuserdetail",
                        "1"
                    ]
                },
                "description": "https://localhost:44340/api/adminuser"
            },
            "response": []
        }
    ],
    "protocolProfileBehavior": {}
}

解决方案

There is 2 issues in your code, I start from easy one to fix:

  1. On your API's startup class, move app.UseAuthentication(); to be before app.UseAuthorization();. Proper order is critical for security. Read more here. Similar issue here

  2. Second issue is that on API you are asking for audience = MyNumberV2Api but if you check your current token on https://jwt.ms/ there is no aud as MyNumberV2Api in the token. Read more here. To fix this we have two options:

    2.1. Change API to remove audience validation. To do this on API startup class use AddJwtBearer instead of AddIdentityServerAuthentication and set ValidateAudience = false. After change code would be like this:

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

    2.2. Add the audience to token. On IdentityServer - Config.cs, add the scopes to API resource:

    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")
             };
    
    

    After this change, if you regenerate the token there will be a property as aud with value as MyNumberV2Api. Check the token on https://jwt.ms/

I suggest you to test every thing on http first and then try on https. For http you may need to remove app.UseHttpsRedirection(); in your code and also clean up the launchSettings.json to remove https URLS and make sure "sslPort": 0.

这篇关于ASP.NET Core 3.0身份服务器4(4.0.0)SecurityTokenInvalidAudienceException:IDX10214:听众验证失败.受众群体:“空"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆