Unable to authenticate salesReports (JWT + NodeJS)

I can't seem to get authenticate against the https://api.appstoreconnect.apple.com/v1/salesReports endpoint.


I'm using jsonwebtoken version 8.5.1. My code looks like



  const
      jwt = require('jsonwebtoken'),       exec = require('madscience-node-exec'),
       fs = require('fs'),
       privateKey = fs.readFileSync('./private.p8'),
       iss = 'MY_TEAM_ID',       
       kid = 'MY_KEY_ID',
       options = {
            algorithm: 'ES256',
            header : {
            'alg': 'ES256',
            'typ': 'JWT',
            'kid' : kid
            }
       };

  let exp = new Date();
  exp.setMinutes(exp.getMinutes() + 10);

  const claims = {
       'iss' : iss,
       'exp' : exp.getTime(),
       'aud': 'appstoreconnect-v1'
  };

  const token = jwt.sign(claims, privateKey, options);


When I do


curl  -v -H "Authorization: Bearer TOKENHERE" https://api.appstoreconnect.apple.com/v1/salesReports


I get


"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"
    }]


I've double checked my team id, key id and private key, they're all valid. My key has permission to access saleReports. I've also tried this with a "developer" level key, and get the same problem. I've tried countless variations of the above, as jsonwebtoken allows you to place the team id and expires at in options instead of in the claims object, but I get the same error regardless of where I place values.


Note that Apple's documentation states that expires may not be greater than 20 minutes after token creation. Has anyone got a confirmed working example of token code for this endpoint? Thanks.

Replies

I found your post and solve the error that you get as follows:

Instead of:

Code Block
let exp = new Date();
exp.setMinutes(exp.getMinutes() + 10);
const claims = {
'iss' : iss,
'exp' : exp.getTime(),
'aud': 'appstoreconnect-v1'
};

Try:

Code Block
let now = Math.round((new Date()).getTime() / 1000); // Notice the /1000
let nowPlus20 = now + 1199 // 1200 === 20 minutes;
const claims = {
"iss": iss,
"exp": nowPlus20,
"aud": "appstoreconnect-v1"
};

You will found a new Error due that you are not passing the requested parameters to the query, look at:

https://developer.apple.com/documentation/appstoreconnectapi/download_sales_and_trends_reports

I also still not solve the problem completely, here is the error that I'm already getting:

https://developer.apple.com/forums/thread/655667?page=1#625376022


Finally I found the solution to solve the problem completely, here is how:

https://developer.apple.com/forums/thread/655667?page=1#625376022