Reputation: 1961
I'm working on a C# Web Api MVC project using VS 2017 and .NET 4.6.2 and I want to use my certificate to sign a JSON Web Token.
This is my code:
using SolutionDOC_Common;
using SolutionDOC_Interface.Repository.Authentication;
using SolutionDOC_SDK.Model;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Authentication;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using mit = Microsoft.IdentityModel.Tokens;
public string Build(Credentials credentials)
{
string thumbprint = ConfigurationManager.AppSettings["CertificateThumbprint"];
string tokenIssuer = ConfigurationManager.AppSettings["TokenIssuer"];
string tokenAudience = ConfigurationManager.AppSettings["TokenAudience"];
List<Claim> claims = new List<Claim>
{
new Claim(ClaimTypes.Name, credentials.Username),
new Claim(ClaimTypes.Surname, credentials.Alias)
};
X509Certificate2 cert = CertificateUtility.GetCertificateByThumbprint(thumbprint);
RSACryptoServiceProvider publicAndPrivate = (RSACryptoServiceProvider)cert.PublicKey.Key;
JwtSecurityToken jwtToken = new JwtSecurityToken
(
issuer: tokenIssuer,
audience: tokenAudience,
claims: claims,
signingCredentials: new mit.SigningCredentials(new mit.RsaSecurityKey(publicAndPrivate), mit.SecurityAlgorithms.RsaSha256Signature),
expires: DateTime.Now.AddDays(30)
);
JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
// This throws the InvalidOperationException!
string tokenString = tokenHandler.WriteToken(jwtToken);
return tokenString;
throw new AuthenticationException();
}
The tokenHandler.WriteToken(jwtToken)
line, throws an InvalidOperationException
saying that
'IDX10638: Cannot created the SignatureProvider, 'key.HasPrivateKey' is false, cannot create signatures. Key: Microsoft.IdentityModel.Tokens.RsaSecurityKey.'
The permission on the corresponding certificate are set to IIS_IUSRS user, so it can read also the private key. The certificate is actually a self signed certificate generated using IIS, that has a private key.
The thumbprint is set correctly and so I get the right certificate.
So I get the X509Certificate2
object correctly. The PrivateKey property of the X509Certificate2
object is populated.
Why doesn't it work?
Upvotes: 1
Views: 5164
Reputation: 41958
Well, even though you labelled the variable publicAndPrivate
you clearly only extracted a public key. Try instead
RSACryptoServiceProvider publicAndPrivate = (RSACryptoServiceProvider)cert.PrivateKey;
Upvotes: 2