簡體   English   中英

如何在ASP.net Core應用程序中同時使用Bearer和Cookie身份驗證?

[英]How can I use both Bearer and Cookie authentication in my ASP.net Core application?

我正在使用ASP.net Core 2.0應用程序,該應用程序使用IdentityServer4令牌服務器進行身份驗證。 我的應用程序具有Razor Pages,我想與它一起使用Cookie身份驗證,它也具有一個API,我想與它一起使用Bearer令牌。

這是我在Startup.cs擁有的設置:

    public void ConfigureServices(IServiceCollection services) {
//...
        services.AddAuthentication(options => { options.DefaultChallengeScheme = "oidc"; })
            .AddIdentityServerAuthentication(JwtBearerDefaults.AuthenticationScheme, options =>
            {
                options.Authority = Configuration["OpenIDConnect:Authority"];
                options.ApiName = Configuration["OpenIDConnect:ApiName"];
                options.JwtBearerEvents.OnChallenge += async context =>
                {
                    context.Response.StatusCode = StatusCodes.Status403Forbidden;
                    context.HandleResponse();
                };
            })
            .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
            .AddOpenIdConnect("oidc", options =>
            {
                options.SignInScheme = "Cookies";
                options.Authority = Configuration["OpenIdConnect:Authority"];
                options.RequireHttpsMetadata = false;
                options.ClientId = Configuration["OpenIdConnect:ClientId"];
                options.SaveTokens = true;
                options.Scope.Add("role");
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    NameClaimType = "name",
                    RoleClaimType = "role"
                };
            });

        services.AddAuthorization(options =>
        {
            options.AddPolicy(Constants.Policies.ApiUserWithBearerToken,
                policy =>
                {
                    policy.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme);
                    policy.AuthenticationSchemes.Remove(CookieAuthenticationDefaults.AuthenticationScheme);
                    policy.AuthenticationSchemes.Remove("oidc");
                    policy.RequireClaim("MobileClient", "true");
                    policy.RequireClaim("ApiUser", "true");
                });
        });
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env) {
    //…
    //…
    app.UseAuthentication();
}

這是我嘗試使用Bearer令牌保護的API端點:

[Route("api/[controller]"), Authorize(Policy = "ApiUserWithBearerToken", AuthenticationSchemes = "Bearer"), MobileAppController]
public class CatalogController : Controller
{
    // …
    [HttpGet("current")]
    public async Task<IActionResult> Current()
    {
        // …
    }        
}

我的問題是ASP.net似乎完全忽略了我的Bearer身份驗證方案設置。 如果我使用有效的承載令牌請求current端點,它將返回到IdentityServer的重定向,要求我登錄。

這是來自Kestrel的消息日志:

info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://localhost:5001/api/Catalog/current
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
      Authorization failed for user: (null).
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[3]
      Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
info: Microsoft.AspNetCore.Mvc.ChallengeResult[1]
      Executing ChallengeResult with authentication schemes ().
info: Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler[12]
      AuthenticationScheme: oidc was challenged.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
      Executed action Pinball.Web.Controllers.CatalogController.Current (Catalog.Web) in 1185.1356ms
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 1871.9771ms 302

如果刪除默認的挑戰方案,則ASP.net只會引發一個異常,指出它是必需的。

我在這里想念什么?

我遇到了同樣的問題,自從解決了問題,我很高興提供解決方案。 通過調用services.AddIdentityServer()添加Identity Server時,默認情況下會默認添加cookie身份驗證,如您在此處所見, https://github.com/IdentityServer/IdentityServer4/blob/75b1a660c3cab2580112e6e0288f3f6bed8189f9/src/Configuration/DependencyInjection/IdentityServerServiceCollectionExtensions.cs。

builder
   .AddRequiredPlatformServices()
   .AddCookieAuthentication() // <-- Cookie auth added
   .AddCoreServices()
   .AddDefaultEndpoints()
   .AddPluggableServices()
   .AddValidators()
   .AddResponseGenerators()
   .AddDefaultSecretParsers()
   .AddDefaultSecretValidators();

之后,您可以使用services.AddAuthentication()添加身份驗證,因此此時您無需再添加cookie身份驗證,因為它已經被添加了。 您只需要通過添加以下代碼來添加IS身份驗證:

services.AddAuthentication()
    .AddIdentityServerAuthentication(options =>
    {
        options.Authority = Configuration["Settings:Authentication:Authority"];
        options.RequireHttpsMetadata = !CurrentEnvironment.IsDevelopment();

        options.ApiName = Configuration["Settings:Authentication:ApiName"];
        options.ApiSecret = Configuration["Settings:Authentication:ApiSecret"];
     });

您也不需要.AddOpenIdConnect()方法。

現在,請記住,完成此操作后,您聲明了兩種用於服務身份驗證請求的身份驗證方法。 第一個是cookie(由IS添加),另一個是通過調用.AddIdentityServerAuthentication()添加的JWT承載。 由於cookie是首先添加的,因此在需要驗證任何請求時也將首先調用它,因此,您需要指定要在授權時使用的方法,可以通過使用以下方法正確完成:

[Route("api/[controller]"), Authorize(Policy = "ApiUserWithBearerToken", AuthenticationSchemes = "Bearer"), MobileAppController]

我個人使用IS默認值,但結果是相同的:

[Route("api/[controller]"), Authorize(Policy = "ApiUserWithBearerToken", AuthenticationSchemes = IdentityServerAuthenticationDefaults.AuthenticationScheme), MobileAppController]

有了這個,您應該有一個可以同時處理API請求和Razor頁面的應用程序。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM