基于Asp.net核心令牌的声明使用OpenIdConnect和angularjs进行身份验证:禁止承载 [英] Asp.net core token based claims authentication with OpenIdConnect and angularjs: Bearer was forbidden
问题描述
我将Asp.net core rc2与OpenIdConnectServer一起使用.我正在使用augular-oauth2的angular1.x.几天后,我的错误已经转移到
I'm using Asp.net core rc2 with OpenIdConnectServer. I'm using angular 1.x with augular-oauth2. After a few days, my error has digressed to
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET http://localhost:54275/api/Account/Username
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware:Information: Successfully validated the token.
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware:Information: HttpContext.User merged via AutomaticAuthentication from authenticationScheme: Bearer.
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware:Information: AuthenticationScheme: Bearer was successfully authenticated.
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:Information: Authorization failed for user: .
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Warning: Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
Microsoft.AspNetCore.Mvc.ChallengeResult:Information: Executing ChallengeResult with authentication schemes (Bearer).
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware:Information: AuthenticationScheme: Bearer was forbidden.
我的ConfigureServices组成
My ConfigureServices consists of
services.AddAuthorization(options =>
{
options.AddPolicy("UsersOnly", policy =>
{
policy.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme);
policy.RequireClaim("role");
});
});
我的配置有
app.UseWhen(context => context.Request.Path.StartsWithSegments(new PathString("/api")), branch =>
{
branch.UseJwtBearerAuthentication(new JwtBearerOptions
{
AutomaticAuthenticate = true,
AutomaticChallenge = true,
RequireHttpsMetadata = false,
Audience = "http://localhost:54275/",
Authority = "http://localhost:54275/",
TokenValidationParameters = new TokenValidationParameters
{
ValidAudience = "client1",
//ValidAudiences = new List<string> { "", "empty", "null"}
}
});
});
app.UseOpenIdConnectServer(options =>
{
options.AuthenticationScheme = OpenIdConnectServerDefaults.AuthenticationScheme;
options.Provider = new SimpleAuthorizationServerProvider();
options.AccessTokenHandler = new JwtSecurityTokenHandler();
options.ApplicationCanDisplayErrors = true;
options.AllowInsecureHttp = true;
options.TokenEndpointPath = new PathString("/oauth2/token");
options.LogoutEndpointPath = new PathString("/oauth2/logout");
options.RevocationEndpointPath = new PathString("/oauth2/revoke");
options.UseJwtTokens();
//options.AccessTokenLifetime = TimeSpan.FromHours(1);
});
我的授权属性在控制器上定义为
My authorize attribute is defined on the Controller as
[Authorize(Policy = "UsersOnly", ActiveAuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme), Route("api/Account")]
我将令牌存储为cookie,并使用http拦截器(以angular的形式)将其附加到请求中.
I store the token as a cookie and attach it to requests using an http interceptor in angular.
我通过以下方式生成令牌
I generate the token with
public override async Task GrantResourceOwnerCredentials(GrantResourceOwnerCredentialsContext context)
{
// validate user credentials (demo mode)
// should be stored securely (salted, hashed, iterated)
using (var con = new SqlConnection(ConnectionManager.GetDefaultConnectionString()))
{
if (!Hashing.ValidatePassword(context.Password, await con.ExecuteScalarAsync<string>("SELECT PassHash FROM dbo.Users WHERE Username = @UserName", new { context.UserName })))
{
context.Reject(
error: "bad_userpass",
description: "UserName/Password combination was invalid."
);
return;
}
// create identity
var id = new ClaimsIdentity(context.Options.AuthenticationScheme);
id.AddClaim(new Claim("sub", context.UserName));
id.AddClaim(new Claim("role", "user"));
// create metadata to pass on to refresh token provider
var props = new AuthenticationProperties(new Dictionary<string, string>
{
{"as:client_id", context.ClientId}
});
var ticket = new AuthenticationTicket(new ClaimsPrincipal(id), props,
context.Options.AuthenticationScheme);
ticket.SetAudiences("client1");
//ticket.SetScopes(OpenIdConnectConstants.Scopes.OpenId, OpenIdConnectConstants.Scopes.Email, OpenIdConnectConstants.Scopes.Profile, "api-resource-controller");
context.Validate(ticket);
}
}
我已经花了最后三天时间来解决这个问题,我意识到此时由于睡眠不足,我可能会遗漏一些明显的东西.任何帮助将不胜感激.
I've spent the last three days on this problem and I realize that at this point I'm probably missing something obvious due to lack of sleep. Any help would be appreciated.
推荐答案
您看到的错误可能是由两个因素引起的:
The error you're seeing is likely caused by 2 factors:
-
您没有将显式目标附加到自定义
role
声明,因此它将永远不会在访问令牌中序列化.您可以在其他SO帖子上找到有关此安全功能的更多信息.
You're not attaching an explicit destination to your custom
role
claim so it will never be serialized in the access token. You can find more information about this security feature on this other SO post.
policy.RequireClaim("role");
可能不适用于OTB,因为IdentityModel使用内部映射将著名的JWT声明转换为等效的ClaimTypes
:在这里,role
可能会替换为http://schemas.microsoft.com/ws/2008/06/identity/claims/role
(policy.RequireRole("user")
.
policy.RequireClaim("role");
might not work OTB, as IdentityModel uses an internal mapping that converts well-known JWT claims to their ClaimTypes
equivalent: here, role
will be likely replaced by http://schemas.microsoft.com/ws/2008/06/identity/claims/role
(ClaimTypes.Role
). I'd recommend using policy.RequireRole("user")
instead.
还有一点值得注意,因为OpenID Connect服务器中间件已经为您完成了client_id
的手动存储.
It's also worth noting that manually storing the client_id
is not necessary as it's already done for you by the OpenID Connect server middleware.
您可以使用ticket.GetPresenters()
检索它,它返回授权演示者的列表(此处为客户标识符).请注意,它还会自动确保客户端B不会使用发布给客户端A的刷新令牌,因此您不必在自己的代码中进行此检查.
You can retrieve it using ticket.GetPresenters()
, that returns the list of authorized presenters (here, the client identifier). Note that it also automatically ensures a refresh token issued to a client A can't be used by a client B, so you don't have to do this check in your own code.
这篇关于基于Asp.net核心令牌的声明使用OpenIdConnect和angularjs进行身份验证:禁止承载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!