使用OpenId,OAuth2,Cognito,.NET Core 3.1和Swagger的Invalid_request,未经授权的客户端

问题描述 投票:0回答:1

[我试图在我的API中使用OpenIdOAuth2添加一个身份验证层,但是当我进行调用时,在标头中传递令牌时,我一直在接收]]

Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectProtocolException:消息包含错误:'invalid_request',error_description:'unauthorized_client',error_uri:'error_uri为null'。

我已经配置了AWS Cognitostartup.cs,并且可以从Swagger或Postman成功获得JWT token

您在startup.cs中看到配置错误或丢失的东西吗?

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

            services.AddAuthentication(c =>
                {
                    c.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                    c.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                    c.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
                })
                .AddCookie()
                .AddOpenIdConnect(c =>
                {
                    c.ResponseType = Configuration["Authentication:Cognito:ResponseType"];
                    c.MetadataAddress = Configuration["Authentication:Cognito:MetadataAddress"];
                    c.ClientId = Configuration["Authentication:Cognito:ClientId"];
                    c.Authority = "https://auth.myauthserver.com";

                    c.Scope.Add("myscope");
                    c.GetClaimsFromUserInfoEndpoint = true;
                });

            // Configure named auth policies that map directly to OAuth2.0 scopes
            services.AddAuthorization(c =>
            {
                c.AddPolicy("myscope", p => p.RequireClaim("scope", "myscope"));
            });

            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo
                {
                    Title = "MyAPI", Version = "v1"
                });
                c.OperationFilter<AddAuthHeaderOperationFilter>();

                c.AddSecurityDefinition("bearer", //Name the security scheme
                    new OpenApiSecurityScheme{
                        Flows = new OpenApiOAuthFlows()
                        {
                            ClientCredentials = new OpenApiOAuthFlow()
                            {
                                TokenUrl = new Uri("https://auth.myauthserver.com/oauth2/token"),
                                Scopes = new Dictionary<string, string>(){ {"myscope", "Access API"}},
                                AuthorizationUrl = new Uri("https://auth.myautherver.com/oauth2/authorize")
                            }
                        }, 
                        Type = SecuritySchemeType.OAuth2,
                        OpenIdConnectUrl = new Uri("https://cognito-idp-url.../.well-known/openid-configuration"),
                        BearerFormat = "JWT",
                        In = ParameterLocation.Header,
                        Scheme = "bearer"
                    });

                c.AddSecurityRequirement(new OpenApiSecurityRequirement{ 
                    {
                        new OpenApiSecurityScheme{
                            Reference = new OpenApiReference{
                                Id = "Bearer",
                                Type = ReferenceType.SecurityScheme
                            },
                            OpenIdConnectUrl = new Uri("https://cognito-idp-url.../.well-known/openid-configuration")
                        },new List<string>(){"myscope"}
                    }
                });
            });

            services.AddOptions();

            services.AddCors(options => options.AddPolicy("CorsPolicy",
                builder =>
                {
                    builder
                        .AllowAnyOrigin()
                        .AllowAnyMethod()
                        .AllowAnyHeader()
                        .AllowCredentials();
                }));
        }

        // 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();
            else
                app.UseHsts();

            app.UseCors(policy => 
                 policy
                     .SetIsOriginAllowedToAllowWildcardSubdomains()
                     .AllowAnyOrigin()
                     .SetPreflightMaxAge(TimeSpan.FromDays(1))
             );
            app.UseCors("CorsPolicy");

            app.UseHttpsRedirection();
            app.UseRouting();
            app.UseAuthorization();
            app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
            app.UseAuthentication();

            app.UseSwagger();
            app.UseSwaggerUI(c => { 
                c.SwaggerEndpoint($"v1/swagger.json", "MyAPI v1");
                c.OAuth2RedirectUrl("https://auth.myauthserver.com/signin-oidc");
            });
        }

控制器具有[Authorize][Produces("application/json")]属性。

这是AddAuthHeaderOperationFilter

public class AddAuthHeaderOperationFilter : IOperationFilter
    {
        public void Apply(OpenApiOperation operation, OperationFilterContext context)
        {
            var isAuthorized = (context.MethodInfo.DeclaringType.GetCustomAttributes(true).OfType<AuthorizeAttribute>().Any()
                                || context.MethodInfo.GetCustomAttributes(true).OfType<AuthorizeAttribute>().Any())
                               && !context.MethodInfo.GetCustomAttributes(true).OfType<AllowAnonymousAttribute>().Any(); // this excludes methods with AllowAnonymous attribute

            if (!isAuthorized) return;

            operation.Responses.TryAdd("401", new OpenApiResponse { Description = "Unauthorized" });
            operation.Responses.TryAdd("403", new OpenApiResponse { Description = "Forbidden" });

            var jwtbearerScheme = new OpenApiSecurityScheme
            {
                Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "bearer" }
            };

            operation.Security = new List<OpenApiSecurityRequirement>
            {
                new OpenApiSecurityRequirement { [jwtbearerScheme] = new string []{} }
            };
        }
    }

这是appsettings.json的一部分:

"Authentication": {
    "Cognito": {
      "ClientId": "47...",
      "IncludeErrorDetails": true,
      "MetadataAddress": "https://cognito-idp-url.../.well-known/openid-configuration",
      "RequireHttpsMetadata": false,
      "ResponseType": "code",
      "SaveToken": true,
      "TokenValidationParameters": {
        "ValidateIssuer": true
      }
    }
  },

[Cognito配置为接受客户端凭据OAuth流,并且选择了允许的身份验证范围myscope

这是一个curl示例:

curl -X GET "https://localhost:5001/v1/MyController/2" -H "accept: application/json" -H "Authorization: Bearer eyJraWQiOiI2dGFPTW..."

谢谢

<< [

我终于找到了解决我问题的方法。并非所有配置都正确,我将在此处保留与“客户端凭据”流配合使用并允许通过Swagger和OpenAPI进行身份验证的startup.cs
[Authentication:Cognito:Authorityappsettings.json中配置为"Authority": "https://cognito-idp.eu-west-1.amazonaws.com/your_region-id"
public void ConfigureServices(IServiceCollection services) { IdentityModelEventSource.ShowPII = true; services.AddControllers(); Initializer.RegisterServices(services); services.AddAuthentication(o => { o.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; o.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { IssuerSigningKeyResolver = (s, securityToken, identifier, parameters) => { var json = new WebClient().DownloadString( parameters.ValidIssuer + "/.well-known/jwks.json"); var keys = JsonConvert.DeserializeObject<JsonWebKeySet>(json).Keys; return (IEnumerable<SecurityKey>) keys; }, ValidIssuer = Configuration["Authentication:Cognito:Authority"], ValidateIssuerSigningKey = true, ValidateIssuer = false, ValidateLifetime = true, ValidateAudience = false, }; options.IncludeErrorDetails = true; options.SaveToken = true; options.Authority = Configuration["Authentication:Cognito:Authority"]; options.RequireHttpsMetadata = true; }) .AddOpenIdConnect(options => { options.Authority = Configuration["Authentication:Cognito:Authority"]; options.RequireHttpsMetadata = false; options.ClientId = Configuration["Authentication:Cognito:ClientId"]; options.Scope.Add("myscope"); });; services.AddAuthorization(options => { options.DefaultPolicy = new AuthorizationPolicyBuilder(JwtBearerDefaults.AuthenticationScheme) .RequireAuthenticatedUser() .Build(); }); services.AddSwaggerGen(c => { c.SwaggerDoc(ApiVersion, new OpenApiInfo { Title = "MyAPI", Version = "v1" }); c.OperationFilter<AddAuthHeaderOperationFilter>(); c.AddSecurityDefinition("bearer", //Name the security scheme new OpenApiSecurityScheme { Flows = new OpenApiOAuthFlows { ClientCredentials = new OpenApiOAuthFlow { TokenUrl = new Uri("https://auth.myauthserver.com/oauth2/token"), Scopes = new Dictionary<string, string> {{"myscope", "Access API"}}, AuthorizationUrl = new Uri("https://auth.myauthserver.com/oauth2/authorize") } }, Type = SecuritySchemeType.OAuth2, OpenIdConnectUrl = new Uri( "https://cognito-idp.eu-west-1.amazonaws.com/your_region-id/.well-known/openid-configuration"), BearerFormat = "JWT", In = ParameterLocation.Header, Scheme = "bearer" }); }); services.AddOptions(); } // 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(); else app.UseHsts(); app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); app.UseAuthentication(); app.UseSwagger(); app.UseSwaggerUI(c => { c.SwaggerEndpoint($"{ApiVersion}/swagger.json", "MyAPI v1"); c.OAuth2RedirectUrl("https://auth.myauthserver.com/signin-oidc"); c.OAuthConfigObject = new OAuthConfigObject { ClientId = Configuration["Authentication:Cognito:ClientId"], UsePkceWithAuthorizationCodeGrant = true }; }); }

希望对您有帮助。

c# oauth-2.0 swagger amazon-cognito openid
1个回答
0
投票
public void ConfigureServices(IServiceCollection services) { IdentityModelEventSource.ShowPII = true; services.AddControllers(); Initializer.RegisterServices(services); services.AddAuthentication(o => { o.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; o.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { IssuerSigningKeyResolver = (s, securityToken, identifier, parameters) => { var json = new WebClient().DownloadString( parameters.ValidIssuer + "/.well-known/jwks.json"); var keys = JsonConvert.DeserializeObject<JsonWebKeySet>(json).Keys; return (IEnumerable<SecurityKey>) keys; }, ValidIssuer = Configuration["Authentication:Cognito:Authority"], ValidateIssuerSigningKey = true, ValidateIssuer = false, ValidateLifetime = true, ValidateAudience = false, }; options.IncludeErrorDetails = true; options.SaveToken = true; options.Authority = Configuration["Authentication:Cognito:Authority"]; options.RequireHttpsMetadata = true; }) .AddOpenIdConnect(options => { options.Authority = Configuration["Authentication:Cognito:Authority"]; options.RequireHttpsMetadata = false; options.ClientId = Configuration["Authentication:Cognito:ClientId"]; options.Scope.Add("myscope"); });; services.AddAuthorization(options => { options.DefaultPolicy = new AuthorizationPolicyBuilder(JwtBearerDefaults.AuthenticationScheme) .RequireAuthenticatedUser() .Build(); }); services.AddSwaggerGen(c => { c.SwaggerDoc(ApiVersion, new OpenApiInfo { Title = "MyAPI", Version = "v1" }); c.OperationFilter<AddAuthHeaderOperationFilter>(); c.AddSecurityDefinition("bearer", //Name the security scheme new OpenApiSecurityScheme { Flows = new OpenApiOAuthFlows { ClientCredentials = new OpenApiOAuthFlow { TokenUrl = new Uri("https://auth.myauthserver.com/oauth2/token"), Scopes = new Dictionary<string, string> {{"myscope", "Access API"}}, AuthorizationUrl = new Uri("https://auth.myauthserver.com/oauth2/authorize") } }, Type = SecuritySchemeType.OAuth2, OpenIdConnectUrl = new Uri( "https://cognito-idp.eu-west-1.amazonaws.com/your_region-id/.well-known/openid-configuration"), BearerFormat = "JWT", In = ParameterLocation.Header, Scheme = "bearer" }); }); services.AddOptions(); } // 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(); else app.UseHsts(); app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); app.UseAuthentication(); app.UseSwagger(); app.UseSwaggerUI(c => { c.SwaggerEndpoint($"{ApiVersion}/swagger.json", "MyAPI v1"); c.OAuth2RedirectUrl("https://auth.myauthserver.com/signin-oidc"); c.OAuthConfigObject = new OAuthConfigObject { ClientId = Configuration["Authentication:Cognito:ClientId"], UsePkceWithAuthorizationCodeGrant = true }; }); }
© www.soinside.com 2019 - 2024. All rights reserved.