首页 > 解决方案 > 手动创建和验证 JWT 令牌

问题描述

我正在使用 IdentityServer4工具手动创建令牌:

var token = await _tools.IssueClientJwtAsync(
   clientId: "client_id",
   lifetime: lifetimeInSeconds,
   audiences: new[] { TokenHelper.Audience },
   additionalClaims:new [] { new Claim("some_id", "1234") }
);

我想知道是否有办法(使用 IdentityServer4 已有的)来手动解码和验证令牌。

要立即解码令牌,我正在使用 JwtSecurityTokenHandler (System.IdentityModel.Tokens.Jwt):

var handler = new JwtSecurityTokenHandler();
var tokenDecoded = handler.ReadJwtToken(token);

这很简单,所以如果 IdentityServer4 没有等价物,我很乐意保留它。

更重要的是令牌的验证。我找到并改编了这个可以完成工作的示例。这是来自 Github 的代码:

const string auth0Domain = "https://jerrie.auth0.com/"; // Your Auth0 domain
const string auth0Audience = "https://rs256.test.api"; // Your API Identifier
const string testToken = ""; // Obtain a JWT to validate and put it in here

   // Download the OIDC configuration which contains the JWKS
   // NB!!: Downloading this takes time, so do not do it very time you need to validate a token, Try and do it only once in the lifetime
   //  of your application!!
IConfigurationManager<OpenIdConnectConfiguration> configurationManager = new ConfigurationManager<OpenIdConnectConfiguration>($"{auth0Domain}.well-known/openid-configuration", new OpenIdConnectConfigurationRetriever());
OpenIdConnectConfiguration openIdConfig = AsyncHelper.RunSync(async () => await configurationManager.GetConfigurationAsync(CancellationToken.None));

// Configure the TokenValidationParameters. Assign the SigningKeys which were downloaded from Auth0. 
// Also set the Issuer and Audience(s) to validate
TokenValidationParameters validationParameters =
    new TokenValidationParameters
    {
        ValidIssuer = auth0Domain,
        ValidAudiences = new[] { auth0Audience },
        IssuerSigningKeys = openIdConfig.SigningKeys
    };

// Now validate the token. If the token is not valid for any reason, an exception will be thrown by the method
SecurityToken validatedToken;
JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
var user = handler.ValidateToken(testToken, validationParameters, out validatedToken);

// The ValidateToken method above will return a ClaimsPrincipal. Get the user ID from the NameIdentifier claim
// (The sub claim from the JWT will be translated to the NameIdentifier claim)
Console.WriteLine($"Token is validated. User Id {user.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value}");

上面的代码正在完成这项工作。我只是想知道 IdentityServer4 是否已经有一些“更简单”的东西,只是像上面的代码那样进行令牌验证。

标签: identityserver4

解决方案


您正在尝试做的是称为令牌委托,您可以Extension Grants在 IDS 上使用它来实现它。这是来自文档的示例代码

public class DelegationGrantValidator : IExtensionGrantValidator
{
    private readonly ITokenValidator _validator;

    public DelegationGrantValidator(ITokenValidator validator)
    {
        _validator = validator;
    }

    public string GrantType => "delegation";

    public async Task ValidateAsync(ExtensionGrantValidationContext context)
    {
        var userToken = context.Request.Raw.Get("token");

        if (string.IsNullOrEmpty(userToken))
        {
            context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant);
            return;
        }

        var result = await _validator.ValidateAccessTokenAsync(userToken);
        if (result.IsError)
        {
            context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant);
            return;
        }

        // get user's identity
        var sub = result.Claims.FirstOrDefault(c => c.Type == "sub").Value;
        
        //Generate a new token manually if needed 
        //Call another API is needed 

        context.Result = new GrantValidationResult(sub, GrantType);
        return;
    }
}

令牌验证是使用ITokenValidator上面的代码完成的,你也可以在手动验证中使用这个验证器。

是另一个例子。


推荐阅读