Recently I ran into a challenge at work and that I had hard time figuring out how to solve. We have an authenticate server written in NodeJS. It signs a user into our application and creates a JWT. This application signs the JWT with a PEM file which ONLY has a Private RSA Key. Our C# API can use the corresponding certificate file (.cer) to validate the token when it is passed in each API call.
This has been working great. For reasons I’m not going to get into here, we had to come up with a way to create a token from our Asp.Net admin that would allow someone to login as a specific user without logging in. We are doing this for a demo type of user account. The challenge was that I couldn’t find any good examples that would allow me to create the JWT using only the PEM file. I found hints here and there but nothing exact.
The solution I came up with was to use a combination of Bouncy Castle and Jose JWT. I used Bouncy Castle to create the signing key and then Jose JWT to encode the token.
public static string CreateToken(List<Claim> claims, string certificateName, string rootFolder, string certificateFolder = "Certificates")
{
string path = Path.Combine(rootFolder, certificateFolder, certificateName);
string pemString = File.ReadAllText(path);
string jwt = string.Empty;
AsymmetricCipherKeyPair keyPair;
using (StreamReader sr = new StreamReader(path))
{
PemReader pr = new PemReader(sr);
keyPair = (AsymmetricCipherKeyPair)pr.ReadObject();
}
RSAParameters rsaParams = DotNetUtilities.ToRSAParameters((RsaPrivateCrtKeyParameters)keyPair.Private);
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
rsa.ImportParameters(rsaParams);
Dictionary<string, object> payload = claims.ToDictionary(k => k.Type, v => (object)v.Value);
jwt = Jose.JWT.Encode(payload, rsa, Jose.JwsAlgorithm.RS256);
}
return jwt;
}
As you can see, this is a somewhat generic method that takes in the path to the certificate along with the claims and then creates the JWT out of that information.
Anyway, I hope this can help others.
If you have other suggestions, I’d love to hear them in the comments.