.NET Core - 使用 Microsoft.Identity.Web 保护整个 Swagger UI

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

我在 .NET Core 中为我的组织构建了一个 api,并使用 PKCE 保护了 MSAL OAuth2 流背后的端点。我想做好准备,以防 api 应该被第 3 方访问。 api 本身可以通过 Bearer 令牌访问,但我也想保护 Swagger UI(访问 /swagger/index.html 应重定向到授权按钮使用的相同 OAuth2 流),以防止未经授权访问文档。

这是当前设置:

using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using System.Net;

namespace WebAPI.SomeNamespace
{
    public class SwaggerAzureAdAuthMiddleware
    {
        private readonly RequestDelegate next;
        public SwaggerAzureAdAuthMiddleware(RequestDelegate next)
        {
            this.next = next;
        }

        public async Task InvokeAsync(HttpContext context)
        {
            if (context.Request.Path.StartsWithSegments("/swagger") && !context.User.Identity.IsAuthenticated)
            {
                await context.ChallengeAsync(JwtBearerDefaults.AuthenticationScheme);
                return;
            }

            await next.Invoke(context);
        }
    }

    public static class SwaggerAuthExtensions
    {
        public static IApplicationBuilder UseSwaggerAzureAdAuth(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<SwaggerAzureAdAuthMiddleware>();
        }
    }
}

Startup.cs 摘录

//...
public void ConfigureServices(IServiceCollection services) 
{
    //...
    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddMicrosoftIdentityWebApi(_configuration.GetSection("AzureAd"))
            .EnableTokenAcquisitionToCallDownstreamApi()
            .AddMicrosoftGraph(_configuration.GetSection("MicrosoftGraph"))
            .AddInMemoryTokenCaches();
    //...
}

public void Configure(IApplicationBuilder app)
{
    //...
        app.UseSwaggerAzureAdAuth();
        app.UseSwagger();
        app.UseSwaggerUI(options =>
        {
                options.SwaggerEndpoint("/swagger/v1/swagger.json", "API v1");
                options.OAuthClientId(_configuration.GetValue<string>("AzureAd:ClientId"));
                options.OAuthScopes(_configuration.GetValue<string>("AzureAd:Scopes"));
                options.OAuthUsePkce();
        });
    //...
}
//...

这肯定是错误的,但不知道如何纠正。根据我收集的信息,

await context.ChallengeAsync()
应该触发
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
中指定的流程,但我可能误解了这一点,因为这条线在调试时似乎没有做任何事情。请帮忙。

c# swagger asp.net-core-webapi swashbuckle microsoft-identity-web
1个回答
0
投票

Swashbuckle 内置了用于集成 Azure AD 身份验证方案的配置,以便我们可以直接通过 Swagger UI 测试受 Azure AD 保护的 API。我关注了这个博客并在我身边进行了测试,效果很好。

首先,我使用 VS 模板创建了一个新的 .net 8 Web api,并将身份验证类型选择为

Microsoft Identity Platform
,以便 API 将包含使用 AAD 来保护 API 的代码。接下来,我需要使用我的 AAD 配置修改 appsettings.json。现在我需要在请求标头中包含一个不记名令牌,以便我可以访问默认的 api 端点,否则我将收到 401 错误。

enter image description here

剩下的就是添加 swagger 配置。使用以下代码替换默认的

builder.Services.AddSwaggerGen();

builder.Services.AddSwaggerGen(c => {
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "WebApplication1", Version = "v1" });
    c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
    {
        Type = SecuritySchemeType.OAuth2,
        Flows = new OpenApiOAuthFlows()
        {
            Implicit = new OpenApiOAuthFlow()
            {
                AuthorizationUrl = new Uri("https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/authorize"),
                TokenUrl = new Uri("https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token"),
                Scopes = new Dictionary<string, string> {
                    {
                        "api://{client_id}/Tiny.Greet", "API permission description"
                    }
                }
            }
        }
    });
    c.AddSecurityRequirement(new OpenApiSecurityRequirement() {
        {
            new OpenApiSecurityScheme {
                Reference = new OpenApiReference {
                    Type = ReferenceType.SecurityScheme,
                    Id = "oauth2"
                },
                Scheme = "oauth2",
                Name = "oauth2",
                In = ParameterLocation.Header
            },
            new List < string > ()
        }
    });
});

并使用下面的代码来替换默认的

app.UseSwaggerUI();

app.UseSwaggerUI(options =>
{
    options.OAuthAppName("Swagger Client");
    options.OAuthClientId("client_id");
    options.OAuthClientSecret("client_secret");
    options.OAuthUseBasicAuthenticationWithAccessCodeGrant();
});

在我上面的代码中,我有这样的 api 范围

api://client_id/Tiny.Greet
。这是我自己暴露的api权限。当我想通过 Azure AD 保护我的 API 时,我需要拥有这样的 API 权限。如果您对这部分不熟悉,可以参考本系列教程

然后,当我转到 Swagger UI 并单击“授权”按钮时,我将看到一个像这样的对话框。单击“授权”按钮会将我重定向到 Microsoft 登录页面,我需要使用我的帐户登录。我将能够使用正确的不记名令牌来测试 API。

enter image description here

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.