Search code examples
c#jwtapp-store

Using ES256 algorithm with jwt-dotnet for Apple AppStore


I'm trying to generate a jwt token to connect to AppStore API. I'm using the jwt-dotnet library to do this.

Apple requires ES256 to be used and the jwt-dotnet is asking for a public key to do the job. I only downloaded a private key from AppStore. How do I handle this?

Here's my code:

public static string GenerateAppStoreJwtToken()
{
   var header = new Dictionary<string, object>()
   {
      { "kid", "MY_VALUE" },
      { "typ", "JWT" }
   };

   var scope = new string[1] { "GET /v1/apps?filter[platform]=IOS" };
   var payload = new Dictionary<string, object>
   {
      { "iss", "MY_VALUE" },
      { "iat", DateTimeOffset.UtcNow.ToUnixTimeSeconds() },
      { "exp", DateTimeOffset.UtcNow.AddMinutes(20).ToUnixTimeSeconds() },
      { "aud", "appstoreconnect-v1" },
      { "scope", scope }
   };


   IJwtAlgorithm algorithm = new ES256Algorithm(???); // What am I going to use here?
   IJsonSerializer serializer = new JsonNetSerializer();
   IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
   IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);

   var token = encoder.Encode(header, payload, privateKey);

   return token;
}

Solution

  • Here's the final solution that worked for me. I ended up switching to jose-jwt but I'm pretty sure you can handle the same thing with jwt-dotnet. I just found working with jose-jwt a bit easier. Here's the link to jose-jwt: https://github.com/dvsekhvalnov/jose-jwt

    And here's the final code. Please note that I did indeed use the private key I find in the p8 file and didn't have to convert anything. So the privateKey parameter I'm passing to the GenerateAppStoreJwtToken() function comes directly from the p8 file.

    using System;
    using System.Collections.Generic;
    using System.Security.Cryptography;
    using Jose;
        
    public static string GenerateAppStoreJwtToken(string privateKey)
    {
        var header = new Dictionary<string, object>()
        {
            { "alg", "ES256" },
            { "kid", "MY_VALUE" },
            { "typ", "JWT" }
        };
        
        var scope = new string[1] { "GET /v1/apps?filter[platform]=IOS" };
        var payload = new Dictionary<string, object>
        {
            { "iss", "MY_VALUE" },
            { "iat", DateTimeOffset.UtcNow.ToUnixTimeSeconds() },
            { "exp", DateTimeOffset.UtcNow.AddMinutes(15).ToUnixTimeSeconds() },
            { "aud", "appstoreconnect-v1" },
            { "scope", scope }
        };
        
        CngKey key = CngKey.Import(Convert.FromBase64String(privateKey), CngKeyBlobFormat.Pkcs8PrivateBlob);
    
        string token = JWT.Encode(payload, key, JwsAlgorithm.ES256, header);
     
        return token;
    }