Apple Maps Server API Unauthorized Error

I'm trying to use the new Apple Maps Server API. As far as I can tell I have set up the token correctly, but my web request is still returning 401 unauthorized.

The following is my code in TypeScript:

import * as jwt from 'jsonwebtoken';

const JWT_SECRET = "-----BEGIN PRIVATE KEY-----\n" +
"MIGTAgEAMBMGBy..............................\n" +
"..............................................................\n" +
"..............................................................\n" +
"-----END PRIVATE KEY-----";

const header = {
alg: "ES256",
kid: "26DYPK65ZK",
typ: "jwt"
}

// Example payload data
const payload = {
"iss": "7F3PBYWYMS",
"iat": Date.now(),
"exp": Date.now() + (1000 * 30 * 60),
};

export async function getRestaurants() {

let token = jwt.sign(payload, JWT_SECRET, { algorithm: 'ES256', header: header});
const response = await fetch('https://maps-api.apple.com/v1/token (https://maps-api.apple.com/v1/token)', {
method: 'GET',
headers: {
'Authorization': "Bearer " + token
},
});
console.log(response);

}

What am I doing incorrectly here?

Answered by DTS Engineer in 811138022

Here's a working implementation for generating an Apple Maps Server token using Node:

const fs = require('fs')
const jwt = require('jsonwebtoken')

// Configure these values
const teamID = "AB12CD34E5"
const mapsServerKeyID = "A1BCDEFGHI"
let authKey = fs.readFileSync("./auth/Maps_Server_AuthKey.p8"); // P8 file from Apple Developer Portal

let payload = {
	iss: teamID,
	iat: Date.now() / 1000,
	exp: (Date.now() / 1000) + (60 * 60 * 24 * 7), // 7 days
};

let header = {
	kid: mapsServerKeyID,
	typ: "JWT",
	alg: "ES256"
};

let token = jwt.sign(payload, authKey, { header: header })
console.log(token)

One thing to double check on is that you didn't accidentally flip your team ID and the Maps ID (kid) values, since they look similar. Also, your expiration and date fields may not be calculated correctly, they need to be specified in seconds, which my code above is doing because Date.now() returns in milliseconds.

—Ed Ford,  DTS Engineer

What error are you seeing?

Response {   status: 401,   statusText: 'Unauthorized',   headers: Headers {     server: 'Apple',     date: 'Fri, 04 Oct 2024 21:25:27 GMT',     'content-type': 'application/json;charset=utf8',     'content-length': '71',     connection: 'keep-alive',     'cache-control': 'max-age=0',     'x-rid': 'f2e9c40e-67a5-4b2c-b8af-586af6a27f72',     'content-encoding': 'gzip',     'x-envoy-upstream-service-time': '26',     'strict-transport-security': 'max-age=31536000; includeSubdomains',     'x-content-type-options': 'nosniff',     'x-xss-protection': '1; mode=block'   },   body: ReadableStream { locked: false, state: 'readable', supportsBYOB: true },   bodyUsed: false,   ok: false,   redirected: false,   type: 'basic',   url: 'https://maps-api.apple.com/v1/token' }

Here's a working implementation for generating an Apple Maps Server token using Node:

const fs = require('fs')
const jwt = require('jsonwebtoken')

// Configure these values
const teamID = "AB12CD34E5"
const mapsServerKeyID = "A1BCDEFGHI"
let authKey = fs.readFileSync("./auth/Maps_Server_AuthKey.p8"); // P8 file from Apple Developer Portal

let payload = {
	iss: teamID,
	iat: Date.now() / 1000,
	exp: (Date.now() / 1000) + (60 * 60 * 24 * 7), // 7 days
};

let header = {
	kid: mapsServerKeyID,
	typ: "JWT",
	alg: "ES256"
};

let token = jwt.sign(payload, authKey, { header: header })
console.log(token)

One thing to double check on is that you didn't accidentally flip your team ID and the Maps ID (kid) values, since they look similar. Also, your expiration and date fields may not be calculated correctly, they need to be specified in seconds, which my code above is doing because Date.now() returns in milliseconds.

—Ed Ford,  DTS Engineer

Hi Ed, I'm not sure where difference is between, the code I included in my question and the sample code you provided as a response. Here is an updated version of my code which still doesn't work but is designed as close as possible to the code you provided as possible.

const jwt = require('jsonwebtoken')
const fs = require('fs')

const authKey = fs.readFileSync("../../Desktop/AuthKey_26DYPK65ZK.p8")
const teamID = "7F3PBYWYMS"
const mapsServerKeyID = "26DYPK65ZK"


const header = {
    alg: "ES256",
    typ: "JWT",
    kid: mapsServerKeyID,
}

// Example payload data
const payload = {
    "iss":  teamID,
    "iat": Date.now(),
    "exp": Date.now() + (60 * 60 * 24 * 7), // 7 days,

};

let token = jwt.sign(payload, authKey, {header: header}); 

export async function getRestaurants() {
    const response = await fetch('https://maps-api.apple.com/v1/token', {
        method: 'GET',
        headers: {
            'Authorization': "Bearer: " + token
        },
    });
    console.log(response)
}

can you please take a look and help me understand what I am doing incorrectly?

Notably I have tried: "Bearer " + token, "Bearer: " + token and just token in the header.

Apple Maps Server API Unauthorized Error
 
 
Q