user3790083 user3790083 -4 years ago 597
C# Question

How to encode JWT for APN tokenization (.NET, C#)

I'm trying to send Push Notifications to APN with tokenization. I tried to use a few libraries like jose-jwt and Microsot Jwt class for creating JWT token, but I can't wrap my head around it.

I get stuck on creating JWT and signing it with private key.

For communicating with certificates, I used PushSharp and it worked just fine. Can anyone help me with a working similar example but with tokens?

edit: following Apple's documentation here: https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CommunicatingwithAPNs.html#//apple_ref/doc/uid/TP40008194-CH11-SW1

Sample code: the closest I came to something would look like this, but I don't know how to create CngKey properly

var payload = new Dictionary<string, object>()
{
{ "iss", issuer },
{ "iat", DateTime.UtcNow }
};

var headers = new Dictionary<string, object>()
{
{ "kid", keyIdentifier}
};

CngKey key = CngKey.Create(CngAlgorithm.ECDsaP256); //how to create this CngKey

string token = Jose.JWT.Encode(payload, key, JwsAlgorithm.ES256, headers);

Answer Source

Thanks for your answers, had to contact many supports to get this done. Here is what the final result looked like.

/// <summary>
    /// Method returns ECDSA signed JWT token format, from json header, json payload and privateKey (pure string extracted from *.p8 file - PKCS#8 format)
    /// </summary>
    /// <param name="privateKey">ECDSA256 key</param>
    /// <param name="header">JSON header, i.e. "{\"alg\":\"ES256\" ,\"kid\":\"1234567899"\"}"</param>
    /// <param name="payload">JSON payload, i.e.  {\"iss\":\"MMMMMMMMMM"\",\"iat\":"122222222229"}"</param>
    /// <returns>base64url encoded JWT token</returns>
    public static string SignES256(string privateKey, string header, string payload)
    {
        CngKey key = CngKey.Import(
            Convert.FromBase64String(privateKey), 
            CngKeyBlobFormat.Pkcs8PrivateBlob);

        using (ECDsaCng dsa = new ECDsaCng(key))
        {
            dsa.HashAlgorithm = CngAlgorithm.Sha256;
            var unsignedJwtData = 
                Url.Base64urlEncode(Encoding.UTF8.GetBytes(header)) + "." + Url.Base64urlEncode(Encoding.UTF8.GetBytes(payload));
            var signature = 
                dsa.SignData(Encoding.UTF8.GetBytes(unsignedJwtData));
            return unsignedJwtData + "." + Url.Base64urlEncode(signature);
        }
    }
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download