Cheshire Cat
Cheshire Cat

Reputation: 1961

C# Cannot sign JWT using certificate

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

Answers (1)

President James K. Polk
President James K. Polk

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

Related Questions