Q:

Azure KeyVault - Sign JWT Token

I began using Azure Keyvault to store private keys for my application.  
I have a use case where I need to sign a JWT token with an RSA private key.  
When I had the private key in my application memory, it was easy,
I would just do that
var token = new JwtSecurityToken(
                issuer,
                ...,
                claims,
                ...,
                ...,
                signingCredentials_PrivateKey);

Now that I began to use Azure Keyvault, I want to see if it's possible to sign JWT tokens via the KeyVaultClient.SignAsync method.  
Something along the lines of  
KeyVaultClient client = ...;
var token = new JwtSecurityToken(
                issuer,
                ...,
                claims,
                ...,
                ...);
var tokenString = client.SignAsync(myKeyIdentifier, token);

A:

First, a JWT token consists of three parts: Header, Payload and Signature. All of them are Base64UrlEncoded.
You can get the signature as following: 
HMAC-SHA256(
 base64urlEncoding(header) + '.' + base64urlEncoding(payload),
 secret
)

So, you need to generate the header and payload, combine them by dot, compute the hash, and then you can get the signature. 
Here is a sample for your reference: 
var byteData = Encoding.Unicode.GetBytes(base64urlEncoding(header) + "." + base64urlEncoding(payload));
var hasher = new SHA256CryptoServiceProvider();
var digest = hasher.ComputeHash(byteData);
var signature = await keyClient.SignAsync(keyIdentifier, "RS256", digest);
var token = base64urlEncoding(header) + "." + base64urlEncoding(payload) + "." + base64urlEncoding(signature)

The official SDK documentation for SignAsync
Wiki for JWT

A:

I ended up using Jack Jia's answer
var token = new JwtSecurityToken(
                issuer,
                appId,
                claims,
                signDate,
                expiryDate);

var header = Base64UrlEncoder.Encode(JsonConvert.SerializeObject(new Dictionary<string, string>()
{
    { JwtHeaderParameterNames.Alg, "RS256" },
    { JwtHeaderParameterNames.Kid, "https://myvault.vault.azure.net/keys/mykey/keyid" },
    { JwtHeaderParameterNames.Typ, "JWT" }
}));
var byteData = Encoding.UTF8.GetBytes(header + "." + token.EncodedPayload);
var hasher = new SHA256CryptoServiceProvider();
var digest = hasher.ComputeHash(byteData);
var signature = await _keyVault.SignAsync("https://myvault.vault.azure.net/keys/mykey/keyid", "RS256", digest);

return $"{header}.{token.EncodedPayload}.{Base64UrlEncoder.Encode(signature.Result)}";

I found another solution, which I didn't like as much but it "integrates" better with the JWT libraries.  
var token = new JwtSecurityToken(
    issuer,
    appId,
    claims,
    signDate,
    expiryDate,
    new SigningCredentials(new KeyVaultSecurityKey("https://myvault.vault.azure.net/keys/mykey/keyid", new KeyVaultSecurityKey.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback)), "RS256")
    {
        CryptoProviderFactory = new CryptoProviderFactory() { CustomCryptoProvider = new KeyVaultCryptoProvider() }
    });

var handler = new JwtSecurityTokenHandler();
return handler.WriteToken(token);

Turns out that there is a library Microsoft.IdentityModel.KeyVaultExtensions with extensions to SecurityToken and ICryptoProvider which support KeyVault.  
My problems with it are  

I can't reuse an existing instance of KeyVaultClient with this solution.
It's blocking (Behind the scenes, it calls .GetAwaiter().GetResult() on KeyVaultClient.SignAsync 

