简体   繁体   English

swagger asp..net core 3.1的隐式承载流

[英]Implicit Bearer flow for swagger asp..net core 3.1

Is there a way to automatically put bearer token to every request in Swagger?有没有办法自动将不记名令牌放入 Swagger 中的每个请求? I don't want to use oauth implicit flow where I should interact with identity.我不想在应该与身份交互的地方使用 oauth 隐式流。

I'd like to provide swagger an endpoint to my api where it could take access token and automatically put it to every request.我想为我的 api 提供一个端点,它可以获取访问令牌并自动将其放入每个请求中。

In your startup.s class:在您的 startup.s 类中:

// prevent from mapping "sub" claim to nameidentifier.
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("sub");

var identityUrl = configuration.GetValue<string>("IdentityUrl");

services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
    options.Authority = identityUrl;
    options.RequireHttpsMetadata = false;
    options.Audience = "demo_api";
});

SwaggerGen SwaggerGen

    services.AddSwaggerGen(options =>
    {
      ...
        options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
       {
            Type = SecuritySchemeType.OAuth2,
            Flows = new OpenApiOAuthFlows
            {
                Implicit = new OpenApiOAuthFlow
                {
                    AuthorizationUrl = new Uri($"{configuration.GetValue<string>("IdentityUrl")}/connect/authorize"),
                    TokenUrl = new Uri($"{configuration.GetValue<string>("IdentityUrl")}/connect/token"),
                    Scopes = new Dictionary<string, string>()
                    {
                        { "api1", "Demo API - full access" }
                    }
                }
            }
        });

Operation filter操作过滤器

options.OperationFilter<AuthorizeCheckOperationFilter>();

The implementation实施

public class AuthorizeCheckOperationFilter : IOperationFilter
{
    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    {
        var hasAuthorize = context.MethodInfo.DeclaringType.GetCustomAttributes(true).OfType<AuthorizeAttribute>().Any() ||
                           context.MethodInfo.GetCustomAttributes(true).OfType<AuthorizeAttribute>().Any();

        if (!hasAuthorize) return;

        var unauthorizedHashCode = HttpStatusCode.Unauthorized.GetHashCode().ToString();
        var unauthorizedDescription = HttpStatusCode.Unauthorized.ToString();

        var forbiddenHashCode = HttpStatusCode.Forbidden.GetHashCode().ToString();
        var forbiddenDescription = HttpStatusCode.Forbidden.ToString();

        operation.Responses.TryAdd(unauthorizedHashCode, new OpenApiResponse { Description = unauthorizedDescription });
        operation.Responses.TryAdd(forbiddenHashCode, new OpenApiResponse { Description = forbiddenDescription });

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

        operation.Security = new List<OpenApiSecurityRequirement>
        {
            new OpenApiSecurityRequirement
            {
                [ oAuthScheme ] = new [] { "api1" }
            }
        };

    }
}

Use this用这个

// Keep both UseAuthentication and UseAuthorization IN THIS ORDER
app.UseAuthentication();
app.UseAuthorization();

Use Swagger使用 Swagger

app.UseSwagger(c =>
        {
            c.RouteTemplate = "swagger/{documentName}/swagger.json";
        });
        app.UseSwaggerUI(s =>
        {
            s.SwaggerEndpoint("/swagger/v1/swagger.json", "Your awesome project name");

            s.OAuthAppName("My API - Swagger");
            s.OAuthClientId("client");

            // Should match the client RedirectUrl in the IdentityServer
            s.OAuth2RedirectUrl("https://localhost:5001/swagger/oauth2-redirect.html");
        });

Your controller您的控制器

[Authorize]
[ApiController]
[Route("api/[controller]")] // TODO: Take care of the versioning
public class IndentityController : ControllerBase
{
    ...

Now in the IdentityServer Project.现在在 IdentityServer 项目中。 The ApiResources: Api资源:

public static IEnumerable<ApiResource> GetApiResources()
    {
        return new List<ApiResource>
        {
            new ApiResource("api1", "My API")
        };
    }

And finally, your Client should look like this:最后,您的客户端应如下所示:

new Client
{
    ClientId = "client",
    AllowedGrantTypes = GrantTypes.Implicit,
    RedirectUris = { "https://localhost:5001/swagger/oauth2-redirect.html" },
    AllowedScopes = { "api1" },
    AllowAccessTokensViaBrowser = true,
    RequireConsent = false
}

And for a complete source code, take a look at the eShopOnContainers repo如需完整的源代码,请查看eShopOnContainers 存储库

Good luck :)祝你好运 :)

the next code worked for me下一个代码对我有用

services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v2", new Microsoft.OpenApi.Models.OpenApiInfo
            {
                Version = "v2",
                Title = "PRJ API",
                Description = "PRJ Web API",
            });

            if (oktaIssuer != null)
            {
                c.AddSecurityDefinition("Okta", new OpenApiSecurityScheme
                {
                    Type = SecuritySchemeType.OAuth2,
                    Scheme = "Bearer",
                    In = ParameterLocation.Header,
                    Name = "Authorization",
                    Flows = new OpenApiOAuthFlows
                    {
                        Implicit = new OpenApiOAuthFlow
                        {
                            AuthorizationUrl = new Uri($"{oktaIssuer}/v1/authorize"),
                            Scopes = new Dictionary<string, string>
                            {
                                { "profile", "Access profile" },
                                { "email", "Email"},
                                { "openid", "OpenID"}
                            }
                        }
                    }
                });

                c.AddSecurityRequirement(new OpenApiSecurityRequirement
                {
                    {
                        new OpenApiSecurityScheme
                        {
                            Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Okta" },
                            Scheme = "oauth2",
                            Name = "Bearer",
                            In = ParameterLocation.Header
                        },
                       
                        new string[] {}
                    }
                });
                c.OperationFilter<AuthorizeCheckOperationFilter>();
            }

Also those strings must be the same!这些字符串也必须相同! AddSecurityDefinition&AddSecurityRequirement

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM