[英]Asp.net core 2.0+ - Multiple Authentication Schemes (Cookie / Bearer)
I've been struggling to get multiple authentication schemes working correctly in Asp.net core 2.1.我一直在努力使多个身份验证方案在 Asp.net 核心 2.1 中正常工作。
I am using Identity Server with an implicit flow and OpenIdConnect as the protocol.我使用带有隐式流和 OpenIdConnect 作为协议的 Identity Server。
When authorizing an action or controller with one of the schemes only (eg Cookie or Bearer) the functionality works correctly.当仅使用其中一种方案(例如 Cookie 或 Bearer)授权操作或控制器时,该功能可以正常工作。
Example:例子:
[Authorize(AuthenticationSchemes = "Cookies")]
[Route("Cookies")]
public class BearerAndCookiesController : Controller {
If I however I specify on the Authorize attribute both schemes, then it fails partially.但是,如果我在 Authorize 属性上指定了两种方案,那么它会部分失败。 Bearer works as normal, but when I try to view the page in the browser it attempts to redirect to a local Login page ( http://localhost/Account/Login ).
Bearer 正常工作,但是当我尝试在浏览器中查看页面时,它会尝试重定向到本地登录页面 ( http://localhost/Account/Login )。
When I inspect the debug logs of Identity Server nothing is returned, which makes sense as it hasn't attempted to contact the Authority.当我检查 Identity Server 的调试日志时,没有返回任何内容,这是有道理的,因为它没有尝试联系管理局。 However when I look at the debug log of the Test MVC Site both the Bearer and Cookie schemes are challenged:
但是,当我查看测试 MVC 站点的调试日志时,Bearer 和 Cookie 方案都受到挑战:
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET http://localhost:5002/cookies
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Route matched with {action = "Get", controller = "BearerAndCookies"}. Executing action MvcClient.Controllers.BearerAndCookiesController.Get (MvcClient)
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:Information: Authorization failed.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
Microsoft.AspNetCore.Mvc.ChallengeResult:Information: Executing ChallengeResult with authentication schemes (Bearer, Cookies).
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler:Information: AuthenticationScheme: Bearer was challenged.
Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler:Information: AuthenticationScheme: Cookies was challenged.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action MvcClient.Controllers.BearerAndCookiesController.Get (MvcClient) in 68.1922ms
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 93.2016ms 302
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET http://localhost:5002/Account/Login?ReturnUrl=%2Fcookies
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 30.2532ms 404
Failed to load resource: the server responded with a status of 404 (Not Found) [http://localhost:5002/Account/Login?ReturnUrl=%2Fcookies]
Does anyone know why this isn't working?有谁知道为什么这不起作用? I'll the person a beer!
我要人喝啤酒! It's been hunting me for the last week.
上周它一直在追捕我。
https://docs.microsoft.com/en-us/aspnet/core/security/authorization/limitingidentitybyscheme?view=aspnetcore-2.2&tabs=aspnetcore2x https://docs.microsoft.com/en-us/aspnet/core/security/authorization/limitingidentitybyscheme?view=aspnetcore-2.2&tabs=aspnetcore2x
Here is my Startup.cs configuration:这是我的 Startup.cs 配置:
public void ConfigureServices(IServiceCollection services) {
services.AddMvc();
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
services.AddAuthentication(options => {
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddJwtBearer(options => {
options.Authority = "http://localhost:5000";
options.Audience = "myApi";
options.RequireHttpsMetadata = false;
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options => {
options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false;
options.ClientId = "myApi";
options.SaveTokens = true;
});
}
[Authorize(AuthenticationSchemes = AuthSchemes)]
[Route("Cookies")]
public class BearerAndCookiesController : Controller {
private const string AuthSchemes =
JwtBearerDefaults.AuthenticationScheme + "," +
CookieAuthenticationDefaults.AuthenticationScheme;
I wanted to give a better explanation of this answer:我想更好地解释这个答案:
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
services.AddAuthentication(options => {
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options => {
options.SignInScheme = "Cookies";
options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false;
options.ClientId = "myApi";
options.SaveTokens = true;
}).AddIdentityServerAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme, options => {
options.Authority = "http://localhost:5000";
options.ApiName = "myApi";
options.RequireHttpsMetadata = false;
});
services.AddAuthorization(options => {
...
});
services.AddAuthorization(options =>
{
var defaultAuthorizationPolicyBuilder = new AuthorizationPolicyBuilder(
CookieAuthenticationDefaults.AuthenticationScheme,
JwtBearerDefaults.AuthenticationScheme);
defaultAuthorizationPolicyBuilder =
defaultAuthorizationPolicyBuilder.RequireAuthenticatedUser();
options.DefaultPolicy = defaultAuthorizationPolicyBuilder.Build();
});
app.UseAuthentication();
app.Use(async (context, next) => {
await next();
var bearerAuth = context.Request.Headers["Authorization"]
.FirstOrDefault()?.StartsWith("Bearer ") ?? false;
if (context.Response.StatusCode == 401
&& !context.User.Identity.IsAuthenticated
&& !bearerAuth) {
await context.ChallengeAsync("oidc");
}
});
Bob's your uncle... and thanks to this post for helping considerably!!鲍勃是你的叔叔……感谢这篇文章的帮助!! oipapio.com/question-1510997
oipapio.com/question-1510997
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.