c# - 如何在 .NET Core 2.2 WebApi 和 Azure AD 2.0 中配置 Swagger?

标签 c# asp.net-core .net-core azure-active-directory asp.net-core-webapi

我对 Swagger 的“授权”功能有疑问,无法使用 Azure AD 2.0 端点对 WebApi 应用程序进行身份验证。我在启动类中使用了以下设置,但获取的 token 无法验证 Swagger 中的承载 token 。 API 可以很好地处理 React 客户端发送的 token 。

private const string AzureAdConfigKey = "AzureAd";
private const string OAuth2Definition = "openid";

private IConfiguration Configuration { get; }
private IHostingEnvironment Environment { get; }

public Startup(IConfiguration configuration, IHostingEnvironment environment)
{
    Environment = environment;
    Configuration = configuration;
}

public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication(AzureADDefaults.JwtBearerAuthenticationScheme)
        .AddAzureADBearer(options => Configuration.Bind(AzureAdConfigKey, options));

    services.Configure<JwtBearerOptions>(AzureADDefaults.JwtBearerAuthenticationScheme,
        options => options.Authority += "/v2.0");

    var authorizationPolicy = new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .Build();

    services.AddMvc(options => options.Filters.Add(new AuthorizeFilter(authorizationPolicy)))
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

    var azureAdAuthority = $"https://login.microsoftonline.com/{Configuration["AzureAd:TenantId"]}/oauth2/v2.0";
    services.AddSwaggerGen(options =>
    {
        options.SwaggerDoc("v1", new Info
        {
            Title = "My Api Name",
            Version = "v1"
        });

        options.AddSecurityDefinition(OAuth2Definition, new OAuth2Scheme
        {
            Description = "OAuth2 Implicit Grant",
            Flow = "implicit",
            AuthorizationUrl = $"{azureAdAuthority}/authorize",
            TokenUrl = $"{azureAdAuthority}/connect/token",
            Scopes = new Dictionary<string, string>
            {
                {OAuth2Definition, "User.Read"}
            }
        });

        options.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>> {{OAuth2Definition, null}});
    });

    services.AddCors(options => options.AddPolicy("AllowSpecificOrigin", builder => builder
        .WithOrigins(Configuration["MyAppClientUrl"])
        .AllowCredentials()
        .AllowAnyHeader()
        .AllowAnyMethod()
    ));

    // Other Service Registrations.
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseMiddleware<ErrorHandlingMiddleware>();

    app.UseCors("AllowSpecificOrigin");

    app.UseHsts();
    app.UseHttpsRedirection();

    app.UseSwagger();
    app.UseSwaggerUI(config =>
    {
        const string swaggerName = "MyApp Coding Api";
        const string swaggerUrl = "/swagger/v1/swagger.json";

        config.SwaggerEndpoint(swaggerUrl, swaggerName);
        config.RoutePrefix = string.Empty;

        config.OAuthAppName(swaggerName);
        config.OAuthClientId(Configuration["AzureAd:ClientId"]);
        config.OAuthClientSecret(Configuration["AzureAd:ClientSecret"]);
        // This is my Api local path.
        config.OAuthRealm("https://localhost:44398/swagger/ui/o2c-html");
        config.OAuthScopeSeparator(" ");
    });

    app.UseAuthentication();
    app.UseMvc();
}

以下是客户端生成的token,运行良好,实现了.v2.0:

{
  "aud": "{Excldued}",
  "iss": "https://login.microsoftonline.com/{Excldued}/v2.0",
  "iat": 1556730915,
  "nbf": 1556730915,
  "exp": 1556734815,
  "aio": "AVQAq/8LAAAA9lULrpdFyoAfnaWTCkdo8PMz2vL4C0MbDNAxmRBa3rMETsjpnXYFb5izdF/VRWMLzOvwgmw9Zt3zzisWRbLCFMd5KAaJ59wUDqNdSoawS6U=",
  "name": "{Excldued}",
  "nonce": "{Excldued}",
  "oid": "{Excldued}",
  "preferred_username": "{Excldued}",
  "roles": [
    "Coder",
    "Supervisor"
  ],
  "sub": "Jn0w0rhsGpwTKPdSjQBLHeHDv2_TD4kaOjo0x06JWKQ",
  "tid": "{Excldued}",
  "uti": "pOW4Q_EBdkSv_q0-OHRSAA",
  "ver": "2.0"
}

但是 swagger 会生成以下 token ,即 .v1.0:

{
  "aud": "00000003-0000-0000-c000-000000000000",
  "iss": "https://sts.windows.net/{Excluded}/",
  "iat": 1556733552,
  "nbf": 1556733552,
  "exp": 1556737452,
  "acct": 0,
  "acr": "1",
  "aio": "AUQAu/8LAAAA9YXDyeK8KuCHbNgw7RGU8GgJk3qpWB1H+Q3i/dC/VRoAtYvp3NHFIYcTFxn3jfTPvvXRWx5MN35kvO0iCK7ftg==",
  "amr": [
    "pwd",
    "mfa"
  ],
  "app_displayname": "{Excluded}",
  "appid": "{Excluded}",
  "appidacr": "0",
  "family_name": "{Excluded}",
  "given_name": "{Excluded}",
  "ipaddr": "{Excluded}",
  "name": "{Excluded}",
  "oid": "{Excluded}",
  "onprem_sid": "{Excluded}",
  "platf": "3",
  "puid": "{Excluded}",
  "scp": "openid profile User.Read email",
  "signin_state": [
    "kmsi"
  ],
  "sub": "{Excluded}",
  "tid": "{Excluded}",
  "unique_name": "{Excluded}",
  "upn": "{Excluded}",
  "uti": "{Excluded}",
  "ver": "1.0",
  "xms_st": {
    "sub": "{Excluded}"
  },
  "xms_tcdt": 1361394419
}

我在请求 1.0 端点并获取错误 token 类型的 Swagger 配置中做错了什么?

更新:

这是对 Azure AD 授权端点的 fiddler 请求:

GET https://login.microsoftonline.com/{TenantId}/oauth2/v2.0/authorize?response_type=token&client_id={ClientId}&redirect_uri=https%3A%2F%2Flocalhost%3A44350%2Foauth2-redirect.html&scope=openid&state={StateValue}&nonce=123456 HTTP/1.1
Host: login.microsoftonline.com
Connection: keep-alive
Upgrade-Insecure-Requests: 1
DNT: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Referer: https://localhost:44350/index.html
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9

最佳答案

您获得 v1.0 token 的原因是因为您正在尝试访问 v1.0 资源。请在此处查看文章:https://learn.microsoft.com/en-us/azure/active-directory/develop/access-tokens

Access tokens are created based on the audience of the token, meaning the application that owns the scopes in the token. This is how a resource setting accessTokenAcceptedVersion in the app manifest to 2 allows a client calling the v1.0 endpoint to receive a v2.0 access token. Similarly, this is why changing the access token optional claims for your client do not change the access token received when a token is requested for user.read, which is owned by the MS Graph resource. For the same reason, while testing your client application with a personal account (such as hotmail.com or outlook.com), you may find that the access token received by your client is an opaque string. This is because the resource being accessed has requested legacy MSA (Microsoft account) tickets that are encrypted and can't be understood by the client.

您的 v1.0 token 具有由 v1.0 端点颁发的 Microsoft Graph 的受众。如果您关注此处的文章:https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow 您会看到,即使在访问 v2.0 端点并使用 Postman 为资源 graph.microsoft.com 请求访问 token 时,您也会在 iss 没有 v2.0 的情况下获得访问 token 。

这也是一个非常有用的资源,因为它是对 Azure 中一些流行 GUID 的很好引用。 : https://www.shawntabrizi.com/aad/common-microsoft-resources-azure-active-directory/

关于c# - 如何在 .NET Core 2.2 WebApi 和 Azure AD 2.0 中配置 Swagger?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55940714/

相关文章:

c# - 如何使用 Moq 模拟 IMongoCollection.Find

c# - C# JIT 优化器中可能存在错误?

c# - 如何比较T与T?

.net - 使用 DeveloperExceptionPage 时如何使用 ApplicationInsights 2.x 记录 ASP.NET Core 应用程序中的异常

c# - 请求参数为空?

.net - dotnet build 未编译 .NET Framework 4.6.1 应用程序

c# - 避免 DivideByZero 异常的好方法

c# - 如何在 UWP C# 中将类列表写入文件

c# - 使用 C# 仅获取 JSON 的一部分

SOAP 请求转换错误