Debugging API JWT authorization problems - any suggestions?

Dear All,

I have working code that talks to the App Attest receipt refresh API using JWT authorization. I'm now trying to talk to the App Store Connect API, and I'm trying to use essentially the same code for the JWT generation - but it doesn't work.

It's frustrating that the API just returns a non-specific 401 "Not Authorized" response, without giving any further clue about what's wrong.

I am creating a JWT as follows for App Store Connect; yes I'm aware that the required fields are slightly different for the two APIs:

header = {"alg":"ES256","kid":"12345YZSX8","typ":"JWT"}
payload = {"iss":"1234567-1234-1234-1234-123456789012","iat":1687379230,"exp":1687379530,"aud":"appstoreconnect-v1"}

Using the resulting encoded token, with my own code or with curl, fails with a 401 error:

Status: 401
{
	"errors": [{
		"status": "401",
		"code": "NOT_AUTHORIZED",
		"title": "Authentication credentials are missing or invalid.",
		"detail": "Provide a properly configured and signed bearer token, and make sure that it has not expired. Learn more about Generating Tokens for API Requests https://developer.apple.com/go/?id=api-generating-tokens"
	}]
}

Doing essentially the same thing, with the slightly different JSON fields and a different .p8 key file, does work with the App Attest API - so I'm probably not creating complete garbage.

I've wasted hours on this now. Does anyone have any debugging hints?

Replies

Just in case this is ever useful to anyone in the future....

My bug was that I was using DER-encoded bytes in the JWT signature, not raw bytes.

Specifically, if you look at the source of the Ruby JWT encoder used by Apple in their 2018 WWDC presentation, it has a function called asn1_to_raw that converts the result of the OpenSSL::Digest call to raw bytes.

The surprising thing is that my code using the DER-encoded version works for the App Attest API !!! What I don't know is whether that API requires DER-encoded data, or whether it accepts both.