Для этой проблемы это вызвано тем, что IdentityServer4
не добавил JwtClaimTypes.Name
в access_token. Если вы проверите access_token из веб-браузера, вы обнаружите, что он пропускает "name": "Tom",
узел.
Для временного решения вы можете реализовать свой собственный ITokenService
как
public class CustomTokenService : DefaultTokenService
{
public CustomTokenService(IClaimsService claimsProvider
, IReferenceTokenStore referenceTokenStore
, ITokenCreationService creationService
, IHttpContextAccessor contextAccessor
, ISystemClock clock
, IKeyMaterialService keyMaterialService
, ILogger<DefaultTokenService> logger)
: base(claimsProvider, referenceTokenStore, creationService, contextAccessor, clock, keyMaterialService, logger)
{
}
public override async Task<Token> CreateAccessTokenAsync(TokenCreationRequest request)
{
Logger.LogTrace("Creating access token");
request.Validate();
var claims = new List<Claim>();
claims.AddRange(await ClaimsProvider.GetAccessTokenClaimsAsync(
request.Subject,
request.Resources,
request.ValidatedRequest));
if (request.ValidatedRequest.Client.IncludeJwtId)
{
claims.Add(new Claim(JwtClaimTypes.JwtId, CryptoRandom.CreateUniqueId(16)));
}
claims.Add(new Claim(JwtClaimTypes.Name, request.Subject.GetDisplayName()));
var issuer = Context.HttpContext.GetIdentityServerIssuerUri();
var token = new Token(OidcConstants.TokenTypes.AccessToken)
{
CreationTime = Clock.UtcNow.UtcDateTime,
Issuer = issuer,
Lifetime = request.ValidatedRequest.AccessTokenLifetime,
Claims = claims.Distinct(new ClaimComparer()).ToList(),
ClientId = request.ValidatedRequest.Client.ClientId,
AccessTokenType = request.ValidatedRequest.AccessTokenType
};
foreach (var api in request.Resources.ApiResources)
{
if (!string.IsNullOrWhiteSpace(api.Name))
{
token.Audiences.Add(api.Name);
}
}
return token;
}
}
, а затем зарегистрироватьсяCustomTokenService
до настройки удостоверения
public void ConfigureServices(IServiceCollection services)
{
services.TryAddTransient<ITokenService, CustomTokenService>();
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<ApplicationUser>()
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddIdentityServer()
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
services.AddAuthentication()
.AddIdentityServerJwt();
}
Для простого способа вы можете попробовать переопределить DefaultClaimsService.GetStandardSubjectClaims
как
public class CustomClaimsService : DefaultClaimsService
{
public CustomClaimsService(IProfileService profile
, ILogger<DefaultClaimsService> logger) : base(profile, logger)
{
}
protected override IEnumerable<Claim> GetStandardSubjectClaims(ClaimsPrincipal subject)
{
var claims = base.GetStandardSubjectClaims(subject);
var newClaims = new List<Claim>(claims)
{
new Claim(JwtClaimTypes.Name, subject.Identity.Name)
};
return newClaims;
}
}
и зарегистрироваться как
public void ConfigureServices(IServiceCollection services)
{
services.TryAddTransient<IClaimsService, CustomClaimsService>();
//services.TryAddTransient<ITokenService, CustomTokenService>();
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<ApplicationUser>()
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddIdentityServer()
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
services.AddAuthentication()
.AddIdentityServerJwt();
}