我如何设置Swashbuckle和Swagger UI以使用Open ID Connect Discovery进行授权,以便它可以提供正确的承载令牌?

发布于 2025-01-28 05:01:20 字数 1587 浏览 3 评论 0原文

如何设置Swashbuckle和Swagger UI以授权使用Open ID Connect Discovery(在我的情况下为Azure AD)?

到目前/a>:

SwaggerGenOptions c => {
    OpenApiInfo apiInfo = new()  { /* ...snip... */ };
    c.SwaggerDoc("v1", apiInfo);
    IncludeXmlFileForSwagger(c);

    // Defines the Open ID Connect discovery scheme - see also https://stackoverflow.com/a/66147996/7453
    OpenApiSecurityScheme mainScheme = new()
    {
        Type = SecuritySchemeType.OpenIdConnect,
        OpenIdConnectUrl = new Uri($"https://login.microsoftonline.com/{myTenantId}/.well-known/openid-configuration"),
    };
    c.AddSecurityDefinition("OpenIdConnect", mainScheme);

    // Adds a reference to the above scheme as required for every API action (we can get more nuanced later)
    //   Note: if just try to use mainScheme instead, it doesn't apply a Bearer token)
    OpenApiSecurityScheme securityScheme = new() {
        Reference = new OpenApiReference {
            Type = ReferenceType.SecurityScheme, Id = "OpenIdConnect"
        }
    };
    OpenApiSecurityRequirement securityRequirements = new() { {securityScheme, Array.Empty<string>()} };
    c.AddSecurityRequirement(securityRequirements);
}

...在静态配置方法中,我有...

app.UseSwaggerUI(c =>
{
    c.SwaggerEndpoint("/swagger/v1/swagger.json", "MyService v1");
    c.OAuthClientId(myClientId);
    c.OAuthUsePkce();
});

因此,上述代码使我可以进行身份​​验证并检查一个称为“ openID”的范围,并显示“锁定的“ padock”。通过Swagger UI,它提供了一个持久的代币,但

我需要以某种方式指定一个名为“ openID”的明确指定

?有效吗?

How do I set up Swashbuckle and Swagger UI to Authorize using Open ID Connect Discovery (in my case, to Azure AD)?

Here's my (not-fully-working) SwaggerGen setup so far, based on https://stackoverflow.com/a/66147996/7453 :

SwaggerGenOptions c => {
    OpenApiInfo apiInfo = new()  { /* ...snip... */ };
    c.SwaggerDoc("v1", apiInfo);
    IncludeXmlFileForSwagger(c);

    // Defines the Open ID Connect discovery scheme - see also https://stackoverflow.com/a/66147996/7453
    OpenApiSecurityScheme mainScheme = new()
    {
        Type = SecuritySchemeType.OpenIdConnect,
        OpenIdConnectUrl = new Uri(
quot;https://login.microsoftonline.com/{myTenantId}/.well-known/openid-configuration"),
    };
    c.AddSecurityDefinition("OpenIdConnect", mainScheme);

    // Adds a reference to the above scheme as required for every API action (we can get more nuanced later)
    //   Note: if just try to use mainScheme instead, it doesn't apply a Bearer token)
    OpenApiSecurityScheme securityScheme = new() {
        Reference = new OpenApiReference {
            Type = ReferenceType.SecurityScheme, Id = "OpenIdConnect"
        }
    };
    OpenApiSecurityRequirement securityRequirements = new() { {securityScheme, Array.Empty<string>()} };
    c.AddSecurityRequirement(securityRequirements);
}

...and in the static configure method, I have...

app.UseSwaggerUI(c =>
{
    c.SwaggerEndpoint("/swagger/v1/swagger.json", "MyService v1");
    c.OAuthClientId(myClientId);
    c.OAuthUsePkce();
});

So the above code lets me authenticate and check a scope called "openid" and shows the "locked" padlock". When I try to run a action via the Swagger UI, it supplies a Bearer token but it comes back invalid.

Do I need to somehow specify an explicit named scope, rather than "openid"? How?

Is my setup even right? If so, why isn't the token valid? Any ideas for troubleshooting?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

狠疯拽 2025-02-04 05:01:20

由于Swagger UI正在使用Web浏览器上下文来提出请求,因此我发现仅在顶部提供一个将它们带到需要AUTH的任何API调用的链接更容易,更简单需要授权的功能。

如果您的API自动重定向并使用浏览器功能登录,这将起作用。用户登录后,Swagger UI的所有将来的HTTP请求都会像直接在浏览器中击中端点一样发送auth cookie。

首先,启动conform.cs中的Swagger配置,包括一个链接以在用户友好的情况下进行签名:

services.AddSwaggerGen(c => {
    OpenApiInfo apiInfo = new()
    {
        Title = "MyService",
        Version = "v1",
        Description = "<p>An API for working with ... "
            + "<p>If you get '<b>Failed to fetch</b>' below on an action that shows a padlock icon, this likely "
            + "means you are not <b>signed in</b>, so "
            + "<a target=\"_blank\" href=\"/api/v1/security/signIn\">sign in here</a>, then "
            + "your sign-in will take effect for any action below.",
    };
    c.SwaggerDoc("v1", apiInfo);

    /* put other configuration here, such as c.IncludeXmlComments */

    c.OperationFilter<MethodNeedsAuthorizationFilter>(); // puts auth UI on the right actions                                                             
});

在上面的示例中,我的端点/api/v1/security/security/security/security/secustin需要授权;您可以使用需要授权的任何端点。

然后,这是您需要适当地显示开放式锁定图标的MethodNeedSauthorizationFilter:

using Microsoft.AspNetCore.Authorization;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using System;
using System.Collections.Generic;
using System.Linq;
namespace GeneralMills.TradePlannerService;
/// <summary>
/// Provides a method that applies Swagger UI security requirements to all controller actions that need authorization.
/// </summary>
public class MethodNeedsAuthorizationFilter : IOperationFilter
{
    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    {
        if (operation is null) throw new ArgumentNullException(nameof(operation));
        if (context is null) throw new ArgumentNullException(nameof(context));

        object[] methodAttributes = context.MethodInfo.GetCustomAttributes(true);

        bool needsAuth =
            methodAttributes.OfType<AuthorizeAttribute>().Any()
            || (context.MethodInfo.DeclaringType != null
                && context.MethodInfo.DeclaringType.GetCustomAttributes(true).OfType<AuthorizeAttribute>().Any()
                && !methodAttributes.OfType<AllowAnonymousAttribute>().Any());

        if (needsAuth)
        {
            OpenApiSecurityScheme scheme = new()
            {
                Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "ExampleName" },
                Scheme = "ExampleName",
                Name = "ExampleName",
                In = ParameterLocation.Header,
            };

            operation.Security = new List<OpenApiSecurityRequirement>()
            {
                new () { {scheme, new List<string>() } }
            };
        }
    }
}

这有效地规避了Swagger UI的内置授权支持,我无法正常工作。

Since Swagger UI is using the web browser context to make the requests, I found it easier and way simpler to just provide a link at the top that will bring them to any API call that requires auth, and then also add a security requirement on all functions that require authorization.

This will work if your API automatically redirects and uses browser functionality to sign in, as I think most do. After the user signs in, all future HTTP requests from the Swagger UI will send the auth cookie just as it would for hitting the endpoints in the browser directly.

First, the Swagger config in Startup.cs, including a link to make signing in user-friendly:

services.AddSwaggerGen(c => {
    OpenApiInfo apiInfo = new()
    {
        Title = "MyService",
        Version = "v1",
        Description = "<p>An API for working with ... "
            + "<p>If you get '<b>Failed to fetch</b>' below on an action that shows a padlock icon, this likely "
            + "means you are not <b>signed in</b>, so "
            + "<a target=\"_blank\" href=\"/api/v1/security/signIn\">sign in here</a>, then "
            + "your sign-in will take effect for any action below.",
    };
    c.SwaggerDoc("v1", apiInfo);

    /* put other configuration here, such as c.IncludeXmlComments */

    c.OperationFilter<MethodNeedsAuthorizationFilter>(); // puts auth UI on the right actions                                                             
});

In the example above, my endpoint /api/v1/security/signIn requires authorization; you can use any endpoint of yours that requires authorization.

Then here's the MethodNeedsAuthorizationFilter you need to enable showing the open padlock icon appropriately:

using Microsoft.AspNetCore.Authorization;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using System;
using System.Collections.Generic;
using System.Linq;
namespace GeneralMills.TradePlannerService;
/// <summary>
/// Provides a method that applies Swagger UI security requirements to all controller actions that need authorization.
/// </summary>
public class MethodNeedsAuthorizationFilter : IOperationFilter
{
    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    {
        if (operation is null) throw new ArgumentNullException(nameof(operation));
        if (context is null) throw new ArgumentNullException(nameof(context));

        object[] methodAttributes = context.MethodInfo.GetCustomAttributes(true);

        bool needsAuth =
            methodAttributes.OfType<AuthorizeAttribute>().Any()
            || (context.MethodInfo.DeclaringType != null
                && context.MethodInfo.DeclaringType.GetCustomAttributes(true).OfType<AuthorizeAttribute>().Any()
                && !methodAttributes.OfType<AllowAnonymousAttribute>().Any());

        if (needsAuth)
        {
            OpenApiSecurityScheme scheme = new()
            {
                Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "ExampleName" },
                Scheme = "ExampleName",
                Name = "ExampleName",
                In = ParameterLocation.Header,
            };

            operation.Security = new List<OpenApiSecurityRequirement>()
            {
                new () { {scheme, new List<string>() } }
            };
        }
    }
}

This effectively circumvents Swagger UI's built-in authorization support, which I could not get working.

油饼 2025-02-04 05:01:20

SwashBuckle充当OIDC服务器的客户端,以获取访问令牌。因此,首先,您应该添加重定向URI以允许列表&lt; origin&gt;/swagger/oauth2-redirect.html(example,https:// https:// localhost:&ltocalhost:&lt; -redirect.html用于本地开发。
Swashbuckle将创建并托管(不是直接)请求以获取发现文档的内容。这样您就应该确保CORS政策是否允许Swashbuckle Origin。

Swashbuckle acts as a client of OIDC server to get access token. Hence, first you should add Redirect Uri to allow list <origin>/swagger/oauth2-redirect.html (example, https://localhost:<port>/swagger/oauth2-redirect.htmlfor local development.
Swashbuckle will create and CORS (not direct) request to get content of discovery documents. So that you should ensure if CORS policy allows Swashbuckle origin.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文