Identity Server 4 自定义令牌端点,在运行时获取签名凭证

Identity Server 4 custom token endpoint, get signingcredential at runtime

我正在为我的 identityserver4 项目实现自定义令牌端点。目标是根据更复杂的凭据模型(与 Identity Server 的内置“client/scope”概念不同的用户数据库)的验证来颁发令牌,并颁发带有额外声明的 Jwt 令牌以帮助用户身份和我自定义的访问权限 api.

我的代码是这样的:

[HttpPost]
    public IActionResult GetCustomApiToken(CustomUserCredentialsModel credentials)
    {

        var customUser = GetCustomValidatedUser(credentials); //validate user from DB


        var tokenHandler = new JwtSecurityTokenHandler();
        var key = Encoding.ASCII.GetBytes(ApplicationSettings.SigningKey); // <--- DeveloperSigningCredential ???
        var tokenDescriptor = new SecurityTokenDescriptor
        {
            Subject = new ClaimsIdentity(new[] { new Claim("user", customUser.ToString()) /* extra custom claims */ }),
            Issuer = "my identity server",
            Audience = "my custom api", 
            Expires = DateTime.UtcNow.AddDays(1),
            SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
        };
        var token = tokenHandler.CreateToken(tokenDescriptor);
        return Ok(tokenHandler.WriteToken(token));

    }

请注意,我还没有完全测试上面的内容,但是如果密钥在 ApplicationSettings 中进行管理,类似的东西应该可以在生产环境中使用。 但它不会在通过 Identity Server 4 的 AddDeveloperSigningCredential() 扩展添加签名密钥的开发中工作。

一种解决方案是在所有 Dev/Test 环境(= 麻烦)的配置中添加 SigningCredentials。

我能否在运行时解析签名凭据(因为它们在 Program/Startup 中设置)?

(此外,是的,我知道:不要在 appSettings 中存储可读的签名密钥,请忽略上面示例中的内容。)

好的,我明白了,您可以注入 ISigningCredentialStore 单例并从那里解析 signingCredential:

    private readonly ISigningCredentialStore _signingCredentialStore;
    
    public CustomTokenController(ISigningCredentialStore signingCredentialStore)
    {
       
        _signingCredentialStore = signingCredentialStore ?? throw new ArgumentNullException(nameof(signingCredentialStore));
    }   

    [HttpPost]
    public async Task<IActionResult> GetCustomApiToken(CustomUserCredentialsModel credentials)
    {

        var userId = GetCustomValidatedUser(credentials); 
        if (userId == null) return Unauthorized();

        var signingCredentials = await _signingCredentialStore.GetSigningCredentialsAsync();
        var tokenHandler = new JwtSecurityTokenHandler();
        var tokenDescriptor = new SecurityTokenDescriptor
        {
            Subject = new ClaimsIdentity(new[] { new Claim("userId", userId.ToString()) /* extra custom claims */ }),
            Issuer = "my IdentityServer",
            IssuedAt = DateTime.UtcNow,
            Audience = "my api",
            Expires = DateTime.UtcNow.AddDays(1),
            SigningCredentials = signingCredentials 
        };
        var token = tokenHandler.CreateToken(tokenDescriptor);
        return Ok(tokenHandler.WriteToken(token));

    }

这对我有用,生成的 Jwt 令牌可以像内置“connect/token”端点发出的任何令牌一样进行验证。