Hey folks! I’m trying to switch from receipt-based to transaction-based purchase verification for my iOS app using StoreKit 2. I’ve set up the Node.js backend, but I’m running into some weird issues.
When I generate the Apple JWT, I get a 401 error if I don’t include the issuerID in both the payload and token options. But when I do include it in both places, I get this warning:
Bad "options.issuer" option. The payload already has an "iss" property.
Is it okay to ignore this warning? I’m using the sandbox environment for testing.
Here’s a simplified version of my code:
function makeAppleToken() {
const secret = getSecretKey();
const kid = 'ABC123';
const issuer = 'XYZ789';
const data = {
iss: issuer,
aud: 'appstore-v1',
sub: 'com.myapp.bundle',
iat: Date.now() / 1000,
};
return jwt.sign(data, secret, {
algorithm: 'ES256',
expiresIn: '5m',
issuer: issuer,
header: { alg: 'ES256', kid: kid }
});
}
Any ideas on how to fix this? Thanks!
hey charlottew, I’ve dealt with similar issues. try removing the ‘issuer’ field from the jwt.sign options. the ‘iss’ in the payload should be enough. if that doesn’t work, double-check your kid and issuer values match whats in app store connect. good luck!
I’ve encountered similar issues with Apple’s API authentication. One thing that often gets overlooked is the format of the private key. Make sure it’s in the correct PEM format, starting with ‘-----BEGIN PRIVATE KEY-----’ and ending with ‘-----END PRIVATE KEY-----’. If it’s not, you might need to convert it.
Also, check the ‘sub’ claim in your payload. It should match your App ID prefix followed by your Bundle ID. For example, if your App ID prefix is ‘1A2B3C4D5E’ and your Bundle ID is ‘com.myapp.bundle’, the ‘sub’ should be ‘1A2B3C4D5E.com.myapp.bundle’.
Lastly, ensure your app’s capabilities in Xcode include ‘In-App Purchase’ and that it’s properly configured in App Store Connect. Sometimes, these misconfigurations can lead to unexpected authentication errors.
If you’re still stuck, Apple’s developer forums can be a goldmine for specific error resolutions.
I’ve faced similar challenges with Apple’s API. From my experience, the warning about the duplicate issuer can indeed be safely ignored. The key is to ensure your payload and options are correctly configured.
One thing that worked for me was adjusting the ‘iat’ (issued at) claim. Instead of using milliseconds, try using seconds since the epoch:
iat: Math.floor(Date.now() / 1000)
Also, make sure your ‘kid’ matches exactly with the one in App Store Connect. Even a slight mismatch can cause 401 errors.
Lastly, double-check that your private key is in the correct format and hasn’t expired. These subtle issues can be easily overlooked but often cause authentication problems.
If you’re still facing issues after these tweaks, consider using Apple’s validation tool to verify your JWT structure.