Securing the JWT with a X509Certificate2 (JwtSecurityTokenHandler)
.net, authorization, c#, claims-based-identity, jwt
Solution
You have to expose the public key which you can get by right clicking on the certificate and do Export (dont include the private key) on the MMC. Then whoever has to validate the token would do
var x509 = new X509Certificate2(pathToExportedCert);
Or you can also use the byte array ctor and have the public key encoded in base64.
Problem
I managed to make the `JwtSecurityTokenHandler` work with `X509Certificate2`. I was able to sign the token with a `X509Certificate2` object. I was also able to validate the token by using the certificate's raw data through `X509Certificate2.RawData` property. Here is the code: ``` class Program { static void Main(string[] args) { X509Store store = new X509Store("My"); store.Open(OpenFlags.ReadOnly); X509Certificate2 signingCert = store.Certificates[0]; string token = CreateTokenWithX509SigningCredentials(signingCert); ClaimsPrincipal principal = ValidateTokenWithX509SecurityToken( new X509RawDataKeyIdentifierClause(signingCert.RawData), token); } static string CreateTokenWithX509SigningCredentials(X509Certificate2 signingCert) { var now = DateTime.UtcNow; var tokenHandler = new JwtSecurityTokenHandler(); var tokenDescriptor = new SecurityTokenDescriptor { Subject = new ClaimsIdentity(new Claim[] { new Claim(ClaimTypes.Name, "Tugberk"), new Claim(ClaimTypes.Role, "Sales"), }), TokenIssuerName = "self", AppliesToAddress = "http://www.example.com", Lifetime = new Lifetime(now, now.AddMinutes(2)), SigningCredentials = new X509SigningCredentials(signingCert) }; SecurityToken token = tokenHandler.CreateToken(tokenDescriptor); string tokenString = tokenHandler.WriteToken(token); return tokenString; } static ClaimsPrincipal ValidateTokenWithX509SecurityToken(X509RawDataKeyIdentifierClause x509DataClause, string token) { var tokenHandler = new JwtSecurityTokenHandler(); var x509SecurityToken = new X509SecurityToken(new X509Certificate2(x509DataClause.GetX509RawData())); var validationParameters = new TokenValidationParameters() { AllowedAudience = "http://www.example.com", SigningToken = x509SecurityToken, ValidIssuer = "self", }; ClaimsPrincipal claimsPrincipal = tokenHandler.ValidateToken( new JwtSecurityToken(token), validationParameters); return claimsPrincipal; } } ``` My main question is all about what should I expose to the world from my `X509Certificate2`. Which part of the X509Certificate2 should I reveal so that the consumer should validate the JWT token but cannot create a new token using the same certificate?