如何将声明包含到从授权端点检索的访问令牌中?
Posted
技术标签:
【中文标题】如何将声明包含到从授权端点检索的访问令牌中?【英文标题】:How do I include claims into the Access Token retrieved from the Authorize endpoint? 【发布时间】:2016-10-16 22:50:36 【问题描述】:我想在通过 IdSrv 进行身份验证时检索到的访问令牌中包含默认声明。声明Ticket
应始终包含在访问令牌中,因此我创建了一个新的资源范围,并将Ticket
包含为ScopeClaim
。但是,正如您从 IdSrv 日志中看到的那样,当 IdSrv 创建访问令牌并调用 GetProfileDataAsync
时,上下文中请求的声明列表为空,因此没有声明被添加到访问令牌中。
如何在默认情况下将此声明包含到访问令牌中?
我的印象是,请求 Resource
范围将允许范围内的声明作为访问令牌的一部分返回。
范围
public static List<Scope> Get()
return new List<Scope>
StandardScopes.OpenId //standard scope when dealing with open id connect
,
StandardScopes.OfflineAccess
,
new Scope
Name = "App",
DisplayName = "App",
Type = ScopeType.Identity,
Claims = new List<ScopeClaim>
new ScopeClaim
AlwaysIncludeInIdToken = false,
Name = "App",
Description = "Role Information"
,
// new ScopeClaim
//
// AlwaysIncludeInIdToken = false,
// Name = "Ticket",
// Description = "Login ticket"
//
,
IncludeAllClaimsForUser = false
,
new Scope
Name = "AppAccess",
DisplayName = "AppAccess",
Type = ScopeType.Resource,
Claims = new List<ScopeClaim>
new ScopeClaim
Name = "Ticket",
Description = "Login ticket",
,
IncludeAllClaimsForUser = true
;
索赔
public static List<Client> Get()
return new List<Client>
new Client
ClientName = "Hybrid Flow",
ClientId = "apphybrid",
Enabled = true,
Flow = Flows.Hybrid,
AllowAccessToAllScopes = true,
IdentityTokenLifetime = 120,
AccessTokenLifetime = 400,
RequireConsent = false,
ClientSecrets = new List<Secret>
new Secret("secret".Sha256())
,
RedirectUris = new List<string>
"localhost/App/login/Login.mr"
,
PostLogoutRedirectUris = new List<string>
"localhost/App/login/Login.mr"
,
AllowedScopes = new List<string>
Constants.StandardScopes.OpenId,
Constants.StandardScopes.OfflineAccess,
"App",
"AppAccess"
;
IDSrv 配置
public override Task AuthenticateLocalAsync(LocalAuthenticationContext context)
var securityServiceProxy = new SecurityServiceProxy(new ServiceHeadersParameters UserHostAddress = Ctx.Request.Host.Value );
var ticket = securityServiceProxy.UseServiceClient(serviceClient => serviceClient.AuthenticateUser(context.UserName, context.Password, Configuration.ProviderCode));
if (!ticket.IsValid())
context.AuthenticateResult = new AuthenticateResult("Invalid credentials");
return Task.FromResult(0);
var claims = new List<Claim>
new Claim(GlobalConstant.TicketClaim, ticket.Ticket.ToString())
;
context.AuthenticateResult = new AuthenticateResult(
ticket.UserObjId.ToString(),
context.UserName,
claims: claims,
authenticationMethod: Constants.AuthenticationMethods.Password,
identityProvider: Configuration.ProviderCode
);
return Task.FromResult(0);
public override Task GetProfileDataAsync(ProfileDataRequestContext context)
var applicationDto = GetApplicationDto(context);
var claims = new List<Claim>
new Claim(Constants.ClaimTypes.Subject, context.Subject.GetSubjectId()),
;
Log.Debug("The requested claims...");
if (context.RequestedClaimTypes == null)
Log.Debug("Requested Claims is null");
else
foreach (var x in context.RequestedClaimTypes)
Log.Debug($"Claims x");
if (context.RequestedClaimTypes.Contains(GlobalConstant.TicketClaim))
claims.Add(context.Subject.Claims.Where(x => x.Type.Equals(GlobalConstant.TicketClaim)).FirstOrDefault());
if (context.RequestedClaimTypes.Contains(GlobalConstant.ApplicationClaim))
claims.Add(new Claim(GlobalConstant.ApplicationClaim, applicationDto.Jsonify()));
// set the issued claims - these are the ones that were requested, if available
context.IssuedClaims = claims;
Log.Debug("Finished ProfileDataAsync");
return Task.FromResult(0);
private ApplicationDto GetApplicationDto(ProfileDataRequestContext context)
var securityServiceProxy = new SecurityServiceProxy(new ServiceHeadersParameters UserHostAddress = Ctx.Request.Host.Value );
return securityServiceProxy.UseServiceClient(serviceClient => serviceClient.RetrieveAuthenticatedUser(GetUserTicketFromContext(context)));
private static UserTicketDto GetUserTicketFromContext(ProfileDataRequestContext context)
Log.Debug("The claims in the context...");
foreach(var x in context.Subject.Claims)
Log.Debug($"Cliams x.Type x.Value");
var ticketString = context.Subject.Claims.Where(x => x.Type.Equals(GlobalConstant.TicketClaim)).FirstOrDefault()?.Value;
var userIdString = context.Subject.GetSubjectId();
Guid Ticket, UserId;
if(Guid.TryParse(ticketString, out Ticket) && Guid.TryParse(userIdString, out UserId))
return new UserTicketDto Ticket = Ticket, UserObjId = UserId ;
return new UserTicketDto();
网络配置
JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>();
AntiForgeryConfig.UniqueClaimTypeIdentifier = IdentityModel.JwtClaimTypes.Name;
app.Use(async (ctx, next) => await next(); );
app.UseCookieAuthentication(new CookieAuthenticationOptions
AuthenticationType = "cookies"
);
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
ClientId = OAuthConstant.Client,
RedirectUri = "localhost/App/login/Login.mr",
PostLogoutRedirectUri = "localhost/App/login/Login.mr",
Authority = "localhost/Oauth2server/securetoken",
SignInAsAuthenticationType = "Cookies",
ResponseType = "token code id_token",
Scope = "OpenId App offline_access AppAccess",
ClientSecret = "secret",
UseTokenLifetime = false,
Notifications = new OpenIdConnectAuthenticationNotifications()
AuthorizationCodeReceived = IdentityServerClient.HandleOther,
SecurityTokenReceived = IdentityServerClient.HandleOther,
MessageReceived = IdentityServerClient.HandleOther,
AuthenticationFailed = IdentityServerClient.HandleOther,
RedirectToIdentityProvider = IdentityServerClient.HandleRedirectToIdentityProvider,
SecurityTokenValidated = IdentityServerClient.HandleSecurityTokenValidated
);
日志
2016-06-15 12:04:51.943 -05:00 [Information] Login page submitted
2016-06-15 12:04:55.320 -05:00 [Information] Login credentials successfully validated by user service
2016-06-15 12:04:55.332 -05:00 [Information] Calling PostAuthenticateAsync on the user service
2016-06-15 12:04:55.338 -05:00 [Information] issuing primary signin cookie
2016-06-15 12:04:55.344 -05:00 [Information] redirecting to: http://localhost/OAuth2Server/securetoken/connect/authorize?client_id=apphybrid&redirect_uri=http:%2F%2Flocalhost%2Fapp%2FLogin%2FLogin.mr&response_mode=form_post&response_type=code id_token token&scope=App openid offline_access AppAccess&state=OpenIdConnect.AuthenticationProperties%3DebxFcJnjMiMq2m1gPqBsYlrBWdLct2kaJSYn-s0nxImnff-37i4t8Wa3wAJewJGFe9msgeeqJDKtR1gwwfA0e8Pdd6RNAi6YPo_CqT4l5zV8ifohYQVN9TrWfLXITXuKId9IW2cCeRQL6d8uWfkzSANqAGSbSGJYZ5pgOLULQresbAiJ7N77FgBmgrVtX4hDQuwGGL5vZFCb_C5tjl8_ezH12w8zQfifKuLwjaDmOSGYyo2AqpowQXXeSSSDgKBF&nonce=636016067018002117.MWY4MGVjOWItYTFjYS00MTVlLTg4MDYtMjYxYjkwMWEzNzU4ZWViNzEyNTQtMjE0Mi00MjYzLTk2ZjMtODdhYmIxYTM5Mjg5
2016-06-15 12:04:55.368 -05:00 [Debug] Incoming request: /securetoken/connect/authorize
2016-06-15 12:04:55.381 -05:00 [Information] Start authorize request
2016-06-15 12:04:55.381 -05:00 [Information] Start authorize request protocol validation
2016-06-15 12:04:55.381 -05:00 [Information] "Authorize request validation success"
"
\"ClientId\": \"apphybrid\",
\"ClientName\": \"app Hybrid Flow\",
\"RedirectUri\": \"http://localhost/app/Login/Login.mr\",
\"AllowedRedirectUris\": [
\"http://localhost/app/Login/Login.mr\"
],
\"SubjectId\": \"783bf872-b864-4042-853d-04fbcb7a505a\",
\"ResponseType\": \"code id_token token\",
\"ResponseMode\": \"form_post\",
\"Flow\": \"Hybrid\",
\"RequestedScopes\": \"app openid offline_access appAccess\",
\"State\": \"OpenIdConnect.AuthenticationProperties=ebxFcJnjMiMq2m1gPqBsYlrBWdLct2kaJSYn-s0nxImnff-37i4t8Wa3wAJewJGFe9msgeeqJDKtR1gwwfA0e8Pdd6RNAi6YPo_CqT4l5zV8ifohYQVN9TrWfLXITXuKId9IW2cCeRQL6d8uWfkzSANqAGSbSGJYZ5pgOLULQresbAiJ7N77FgBmgrVtX4hDQuwGGL5vZFCb_C5tjl8_ezH12w8zQfifKuLwjaDmOSGYyo2AqpowQXXeSSSDgKBF\",
\"Nonce\": \"636016067018002117.MWY4MGVjOWItYTFjYS00MTVlLTg4MDYtMjYxYjkwMWEzNzU4ZWViNzEyNTQtMjE0Mi00MjYzLTk2ZjMtODdhYmIxYTM5Mjg5\",
\"SessionId\": \"e79cd97a339b4513b45038e7755c1b88\",
\"Raw\":
\"client_id\": \"apphybrid\",
\"redirect_uri\": \"http://localhost/app/Login/Login.mr\",
\"response_mode\": \"form_post\",
\"response_type\": \"code id_token token\",
\"scope\": \"app openid offline_access appAccess\",
\"state\": \"OpenIdConnect.AuthenticationProperties=ebxFcJnjMiMq2m1gPqBsYlrBWdLct2kaJSYn-s0nxImnff-37i4t8Wa3wAJewJGFe9msgeeqJDKtR1gwwfA0e8Pdd6RNAi6YPo_CqT4l5zV8ifohYQVN9TrWfLXITXuKId9IW2cCeRQL6d8uWfkzSANqAGSbSGJYZ5pgOLULQresbAiJ7N77FgBmgrVtX4hDQuwGGL5vZFCb_C5tjl8_ezH12w8zQfifKuLwjaDmOSGYyo2AqpowQXXeSSSDgKBF\",
\"nonce\": \"636016067018002117.MWY4MGVjOWItYTFjYS00MTVlLTg4MDYtMjYxYjkwMWEzNzU4ZWViNzEyNTQtMjE0Mi00MjYzLTk2ZjMtODdhYmIxYTM5Mjg5\"
"
2016-06-15 12:04:55.399 -05:00 [Information] Creating Hybrid Flow response.
2016-06-15 12:04:55.412 -05:00 [Information] Creating Implicit Flow response.
2016-06-15 12:04:55.416 -05:00 [Debug] Creating access token
2016-06-15 12:04:55.424 -05:00 [Debug] Getting ProfileDataAsync
2016-06-15 12:04:55.436 -05:00 [Debug] The claims in the context...
2016-06-15 12:04:55.437 -05:00 [Debug] Cliams sub 783bf872-b864-4042-853d-04fbcb7a505a
2016-06-15 12:04:55.437 -05:00 [Debug] Cliams name dev.guser
2016-06-15 12:04:55.437 -05:00 [Debug] Cliams amr password
2016-06-15 12:04:55.437 -05:00 [Debug] Cliams idp IDSRV
2016-06-15 12:04:55.437 -05:00 [Debug] Cliams auth_time 1466010295
2016-06-15 12:04:55.437 -05:00 [Debug] Cliams ticket fc05cd84-7756-4ec5-ac3c-53ac6d4d5e2a
2016-06-15 12:04:55.975 -05:00 [Debug] The requseted claims...
2016-06-15 12:04:55.976 -05:00 [Debug] Requested Claims Is Null
2016-06-15 12:04:55.976 -05:00 [Debug] Finished ProfileDataAsync
2016-06-15 12:04:55.982 -05:00 [Debug] Creating JWT access token
2016-06-15 12:04:56.049 -05:00 [Debug] Creating identity token
2016-06-15 12:04:56.054 -05:00 [Information] Getting claims for identity token for subject: 783bf872-b864-4042-853d-04fbcb7a505a
2016-06-15 12:04:56.054 -05:00 [Debug] Getting ProfileDataAsync
2016-06-15 12:04:56.066 -05:00 [Debug] The claims in the context...
2016-06-15 12:04:56.066 -05:00 [Debug] Cliams sub 783bf872-b864-4042-853d-04fbcb7a505a
2016-06-15 12:04:56.066 -05:00 [Debug] Cliams name dev.guser
2016-06-15 12:04:56.066 -05:00 [Debug] Cliams amr password
2016-06-15 12:04:56.066 -05:00 [Debug] Cliams idp IDSRV
2016-06-15 12:04:56.066 -05:00 [Debug] Cliams auth_time 1466010295
2016-06-15 12:04:56.066 -05:00 [Debug] Cliams ticket fc05cd84-7756-4ec5-ac3c-53ac6d4d5e2a
2016-06-15 12:04:56.338 -05:00 [Debug] The requseted claims...
2016-06-15 12:04:56.338 -05:00 [Debug] Cliams sub
2016-06-15 12:04:56.338 -05:00 [Debug] Finished ProfileDataAsync
2016-06-15 12:04:56.338 -05:00 [Debug] Creating JWT identity token
2016-06-15 12:04:56.344 -05:00 [Debug] Adding client "apphybrid" to client list cookie for subject "783bf872-b864-4042-853d-04fbcb7a505a"
2016-06-15 12:04:56.349 -05:00 [Information] End authorize request
2016-06-15 12:04:56.352 -05:00 [Information] Posting to http://localhost/app/Login/Login.mr
2016-06-15 12:04:56.352 -05:00 [Debug] Using AssetManager to render authorization response html
2016-06-15 12:04:56.388 -05:00 [Debug] Incoming request: /securetoken/assets/app.FormPostResponse.js
//Web
2016-06-15 12:04:56,422 [16] DEBUG app.Web.IdentityServer.IdentityServerClient Triggered MessageReceivedNotification`2 notification
2016-06-15 12:04:56,426 [16] DEBUG app.Web.IdentityServer.IdentityServerClient Triggered SecurityTokenReceivedNotification`2 notification
2016-06-15 12:04:56,487 [16] DEBUG app.Web.IdentityServer.IdentityServerClient Triggered SecurityTokenValidated notification
2016-06-15 12:04:56,487 [16] DEBUG app.Web.IdentityServer.IdentityServerClient The Claims in the identity
2016-06-15 12:04:56,488 [16] DEBUG app.Web.IdentityServer.IdentityServerClient Claims: iss http://localhost/OAuth2Server/securetoken
2016-06-15 12:04:56,488 [16] DEBUG app.Web.IdentityServer.IdentityServerClient Claims: aud apphybrid
2016-06-15 12:04:56,488 [16] DEBUG app.Web.IdentityServer.IdentityServerClient Claims: exp 1466010416
2016-06-15 12:04:56,488 [16] DEBUG app.Web.IdentityServer.IdentityServerClient Claims: nbf 1466010296
2016-06-15 12:04:56,488 [16] DEBUG app.Web.IdentityServer.IdentityServerClient Claims: nonce 636016067018002117.MWY4MGVjOWItYTFjYS00MTVlLTg4MDYtMjYxYjkwMWEzNzU4ZWViNzEyNTQtMjE0Mi00MjYzLTk2ZjMtODdhYmIxYTM5Mjg5
2016-06-15 12:04:56,488 [16] DEBUG app.Web.IdentityServer.IdentityServerClient Claims: iat 1466010296
2016-06-15 12:04:56,488 [16] DEBUG app.Web.IdentityServer.IdentityServerClient Claims: at_hash 6pIu3P1cEeTQJMcK8Gcnhw
2016-06-15 12:04:56,488 [16] DEBUG app.Web.IdentityServer.IdentityServerClient Claims: c_hash VsSw9HC0xyodlSkSCZefLw
2016-06-15 12:04:56,488 [16] DEBUG app.Web.IdentityServer.IdentityServerClient Claims: sid e79cd97a339b4513b45038e7755c1b88
2016-06-15 12:04:56,488 [16] DEBUG app.Web.IdentityServer.IdentityServerClient Claims: sub 783bf872-b864-4042-853d-04fbcb7a505a
2016-06-15 12:04:56,488 [16] DEBUG app.Web.IdentityServer.IdentityServerClient Claims: auth_time 1466010295
2016-06-15 12:04:56,488 [16] DEBUG app.Web.IdentityServer.IdentityServerClient Claims: idp IDSRV
2016-06-15 12:04:56,488 [16] DEBUG app.Web.IdentityServer.IdentityServerClient Claims: amr password
2016-06-15 12:04:56,488 [16] DEBUG app.Web.IdentityServer.IdentityServerClient The access token: [Omitted]
2016-06-15 12:04:56,488 [16] DEBUG app.Web.IdentityServer.IdentityServerClient The id token: [Omitted]
2016-06-15 12:04:56,491 [16] DEBUG app.Web.IdentityServer.IdentityServerClient Triggered AuthenticationFailedNotification`2 notification
//Web
//Logs
有问题的日志输出...
2016-06-15 12:04:55.412 -05:00 [Information] Creating Implicit Flow response.
2016-06-15 12:04:55.416 -05:00 [Debug] Creating access token
2016-06-15 12:04:55.424 -05:00 [Debug] Getting ProfileDataAsync
2016-06-15 12:04:55.436 -05:00 [Debug] The claims in the context...
2016-06-15 12:04:55.437 -05:00 [Debug] Cliams sub 783bf872-b864-4042-853d-04fbcb7a505a
2016-06-15 12:04:55.437 -05:00 [Debug] Cliams name dev.guser
2016-06-15 12:04:55.437 -05:00 [Debug] Cliams amr password
2016-06-15 12:04:55.437 -05:00 [Debug] Cliams idp IDSRV
2016-06-15 12:04:55.437 -05:00 [Debug] Cliams auth_time 1466010295
2016-06-15 12:04:55.437 -05:00 [Debug] Cliams ticket fc05cd84-7756-4ec5-ac3c-53ac6d4d5e2a <- Has the claim I want
2016-06-15 12:04:55.975 -05:00 [Debug] The requseted claims...
2016-06-15 12:04:55.976 -05:00 [Debug] Requested Claims Is Null <- but this needs to indicate that we want that claim...
2016-06-15 12:04:55.976 -05:00 [Debug] Finished ProfileDataAsync
【问题讨论】:
【参考方案1】:更新 2:好的,现在我仔细观察,你有 IncludeAllClaimsForUser = true
。在 GetProfileData 上下文中有一个类似的标志。我怀疑这就是为什么您在集合中没有声明。
更新 1:您想要进入令牌的声明应添加到 GetProfile
而不是 AuthentivcateLocal
方法的 AuthenticateResult
中。
原文:将作用域的类型从Identity
更改为Resource
。这会影响声明进入哪些令牌。
【讨论】:
作用域类型是Resource
,对于AppAccess
作用域
啊,我在看 App 范围。
已更新以回答问题。
感谢您的更新,我知道这些声明应该添加到 GetProfile()
但我想尊重 RequestedClaims
框架,而不是一直包含声明。问题是当我从 IdSrv 内部点击 UserInfo 端点时(当它开始构建令牌时)RequestedClaims
列表为空。我可以一直添加Ticket
声明,但这违背了拥有此端点的目的......
我编辑了问题以使问题中的日志更加可见以上是关于如何将声明包含到从授权端点检索的访问令牌中?的主要内容,如果未能解决你的问题,请参考以下文章
如何让我的 Auth0 权限进入 AWS HTTP API Jwt 授权方的访问令牌的范围声明?