2017-03-22 38 views
3

我試圖驗證以下測試智威湯遜,選擇的關鍵是「私人」,我可以成功地驗證它https://jwt.io驗證JWT與微軟的IdentityModel

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIyNzFjNmFkYjNhYTk1YTIxZWI3ZTljMTE2OGViNjI2YiIsImlhdCI6MTQ5MDE5NzQ2MCwibmJmIjoxNDkwMTk3NDYwLCJleHAiOjE0OTAyMDEwNjAsIklwIjoiNzkuMjMxLjczLjE1NCIsIk1lbWJlcklkIjoxfQ.P3m7RkXJ9TUiUFJ2bbtiyoL7OXaD7ITq_LsWMCRJj04 

好像微軟改變了JwtSecurityTokenhandler()類和文檔不是最新的。我檢查了一些使用new InMemorySymetricSecurityKey()的教程和gitpages,但這個類不再存在。

NuGet包:安裝,包裝System.IdentityModel.Tokens.Jwt(5.1.3版本)。

我創建了一個簡單的控制檯應用程序,我嘗試驗證給定的JWT,但我不知道如何指定TokenValidationParameters。

static void Main(string[] args) 
{ 
    var key = "private"; 
    var jwt = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIyNzFjNmFkYjNhYTk1YTIxZWI3ZTljMTE2OGViNjI2YiIsImlhdCI6MTQ5MDE5NzQ2MCwibmJmIjoxNDkwMTk3NDYwLCJleHAiOjE0OTAyMDEwNjAsIklwIjoiNzkuMjMxLjczLjE1NCIsIk1lbWJlcklkIjoxfQ.P3m7RkXJ9TUiUFJ2bbtiyoL7OXaD7ITq_LsWMCRJj04"; 

    var tokenHandler = new JwtSecurityTokenHandler(); 
    var securityToken = tokenHandler.ReadToken(jwt); 
    var validationParameters = new TokenValidationParameters {IssuerSigningKey = new InMemorySymetricSecurityKey()}; 
    SecurityToken validated; 
    tokenHandler.ValidateToken(jwt, validationParameters, out validated); 

    Console.WriteLine(validated.ToString()); 
} 
+0

我已經通過使用jose-jwt解決了我的問題,這非常簡單。 – kentor

回答

1

[參見下面更新]

這取決於誰簽署了JWT令牌。通常情況下,發佈令牌的授權服務器會使用其簽名憑證的公鑰來發布元數據。

您的代碼可以下載元數據並使用公鑰驗證令牌。例如,Azure AD發佈其簽名密鑰here

您可以使用此代碼來驗證由Azure AD發佈的JWT令牌。

var jwtToken = "<JWT TOKEN>"; 
var url = "https://login.windows.net/common/federationmetadata/2007-06/federationmetadata.xml"; 
var serializer = new MetadataSerializer(); 
MetadataBase metadata = serializer.ReadMetadata(XmlReader.Create(url)); 

var entityDescriptor = (EntityDescriptor)metadata; 
var securityTokens = new List<X509SecurityToken>(); 
var descriptor = entityDescriptor.RoleDescriptors.OfType<SecurityTokenServiceDescriptor>().First(); 

var x509DataClauses = descriptor.Keys.Where(key => key.KeyInfo != null && 
              (key.Use == KeyType.Signing || key.Use == KeyType.Unspecified)) 
            .Select(key => key.KeyInfo.OfType<X509RawDataKeyIdentifierClause>().First()); 

securityTokens.AddRange(x509DataClauses.Select(token => new X509SecurityToken(new X509Certificate2(token.GetX509RawData())))); 

var validationParameters = new TokenValidationParameters 
{ 
    IssuerSigningTokens = securityTokens, 
    CertificateValidator = X509CertificateValidator.ChainTrust, 
}; 
SecurityToken validatedToken; 
ClaimsPrincipal claimsPrincipal = tokenHandler.ValidateToken(jwtToken, validationParameters, out validatedToken); 

UPDATE: 我誤解你的問題,錯過了你指定的對稱密鑰的字面意義。你應該可以使用這樣一個SymmetricSecurityKey

HMACSHA256 hmac = new HMACSHA256(Encoding.ASCII.GetBytes(key)); 

var validationParameters = new TokenValidationParameters 
{ 
    IssuerSigningKey = new SymmetricSecurityKey(hmac.Key); 
}; 
+1

JWT令牌已從使用PHP編碼的網站發佈。當我去jwt.io時,我可以粘貼我的JWT並根據密鑰進行驗證。我期待C#庫類似的東西很容易。我認爲你的代碼片段顯示了完全不同的東西或? – kentor

+0

您在jwt.io中獲得的是JWT令牌的解碼。 JWT令牌包含3個base64編碼的部分。如果您將令牌粘貼到jwt.io站點,它會在底部顯示「無效簽名」,因爲它無法驗證沒有簽名密鑰公鑰的令牌。 – MvdD

+0

JwtSecurityTokenHandler.ValidateToken方法試圖驗證令牌的真實性,即簽名是否有效,因此令牌可以被信任。可信表示該令牌是由您期望的授權服務器(iss聲明)發出的,旨在用於您的服務(aud聲明)並且在有效時間範圍內(nbf&exp聲明)。它也保證令牌不被修改。 – MvdD