Microsoft.IdentityModel.Tokens: 添加额外声明
Microsoft.IdentityModel.Tokens: Add additonal claims
背景
出于 authn/z 目的,我们使用 JOSE-JWT 创建 JWT 令牌。此令牌通过 Authorize: Bearer HTTP header 传递给不同的微服务以模拟调用者。
微服务本身利用 Microsoft.IdentityModel.Tokens 来验证 JWT 令牌:
using System;
using System.Text;
using Microsoft.IdentityModel.Tokens;
using Microsoft.AspNetCore.Builder;
// The key length needs to be of sufficient length, or otherwise an error will occur.
var tokenSecretKey = Encoding.UTF8.GetBytes(Configuration["TokenSecretKey"]);
var tokenValidationParameters = new TokenValidationParameters
{
// Token signature will be verified using a private key.
ValidateIssuerSigningKey = true,
RequireSignedTokens = true,
IssuerSigningKey = new SymmetricSecurityKey(tokenSecretKey),
// Token will only be valid if contains "accelist.com" for "iss" claim.
ValidateIssuer = true,
ValidIssuer = "accelist.com",
// Token will only be valid if contains "accelist.com" for "aud" claim.
ValidateAudience = true,
ValidAudience = "accelist.com",
// Token will only be valid if not expired yet, with 5 minutes clock skew.
ValidateLifetime = true,
RequireExpirationTime = true,
ClockSkew = new TimeSpan(0, 5, 0),
ValidateActor = false,
};
app.UseJwtBearerAuthentication(new JwtBearerOptions
{
AutomaticAuthenticate = true,
TokenValidationParameters = tokenValidationParameters,
});
某些 JWT 保留声明将自动填充到 HttpContext.User,即
问题
是否有一种简单而优雅的方法可以将 其他自定义 声明填充到 HttpContext.User 中?目前我能想到的唯一方法是解码令牌并调用 HttpContext.User.Claims.Add(...).
提前致谢!
不是解码令牌并添加您的 custom claims
,而是动态地对 user
和 custom
声明进行 Union
,例如:
private async Task<JwtSecurityToken> GetJwtSecurityToken(ApplicationUser user)
{
//Get the user claims
var userClaims = await _userManager.GetClaimsAsync(user);
//Merge the claims here
return new JwtSecurityToken(
issuer: "", //Insert your issuer
audience: "",//Insert your audience
claims: GetTokenClaims(user).Union(userClaims), //This is the Union you need
expires: DateTime.UtcNow.AddMinutes(5),//Add expiry time here
signingCredentials: new SigningCredentials(IssuerSigningKey, SecurityAlgorithms.HmacSha256)//Do your magic here
);
}
GetTokenClaims()
方法只会 return 自定义声明列表,例如:
private static IEnumerable<Claim> GetTokenClaims(ApplicationUser user)
{
return new List<Claim>
{
new Claim("UserName", user.UserName),
new Claim("Email", user.Email),
new Claim("FirstName", user.FirstName),
new Claim("LastName", user.LastName),
new Claim("Phone", user.PhoneNumber),
//More custom claims
};
}
最后,您可以将其总结如下:
//Get the token combination
var token = await GetJwtSecurityToken(user);
//Write and return the token
return Ok(new
{
token = new JwtSecurityTokenHandler().WriteToken(token),
expiration = token.ValidTo,
});
背景
出于 authn/z 目的,我们使用 JOSE-JWT 创建 JWT 令牌。此令牌通过 Authorize: Bearer HTTP header 传递给不同的微服务以模拟调用者。
微服务本身利用 Microsoft.IdentityModel.Tokens 来验证 JWT 令牌:
using System;
using System.Text;
using Microsoft.IdentityModel.Tokens;
using Microsoft.AspNetCore.Builder;
// The key length needs to be of sufficient length, or otherwise an error will occur.
var tokenSecretKey = Encoding.UTF8.GetBytes(Configuration["TokenSecretKey"]);
var tokenValidationParameters = new TokenValidationParameters
{
// Token signature will be verified using a private key.
ValidateIssuerSigningKey = true,
RequireSignedTokens = true,
IssuerSigningKey = new SymmetricSecurityKey(tokenSecretKey),
// Token will only be valid if contains "accelist.com" for "iss" claim.
ValidateIssuer = true,
ValidIssuer = "accelist.com",
// Token will only be valid if contains "accelist.com" for "aud" claim.
ValidateAudience = true,
ValidAudience = "accelist.com",
// Token will only be valid if not expired yet, with 5 minutes clock skew.
ValidateLifetime = true,
RequireExpirationTime = true,
ClockSkew = new TimeSpan(0, 5, 0),
ValidateActor = false,
};
app.UseJwtBearerAuthentication(new JwtBearerOptions
{
AutomaticAuthenticate = true,
TokenValidationParameters = tokenValidationParameters,
});
某些 JWT 保留声明将自动填充到 HttpContext.User,即
问题
是否有一种简单而优雅的方法可以将 其他自定义 声明填充到 HttpContext.User 中?目前我能想到的唯一方法是解码令牌并调用 HttpContext.User.Claims.Add(...).
提前致谢!
不是解码令牌并添加您的 custom claims
,而是动态地对 user
和 custom
声明进行 Union
,例如:
private async Task<JwtSecurityToken> GetJwtSecurityToken(ApplicationUser user)
{
//Get the user claims
var userClaims = await _userManager.GetClaimsAsync(user);
//Merge the claims here
return new JwtSecurityToken(
issuer: "", //Insert your issuer
audience: "",//Insert your audience
claims: GetTokenClaims(user).Union(userClaims), //This is the Union you need
expires: DateTime.UtcNow.AddMinutes(5),//Add expiry time here
signingCredentials: new SigningCredentials(IssuerSigningKey, SecurityAlgorithms.HmacSha256)//Do your magic here
);
}
GetTokenClaims()
方法只会 return 自定义声明列表,例如:
private static IEnumerable<Claim> GetTokenClaims(ApplicationUser user)
{
return new List<Claim>
{
new Claim("UserName", user.UserName),
new Claim("Email", user.Email),
new Claim("FirstName", user.FirstName),
new Claim("LastName", user.LastName),
new Claim("Phone", user.PhoneNumber),
//More custom claims
};
}
最后,您可以将其总结如下:
//Get the token combination
var token = await GetJwtSecurityToken(user);
//Write and return the token
return Ok(new
{
token = new JwtSecurityTokenHandler().WriteToken(token),
expiration = token.ValidTo,
});