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

Posted

技术标签:

【中文标题】如何在 .NET Core 2.2 WebApi 和 Azure AD 2.0 中配置 Swagger?【英文标题】:How to Configure Swagger in .NET Core 2.2 WebApi and Azure AD 2.0? 【发布时间】:2019-09-20 06:47:29 【问题描述】:

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

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 端点并获取错误令牌类型的 Swagger 配置中做错了什么?

更新:

这是对 Azure AD 授权端点的提琴手请求:

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

【问题讨论】:

嗨,Saeid,您是否可以在本地托管它并获取提琴手/网络跟踪以查看 Swagger 真正在做什么?如果是这样,您能否提供大摇大摆的 URL 是什么?看起来 configureservices 方法设置正确,所以它应该转到 v2.0 端点, 嘿@FrankHu。我用 Fiddler 请求更新了这个问题。奇怪的是,该 API 可以与使用 MSAL 库进行身份验证的客户端 SPA 应用程序一起正常工作。它只是不适用于 Swagger 或 Postman。不过,感谢您对此进行检查。 如果您愿意,我可以让您与技术支持部门联系以仔细查看。查看完整的提琴手跟踪可能很有用。我不确定该请求是否是 Swagger 请求。您可以通过 AzCommunity@microsoft.com 给我发送电子邮件,并在电子邮件中包含指向该主题的链接,这样我就可以为您启用免费支持请求。 @Saeid 你是怎么解决的? 【参考方案1】:

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

访问令牌是根据令牌的受众创建的,即拥有令牌范围的应用程序。这就是将应用清单中的资源设置 accessTokenAcceptedVersion 为 2 允许调用 v1.0 端点的客户端接收 v2.0 访问令牌的方式。同样,这就是为什么更改客户端的访问令牌可选声明不会更改在为 user.read 请求令牌时收到的访问令牌,该令牌由 MS Graph 资源拥有。 出于同样的原因,在使用个人帐户(例如 hotmail.com 或 Outlook.com)测试您的客户端应用程序时,您可能会发现您的客户端收到的访问令牌是一个不透明的字符串。这是因为正在访问的资源请求了已加密且客户端无法理解的旧版 MSA(Microsoft 帐户)票证。

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

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

【讨论】:

以上是关于如何在 .NET Core 2.2 WebApi 和 Azure AD 2.0 中配置 Swagger?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 AzureAD 和 AzureADBearer 添加到 asp.net core 2.2 web api

从.Net core 2.2迁移到.Net Core 3.0

如何将 .NET Core 2.2 Web API 迁移到 .NET Core 3.0?

这是如何使用 Entity Framework Core 和 ASP.NET Core MVC 2.2+ 和 3.0 创建数据传输对象 (DTO)

无法从 NET Core 2.2 Web API 连接到 docker sql server

如何测试返回 Ok(object) 的 ASP.NET Core 2.2 Web API GET IActionResult?