2016-08-25 403 views
1

我JwtToken這樣創建:JwtToken - 聲明名稱JwtTokenTypes.Subject解析爲ClaimTypes.NameIdentifier,爲什麼是這樣以及如何防止?

 X509Certificate2 cert = certificateStore.Certificate; 

     var now = DateTime.UtcNow; 
     var tokenHandler = new JwtSecurityTokenHandler(); 
     var tokenDescriptor = new SecurityTokenDescriptor() 
     { 
      Subject = new ClaimsIdentity(new[] 
      { 
        new Claim(JwtClaimTypes.Subject, upn), 
        new Claim(REQUEST_TYPE_NAME, requestType), 
        new Claim(DOMAIN_NAME, domain), 
       }), 
      Lifetime = new Lifetime(now, now.AddMinutes(60)), 
      SigningCredentials = new X509SigningCredentials(cert), 
      TokenIssuerName = ISSUER 
     }; 

     SecurityToken token = tokenHandler.CreateToken(tokenDescriptor); 

這是正確的。 Token被創建,它的第一個聲明被命名爲「sub」,它是JwtTokenTypes.Subject的內容。我通過jwt web檢查了它。

問題是,我有解決索賠這個方法:

 if (string.IsNullOrWhiteSpace(token)) throw new MissingTokenException("Token should not be null."); 

     var tokenHandler = new JwtSecurityTokenHandler(); 
     var securityToken = new X509SecurityToken(new X509Certificate2(new X509RawDataKeyIdentifierClause(certificateStore.Certificate).GetX509RawData())); 
     var validationParameters = new TokenValidationParameters() 
     { 
      IssuerSigningToken = securityToken, 
      ValidateAudience = false, 
      ValidateActor = false, 
      ValidIssuer = ISSUER 
     }; 

     SecurityToken securedToken = new JwtSecurityToken(); 
     ClaimsPrincipal claimsPrincipal = tokenHandler.ValidateToken(token, validationParameters, out securedToken); 

     Claim claim = claimsPrincipal.FindFirst(m => string.Equals(m.Type, REQUEST_TYPE_NAME, StringComparison.OrdinalIgnoreCase)); 
     if (claim != null && !string.Equals(claim.Value, requestType, StringComparison.OrdinalIgnoreCase)) 
     { 
      throw new MismatchedTokenException("Token is not of the proper type."); 
     } 

     upn = claimsPrincipal.Claims.FirstOrDefault(m => m.Type.Equals(JwtClaimTypes.Subject) || m.Type.Equals(ClaimTypes.NameIdentifier))?.Value; 

     domain = claimsPrincipal.Claims.FirstOrDefault(m => m.Type.Equals(DOMAIN_NAME))?.Value; 

在該方法的最後,你可以看到我的JwtClaimTypes.Subject,這應該是檢查要求的名稱,併爲ClaimTypes.NameIdentifiew ,它實際上是。

你有什麼想法爲什麼會發生這種轉變或如何防止它們?

回答

3

您需要添加:

JwtSecurityTokenHandler.InboundClaimTypeMap.Clear(); 

掃清了智威湯遜的權利要求的映射。

該映射是爲了使jwt聲明適應.net類型的聲明。 如果您避免使用映射,則需要爲名稱和角色設置聲明類型(如果要使用Identity(IPrincipal.IsInRole或Identity.Name)中的聲明類型))。

創建ClaimsIdentity時,你可以這樣做:

Subject = new ClaimsIdentity(new[] 
    { 
      new Claim(JwtClaimTypes.Subject, upn), 
      new Claim(REQUEST_TYPE_NAME, requestType), 
      new Claim(DOMAIN_NAME, domain), 
     }, "<auth type>", "name", "role"), 

你必須給的authType更改爲類似餅乾,姓名和角色要求名最有可能會是這樣的。

另一個辦法是把它放在令牌認證參數:

var validationParameters = new TokenValidationParameters() 
    { 
     IssuerSigningToken = securityToken, 
     ValidateAudience = false, 
     ValidateActor = false, 
     ValidIssuer = ISSUER, 
     NameClaimType = "name", 
     RoleClaimType = "role" 
    }; 
相關問題