Apple ID Authentication in .net ASP.NET framework Unsupported Grant Type error

1.6k views Asked by At

I'm writing a server application that handles Apple ID authorization from the iOS device. The server is written in C# .net ASP.NET framework.

To authenticate I'm using this data:

  • _config.ClientId = com.organization.ios.app_name,
  • _config.PrivateKeyId - .p8 file key id
  • _config._DevelopmentTeam - code located before client id name ,X.com.organization.ios.app_name that X,
  • _config.PrivateKey - private key from .p8 file

From request from an iOS device I'm getting:

  • request.AuthCode - authorization code,
  • request.IdentityToken - token.

Code is really simple:

public Task<ResponseDTO> AuthenticateWithApple(RequestDTO request)
{
    var contentData = new List<KeyValuePair<string, string>>()
    {
        new KeyValuePair<string, string>("client_id", _config.ClientId),
        new KeyValuePair<string, string>("client_secret", GenerateAppleJwtToken()),
        new KeyValuePair<string, string>("code", passData.AuthCode);
        new KeyValuePair<string, string>("grand_type", "authorization_code"),
        new KeyValuePair<string, string>("refresh_token", "");
        new KeyValuePair<string, string>("redirect_uri", "");
    };

    try
    {
        var content = new FormUrlEncodedContent(contentData);
        var response = await httpClient.PostAsync(_requestUrl, content);
        var rawResponseData = await response.Content.ReadAsStringAsync();

        if (response.StatusCode == HttpStatusCode.OK)
        {
            var responseData = JsonConvert.DeserializeObject<ResponseDTO>(rawResponseData);
            return responseData;
        }
        else
        {
            var errorMessage = $"Status code {response.StatusCode}: \"{rawResponseData}\"";
            throw new ArgumentException(errorMessage);
        }
    }
    catch (Exception exc)
    {
        var error = new ErrorResponseViewModel();
        var errorMessage = $"Problem encountered during authorization: {exc.Message}";
        error.AddError(ErrorTypes.UNAUTHORIZED, nameof(AppleAuthenticationProvider), errorMessage);
        return new ResponseDTO()
        {
            Errors = error
        };
    }
}

And for creating JWT client secret code is:

private string GenerateAppleJwtToken()
{
    var issueTime = DateTime.Now;
    var zeroTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);

    var iat = (int) issueTime.Subtract(zeroTime).TotalSeconds;
    var exp = (int) issueTime.AddMinutes(5).Subtract(zeroTime).TotalSeconds;

    var headers = new Dictionary<string, object>()
    {
        { "alg", "ES256" },
        { "typ", "JWT" },
        { "kid", _config.PrivateKeyId },
    };

    var payload = new Dictionary<string, object>()
    {
        { "sub", _config.ClientId },
        { "aud", "https://appleid.apple.com" },
        { "iss", _config.DevelopmentTeam },
        { "exp", exp },
        { "iat", iat }
    };

    var cngKey = CngKey.Import(Convert.FromBase64String(_config.PrivateKey), CngKeyBlobFormat.Pkcs8PrivateBlob);
    var ecdsa = new ECDsaCng(cngKey);

    byte[] headerBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(headers, Formatting.None));
    byte[] claimsBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(payload, Formatting.None));

    var base64Payload = Base64UrlEncoder.Encode(headerBytes) + "." + Base64UrlEncoder.Encode(claimsBytes);
    var signature = ecdsa.SignData(Encoding.UTF8.GetBytes(base64Payload), HashAlgorithmName.SHA256);

    return base64Payload + "." + Base64UrlEncoder.Encode(signature);
}

According to many code implementations of Apple ID authorization, this should work, but it doesn't. Error message is that i recive is: "unsupported_grant_type"

1

There are 1 answers

1
muxto On BEST ANSWER

You are sending a parameter grand_type, but grant_type is expected. Mind the typo in grand.