[英]OpenIddict Samples - Add 'unique-name' to the id_token
我正在使用 OpenIddict-Samples 的 RefreshFlow 示例。 它工作得很好。 我注意到在 Angular 模型中有一個 ProfileModel 是從 id_token 的 JWT_Decode 填充的:
export interface ProfileModel {
sub: string;
jti: string;
useage: string;
at_hash: string;
nbf: number;
exp: number;
iat: number;
iss: string;
unique_name: string;
email_confirmed: boolean;
role: string[];
}
我看不到在服務器上的何處填充了 unique_name。 我對此字段有要求,並嘗試在此處應用該值:
[HttpPost("~/connect/token"), Produces("application/json")]
public async Task<IActionResult> Exchange([ModelBinder(typeof(OpenIddictMvcBinder))] OpenIdConnectRequest request)
{
if (request.IsPasswordGrantType())
{
var user = await _userManager.FindByNameAsync(request.Username);
if (user == null)
{
return BadRequest(new OpenIdConnectResponse
{
Error = OpenIdConnectConstants.Errors.InvalidGrant,
ErrorDescription = "The username/password couple is invalid."
});
}
// Validate the username/password parameters and ensure the account is not locked out.
var result = await _signInManager.CheckPasswordSignInAsync(user, request.Password, lockoutOnFailure: true);
if (!result.Succeeded)
{
return BadRequest(new OpenIdConnectResponse
{
Error = OpenIdConnectConstants.Errors.InvalidGrant,
ErrorDescription = "The username/password couple is invalid."
});
}
var properties = new AuthenticationProperties(new Dictionary<string, string>
{
{ "unique_name", "hello World!" }
});
// Create a new authentication ticket.
var ticket = await CreateTicketAsync(request, user, properties);
return SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme);
}
這是我需要添加的地方嗎? 我之前使用 JwtSecureDataFormat : ISecureDataFormat 推出了我自己的令牌創建者,並將該字段添加為屬性。
如何使用 OpenIddict/ASOS 添加它?
謝謝!
所以我想出了如何實現我最想要的!!
我真的不需要專門向令牌添加“unique_name”,而只需添加比標准身份框架為您添加的聲明更多的聲明。
我是這樣做的:
創建自定義 SignInManager:
public class OpenIdictSignInManager<TUser> : SignInManager<TUser> where TUser : IdentityUser
{
public OpenIdictSignInManager(
UserManager<TUser> userManager,
IHttpContextAccessor contextAccessor,
IUserClaimsPrincipalFactory<TUser> claimsFactory,
IOptions<IdentityOptions> optionsAccessor,
ILogger<SignInManager<TUser>> logger,
IAuthenticationSchemeProvider schemes) : base(userManager,
contextAccessor,
claimsFactory,
optionsAccessor,
logger,
schemes)
{
}
public override async Task<ClaimsPrincipal> CreateUserPrincipalAsync(TUser user)
{
var principal = await base.CreateUserPrincipalAsync(user);
var identity = (ClaimsIdentity)principal.Identity;
identity.AddClaim(new Claim(OpenIdConnectConstants.Claims.EmailVerified, user.EmailConfirmed.ToString().ToLower()));
return principal;
}
}
然后將新的 SignInManager 應用到 startup.cs 配置:
// Register the Identity services.
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders()
.AddSignInManager<OpenIdictSignInManager<ApplicationUser>>();
然后在 AuthorizationController 中創建票證時添加了一個聲明目的地:
// Note: by default, claims are NOT automatically included in the access and identity tokens.
// To allow OpenIddict to serialize them, you must attach them a destination, that specifies
// whether they should be included in access tokens, in identity tokens or in both.
foreach (var claim in ticket.Principal.Claims)
{
// Never include the security stamp in the access and identity tokens, as it's a secret value.
if (claim.Type == _identityOptions.Value.ClaimsIdentity.SecurityStampClaimType)
{
continue;
}
var destinations = new List<string>();
// Identity Token destinations only
if (new List<string>
{
OpenIdConnectConstants.Claims.EmailVerified
}.Contains(claim.Type))
{
destinations.Add(OpenIdConnectConstants.Destinations.IdentityToken);
claim.SetDestinations(destinations);
continue;
}
destinations.Add(OpenIdConnectConstants.Destinations.AccessToken);
// Only add the iterated claim to the id_token if the corresponding scope was granted to the client application.
// The other claims will only be added to the access_token, which is encrypted when using the default format.
if ((claim.Type == OpenIdConnectConstants.Claims.Name && ticket.HasScope(OpenIdConnectConstants.Scopes.Profile)) ||
(claim.Type == OpenIdConnectConstants.Claims.Email && ticket.HasScope(OpenIdConnectConstants.Scopes.Email)) ||
(claim.Type == OpenIdConnectConstants.Claims.Role && ticket.HasScope(OpenIddictConstants.Claims.Roles)))
{
destinations.Add(OpenIdConnectConstants.Destinations.IdentityToken);
}
claim.SetDestinations(destinations);
}
我花了幾天的時間研究代碼和谷歌搜索來提出這種方法,所以我想我會分享並希望它可以幫助其他人:)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.