2016-02-26 140 views
3

我有id_token和JsonWebKeys的access_token(JWK)。然後我從/ token url獲得我的id_token。 如何在C#中使用JWK驗證此JWT id_token。驗證令牌JWT在C#中使用JWK

不用說,我已經試過幾乎所有的東西,但(IdenityModels.Jwt等),但JwtSecurityTokenHandler不採取JsonWebKey。 我使用RS512作爲簽名算法。

回答

5

我只是這個實現自己的谷歌IdToken審定:

var parameters = new TokenValidationParameters 
{ 
    ... 
    IssuerSigningKeyResolver = await keyProvider.GetIssuerSigningKeyResolverAsync(cancellationToken), 
}; 

SecurityToken token; 
var handler = new JwtSecurityTokenHandler(); 
var principal = handler.ValidateToken(source, parameters, out token); 

keyProvider是:

public class GoogleOAuth2KeyProvider 
{ 
    private readonly IGoogleAuthConfiguration configuration; 
    private Jwk lastCertResponse; 
    private DateTimeOffset lastCertExpires; 

    public GoogleOAuth2KeyProvider(IGoogleAuthConfiguration configuration) 
    { 
     this.configuration = configuration; 
    } 

    public async Task<IssuerSigningKeyResolver> GetIssuerSigningKeyResolverAsync(CancellationToken cancellationToken) 
    { 
     await UpdateCert(cancellationToken); 

     var keys = lastCertResponse.Keys 
      .Where(key => key.Kty == "RSA" && key.Use == "sig") 
      .ToDictionary(key => key.Kid, StringComparer.InvariantCultureIgnoreCase); 
     return new IssuerSigningKeyResolver((token, securityToken, keyIdentifier, tokenValidationParameters) => 
     { 
      foreach (var keyIdentifierClause in keyIdentifier) 
      { 
       Jwk.KeysData key; 
       if (!keys.TryGetValue(keyIdentifierClause.Id, out key)) 
       { 
        continue; 
       } 
       var rsa = RSA.Create(); 
       rsa.ImportParameters(new RSAParameters 
       { 
        Exponent = Base64UrlEncoder.DecodeBytes(key.E), 
        Modulus = Base64UrlEncoder.DecodeBytes(key.N), 
       }); 
       return new RsaSecurityKey(rsa); 
      } 
      return null; 
     }); 
    } 

    private async Task UpdateCert(CancellationToken cancellationToken) 
    { 
     if (lastCertResponse != null && DateTimeOffset.UtcNow < lastCertExpires) 
     { 
      return; 
     } 
     var initializer = new BaseClientService.Initializer 
     { 
      ApiKey = configuration.ServerApiKey, 
     }; 
     using (var service = new Oauth2Service(initializer)) 
     { 
      lastCertResponse = await service.GetCertForOpenIdConnect().ExecuteAsync(cancellationToken); 
      lastCertExpires = DateTimeOffset.UtcNow.AddHours(12); 
     } 
    } 
} 

RSA等只是System.Security.Cryptography,而Base64UrlEncoderSystem.IdentityModel(但很容易的自己動手做)

不幸的是,它看起來並不像other kty/alg values一樣容易支持,例如有沒有ECDsa.ImportParameters(),它想從byte[]通用CngKey,所以有人做一個普通的.NET JWK庫將不得不收拾xy PARAMS自己,大概。