2017-11-05 2 views
1

모든 OpenID Connect 제공 업체는 jwks_uri 속성이 포함 된 검색 문서를 게시합니다. jwks_uri에서 반환 된 데이터는 두 가지 다른 형식을 취하는 것으로 보입니다. 하나의 양식에는 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.TokenValidationParameters과 같은 클래스를 사용할 경우 주어진 정보를 사용하여 IssuerSigningKey을 어떻게 제공합니까? 이 클래스의 샘플 사용은 내가 내가 액세스 토큰의 유효성을 검사 할 수있는 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

이것은 내가 함께가는 끝난 것입니다. 요청은 위의 객체를 적절히 채 웁니다. I 다음 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

RSA 공개 키는 것입니다 항상 ne (거의 모든 키에 대한 AQAB 즉 65,537 공개 지수) (값 RSA로) 적어도 회원 kty가 포함되어 있습니다.

기타 구성원은 선택 사항이며 키에 대한 정보를 제공하는 데 사용됩니다. 일반적으로 , 당신은 다음과 같은 권장 멤버를 찾을 수 :

  • 의 ID (kid),
  • 가 (서명 또는 암호화)
  • 그들이 당신의 예제 (RS256을 위해 설계되었습니다 어떤 알고리즘을 사용하는 방법).

키가 X.509 인증서에서 오는 경우 또는 x5t#256 (각각 sha1 및 sha256 인증서 썸 프린트)을 자주 볼 수 있습니다. 일부 시스템에서는 JWK를 직접 사용할 수 없으며 PKCS # 1 키가 제공됩니다 (x5c 구성원).

커플 (n, e) 또는 x5c (제공된 경우) 커플을 사용할 수 있습니다. 사용하는 라이브러리/타사 응용 프로그램의 기능에 따라 다릅니다.

//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; } 
} 

내가 먼저 오픈 ID 연결 발견 문서에서 제공되는 jwks_uri 엔드 포인트에 요청합니다