2017-11-05 17 views
1

すべてのOpenID Connectプロバイダは、jwks_uriプロパティを含むディスカバリドキュメントを発行します。 jwks_uriから返されたデータは、2つの異なる形式をとっているようです。 1つのフォームには、x5cx5tというフィールドがあります。この例は次のようになります。C#でOpenID Connect jwks_uriメタデータを正しく消費する方法は?

{ 
    "keys": [ 
     { 
      "kty": "RSA", 
      "use": "sig", 
      "kid": "C61F8F2524D080D0DB0A508747A94C2161DEDAC8", 
      "x5t": "xh-PJSTQgNDbClCHR6lMIWHe2sg", <------ HERE 
      "e": "AQAB", 
      "n": "lueb...", 
      "x5c": [ 
       "MIIC/..." <------ HERE 
      ], 
      "alg": "RS256" 
     } 
    ] 
} 

私が見る他のバージョンでは、x5cとx5tプロパティを省略したがenが含まれています。この例は次のとおりです。私はかなりの差があり、時にはx5c/x5t組み合わせが使用されるが、他の回されている理由、それは単にe/nが何であるかを理解していない

{ 
    "keys": [ 
     { 
      "kty": "RSA", 
      "alg": "RS256", 
      "use": "sig", 
      "kid": "cb11e2f233aee0329a5344570349cddb6b8ff252", 
      "n": "sJ46h...", <------ HERE 
      "e": "AQAB"  <------ HERE 
     } 
    ] 
} 

。さらに、C#のようなクラスを使用する場合Microsoft.IdentityModel.Tokens.TokenValidationParametersIssuerSigningKeyを供給するために与えられた情報をどのように使用するのですか?このクラスの使用例は、私はので、私はアクセストークンを検証することができTokenValidationParameterIssuerSigningKeyを提供するために、それらを使用しない方法を二つの異なるJWKメタデータ形式を考えると

new TokenValidationParameters 
{ 
    ValidateAudience = true, 
    ValidateIssuer = true, 
    ..., 
    IssuerSigningKey = new X509SecurityKey(???) or new JsonWebKey(???) //How to create this based on x5c/x5t and also how to create this based on e and n ? 
} 

のですか?

答えて

1

これは私が一緒に行くことになったものです:

//Model the JSON Web Key Set 
public class JsonWebKeySet 
{ 
    [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore, PropertyName = "keys", Required = Required.Default)] 
    public JsonWebKey[] Keys { get; set; } 
} 


//Model the JSON Web Key object 
public class JsonWebKey 
{ 
    [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore, PropertyName = "kty", Required = Required.Default)] 
    public string Kty { get; set; } 

    [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore, PropertyName = "use", Required = Required.Default)] 
    public string Use { get; set; } 

    [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore, PropertyName = "kid", Required = Required.Default)] 
    public string Kid { get; set; } 

    [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore, PropertyName = "x5t", Required = Required.Default)] 
    public string X5T { get; set; } 

    [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore, PropertyName = "e", Required = Required.Default)] 
    public string E { get; set; } 

    [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore, PropertyName = "n", Required = Required.Default)] 
    public string N { get; set; } 

    [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore, PropertyName = "x5c", Required = Required.Default)] 
    public string[] X5C { get; set; } 

    [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore, PropertyName = "alg", Required = Required.Default)] 
    public string Alg { get; set; } 
} 

私が最初にOpenIDの接続探索ドキュメントで提供されjwks_uriエンドポイントに要求を行います。要求はそれに応じて上記のオブジェクトを設定します。それからGetSecurityKeys方法がそう

private List<SecurityKey> GetSecurityKeys(JsonWebKeySet jsonWebKeySet) 
{ 
     var keys = new List<SecurityKey>(); 

     foreach (var key in jsonWebKeySet.Keys) 
     { 
      if (key.Kty == OpenIdConnectConstants.Rsa) 
      { 
      if (key.X5C != null && key.X5C.Length > 0) 
      { 
       string certificateString = key.X5C[0]; 
       var certificate = new X509Certificate2(Convert.FromBase64String(certificateString)); 

       var x509SecurityKey = new X509SecurityKey(certificate) 
             { 
              KeyId = key.Kid 
             }; 

       keys.Add(x509SecurityKey); 
       } 
       else if (!string.IsNullOrWhiteSpace(key.E) && !string.IsNullOrWhiteSpace(key.N)) 
       { 
        byte[] exponent = Base64Url.Decode(key.E); 
        byte[] modulus = Base64Url.Decode(key.N); 

        var rsaParameters = new RSAParameters 
             { 
              Exponent = exponent, 
              Modulus = modulus 
             }; 

        var rsaSecurityKey = new RsaSecurityKey(rsaParameters) 
             { 
              KeyId = key.Kid 
             }; 

        keys.Add(rsaSecurityKey); 
       } 
       else 
       { 
        throw new PlatformAuthException("JWK data is missing in token validation"); 
       } 
      } 
      else 
      { 
       throw new NotImplementedException("Only RSA key type is implemented for token validation"); 
      } 
     } 

     return keys; 
    } 
ように実装され ClaimsPrincipal

string idToken = "<the id_token that was returned from the Token endpoint>"; 
List<SecurityKey> keys = this.GetSecurityKeys(jsonWebKeySet); 
var parameters = new TokenValidationParameters 
       { 
         ValidateAudience = true, 
         ValidAudience = tokenValidationParams.Audience, 
         ValidateIssuer = true, 
         ValidIssuer = tokenValidationParams.Issuer, 
         ValidateIssuerSigningKey = true, 
         IssuerSigningKeys = keys, 
         NameClaimType = NameClaimType, 
         RoleClaimType = RoleClaimType 
        }; 

var handler = new JwtSecurityTokenHandler(); 
handler.InboundClaimTypeMap.Clear(); 

SecurityToken jwt; 
ClaimsPrincipal claimsPrincipal = handler.ValidateToken(idToken, parameters, out jwt); 

// validate nonce 
var nonceClaim = claimsPrincipal.FindFirst("nonce")?.Value ?? string.Empty; 

if (!string.Equals(nonceClaim, "<add nonce value here>", StringComparison.Ordinal)) 
{ 
     throw new AuthException("An error occurred during the authentication process - invalid nonce parameter"); 
} 

return claimsPrincipal; 

作成方法JsonWebKeySetオブジェクトを渡します

2

A RSA公開鍵は常に最低のメンバーkty(値RSA有する)、neAQABすなわち、ほぼすべてのキーの65537パブリック指数)に含まれています。

他のメンバーはオプションで、キーに関する情報を提供するために使用されます。 一般的には、次の推奨メンバー見つける:彼らはあなたの例では(RS256のために設計されてどのようなアルゴリズム

  • そのID(kid)、
  • (署名や暗号化)、それを使用する方法
  • を)。

鍵はX.509証明書から出たとき、あなたは、多くの場合、(それぞれSHA1とSHA256証明書のサムプリント)x5tまたはx5t#256があります。 一部のシステムでJWKを直接使用することはできず、PKCS#1キーが提供されています(x5cメンバー)。

カップル(ne)、またはx5cメンバー(提供されている場合)のいずれかを使用できます。使用するライブラリ/サードパーティアプリケーションの機能によって異なります。

関連する問題