我正在尝试验证以下测试JWT,所选择的密钥是私有的'我可以在https://jwt.io
上成功验证它eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIyNzFjNmFkYjNhYTk1YTIxZWI3ZTljMTE2OGViNjI2YiIsImlhdCI6MTQ5MDE5NzQ2MCwibmJmIjoxNDkwMTk3NDYwLCJleHAiOjE0OTAyMDEwNjAsIklwIjoiNzkuMjMxLjczLjE1NCIsIk1lbWJlcklkIjoxfQ.P3m7RkXJ9TUiUFJ2bbtiyoL7OXaD7ITq_LsWMCRJj04
似乎Microsoft已经更改了JwtSecurityTokenhandler()类,文档并不是最新的。我检查了一些使用new InMemorySymetricSecurityKey()
的教程和gitpages,但这个类不再存在了。
Nuget Package: Install-Package 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 :(得分:2)
[请参阅下面的更新]
这取决于谁签署了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);
<强>更新强>
我误读了你的问题而错过了你指定对称密钥的字面值。你应该可以使用这样的SymmetricSecurityKey
:
HMACSHA256 hmac = new HMACSHA256(Encoding.ASCII.GetBytes(key));
var validationParameters = new TokenValidationParameters
{
IssuerSigningKey = new SymmetricSecurityKey(hmac.Key);
};
答案 1 :(得分:0)
如果您拥有身份提供者提供的元数据,则可以使用以下代码从元数据中获取密钥并验证令牌,
static string _issuer = string.Empty;
static List<X509SecurityToken> _signingTokens = null;
var stsMetadataAddress = "Your Metadata URL";
static string _audience = "your Audience URL"; //app id
GetTenantInformation(stsMetadataAddress, out issuer, out signingTokens);
Microsoft.IdentityModel.Tokens.SecurityKey key = new
X509SecurityKey(signingTokens.FirstOrDefault().Certificate);
TokenValidationParameters validationParameters = new TokenValidationParameters
{
ValidAudience = _audience,
ValidIssuer = issuer,
IssuerSigningKey = key
};
以下是从元数据中获取签名令牌和发行人信息的方法,
static void GetTenantInformation(string metadataAddress, out string issuer, out List<X509SecurityToken> signingTokens)
{
signingTokens = new List<X509SecurityToken>();
// The issuer and signingTokens are cached for 24 hours. They are updated if any of the conditions in the if condition is true.
if (DateTime.UtcNow.Subtract(_stsMetadataRetrievalTime).TotalHours > 24
|| string.IsNullOrEmpty(_issuer)
|| _signingTokens == null)
{
MetadataSerializer serializer = new MetadataSerializer()
{
// turning off certificate validation for demo. Don't use this in production code.
CertificateValidationMode = X509CertificateValidationMode.None
};
MetadataBase metadata = serializer.ReadMetadata(XmlReader.Create(metadataAddress));
EntityDescriptor entityDescriptor = (EntityDescriptor)metadata;
// get the issuer name
if (!string.IsNullOrWhiteSpace(entityDescriptor.EntityId.Id))
{
_issuer = entityDescriptor.EntityId.Id;
}
// get the signing certs
_signingTokens = ReadSigningCertsFromMetadata(entityDescriptor);
_stsMetadataRetrievalTime = DateTime.UtcNow;
}
issuer = _issuer;
signingTokens = _signingTokens;
}