mapkit js erro 401 Unauthorized

Hello Apple Developers, I encountered a 401 Unauthorized error when developing a web map. I asked the developer to check whether my key authorization is normal.

This is the test website: https://pro.kyeasy.com/#/user/map

Test account: +33 0625823391 Test password: jinghui111

Domain pro.kyeasy.com

Token Type MapKit JS

Restriction Type Domain Restricted

Token

eyJraWQiOiJKNzZSNkpSM0FLIiwidHlwIjoiSldUIiwiYWxnIjoiRVMyNTYifQ.eyJpc3MiOiIzSzQ4UEE2MjRNIiwiaWF0IjoxNzU0ODA3MTc2LCJvcmlnaW4iOiJwcm8ua3llYXN5LmNvbSJ9.ZQLVPpn2Zbm5uHhT_YaA6T2eyaYNKYL5X1Z3DIC17vo4FlOLAKJnXUdB_0zOLDufVDT-CNZWK08_5KkjI5pAKA

Creation Date 08/10/25

Expiration Date None

Status Active

Created by Jinghui Yang

info java develop

team id: 3K48PA624M

Key ID DNRWXXA4L2 Created by Jinghui Yang on 2025/08/10 06:08 am

bunld id 3K48PA624M.maps.com.kyeasy

p8 DNRWXXA4L2.p8

info java develop

How was your token created? If you create a token through the Apple Developer website as described in the documentation, does that token work?

— Ed Ford,  DTS Engineer

When generating a JWT in Java backend development, we received an error: "Unable to retrieve public key from issuer (iss)"

'3K48PA624M'. Expected a valid HTTPS URL.

Please manually enter the public key to verify the JWT signature. ///// document: https://developer.apple.com/documentation/applemapsserverapi/creating-and-using-tokens-with-maps-server-api

The Apple Maps Server API is not quite the same thing as MapKit JS. If you generate a token by following the MapKit JS instructions I linked to previously, what happens?

— Ed Ford,  DTS Engineer

Hi, web react developers have no problem creating mapkit js token, our problem is that init mapkit js requires java developers to generate jwt, but cannot decrypt the map .P8 file

const path = require('path');
const express = require('express');
const jwt = require('jsonwebtoken');
const cors = require('cors');

const app = express();

// 配置 CORS - 允许前端域名
app.use(cors({
  origin: ['http://localhost:5173', 'https://yourproductiondomain.com'],
  credentials: true
}));

const TEAM_ID = '3K48PA624M';           // 你的 Team ID
const KEY_ID = 'MFF8WDFV2T';            // 你的 Key ID
const PRIVATE_KEY_PATH = path.join(__dirname, 'AuthKey_MFF8WDFV2T.p8');

// 读取私钥文件
let PRIVATE_KEY;
try {
  PRIVATE_KEY = fs.readFileSync(PRIVATE_KEY_PATH, 'utf8');
  console.log('私钥加载成功');

  // 验证私钥格式
  if (!PRIVATE_KEY.includes('-----BEGIN PRIVATE KEY-----') ||
      !PRIVATE_KEY.includes('-----END PRIVATE KEY-----')) {
    throw new Error('私钥格式不正确,必须包含 BEGIN/END PRIVATE KEY 标记');
  }
} catch (error) {
  console.error('无法读取私钥文件:', error.message);
  process.exit(1);
}

function generateMapKitToken() {
  const now = Math.floor(Date.now() / 1000);
  
  const payload = {
    iss: TEAM_ID,               // Team ID
    iat: now,                   // 签发时间
    exp: now + 1800,            // 30分钟有效(官方建议15-30分钟)
  };

  try {
    // 使用 ES256 算法签名
    const token = jwt.sign(payload, PRIVATE_KEY, {
      algorithm: 'ES256',
      header: {
        alg: 'ES256',
        typ: 'JWT',
        kid: KEY_ID,            // Key ID
      }
    });

    console.log('JWT 生成成功');
    return token;
  } catch (error) {
    console.error('JWT 生成错误:', error);
    throw error;
  }
}

// MapKit JS 令牌端点
app.get('/base-service/api/base/app/map/token', (req, res) => {
  console.log('收到令牌请求,来源:', req.headers.origin || '未知');

  try {
    const token = generateMapKitToken();

    // 返回纯文本令牌(MapKit JS 期望纯文本响应)
    res.set('Content-Type', 'text/plain');
    res.send(token);
  } catch (err) {
    console.error('令牌生成失败:', err);
    res.status(500).json({
      message: 'Token生成失败',
      error: err.message
    });
  }
});

// 健康检查端点
app.get('/health', (req, res) => {
  res.status(200).json({ status: 'OK', service: 'MapKit Token Service' });
});

// 启动服务器
const PORT = 7101;
app.listen(PORT, () => {
  console.log(`MapKit Token Server running at http://localhost:${PORT}`);
  console.log(`令牌端点: http://localhost:${PORT}/base-service/api/base/app/map/token`);
public async initializeMapKit(): Promise<void> {
    if (this.isInitialized) return;

    if (!(window as any).mapkit) throw new Error("MapKit 未加载");

    return new Promise((resolve, reject) => {
      (window as any).mapkit.init({
        authorizationCallback:function(done) {   // 注意这里不能 async
          fetch("http://localhost:7101/base-service/api/base/app/map/token", {
            method: "GET",
            headers: {
              "Content-Type": "application/json",
            },
          }).then(res => res.text())
              .then(data => done(data))
              .catch(error => console.error('获取令牌失败:', error));
        },
        language: "zh-CN",
      });

      (window as any).mapkit.addEventListener("configuration-change", (event) => {
        console.log("map configuration change:", event);
        switch (event.status) {
          case "Initialized":
            console.log("MapKit 已初始化");
            break;
          case "Refreshed":
            console.log("MapKit 已刷新配置");
            break;
        }
      });
    });
  }

web react developers have no problem creating mapkit js token,

It sounds like they can create a token, but have you tried to deploy that token generated through the Apple website into your app to make sure that initialization succeeds without the 401 response? I'm looking to rule out entire classes of issues by ensuring that path is working for you before proceeding with the other details of how you are custom generating your tokens.

— Ed Ford,  DTS Engineer

        authorizationCallback:function(done) {   // 注意这里不能 async
          done("eyJraWQiOiI3OVNYVEdIOU45IiwidHlwIjoiSldUIiwiYWxnIjoiRVMyNTYifQ.eyJpc3MiOiIzSzQ4UEE2MjRNIiwiaWF0IjoxNzU1ODAwMDAyLCJleHAiOjE3NTY0NTA3OTl9.qUD9RUV7oC6LAo1KmpDCst-CUyEvz1Lbk5ZPt4E3E0z0q_lFoES8YsJGdSc4_UV405XyCaBfyFNBP-BlKZzQew")
        },
        language: "zh-CN",
      });

// 使用的方法
async function getCurrentLocation() {
  if (!navigator.geolocation) {
    error.value = "您的浏览器不支持地理定位";
    return;
  }
  try {
    await mapTokenManager.initializeMapKit();
    map = new (window as any).mapkit.Map(mapContainer.value);
  } catch (err) {
    error.value = "地图初始化失败";
    console.error(err);
  }
  isLoading.value = true;
  error.value = "";

  navigator.geolocation.getCurrentPosition(
    (position) => {
      currentLocation.value = {
        latitude: position.coords.latitude,
        longitude: position.coords.longitude,
        accuracy: position.coords.accuracy,
        timestamp: position.timestamp
      };

      // 在地图上显示位置
      if (map) {
        const coord = new (window as any).mapkit.Coordinate(
          position.coords.latitude,
          position.coords.longitude
        );
        map.setCenterAnimated(coord);
        
        // 添加标记
        const annotation = new (window as any).mapkit.Annotation(coord, {
          title: "当前位置",
          subtitle: `${position.coords.latitude.toFixed(6)}, ${position.coords.longitude.toFixed(6)}`
        });
        map.addAnnotation(annotation);
      }

      isLoading.value = false;
    },
    (err) => {
      error.value = `定位失败: ${err.message}`;
      isLoading.value = false;
    },
    {
      enableHighAccuracy: true,
      timeout: 10000,
      maximumAge: 60000
    }
  );
}

Hello, as shown above, I generated a test token. In the code, I initialized it through mapkit.init, and then it reported the 401 error shown in the screenshot. This is the token created directly in the maps service on our website without background processing.

Thanks for doing that, which confirmed my suspicions that this wasn't related to your server. Please open a bug report for this, and once you've done so, please post the FB number here for the record.

— Ed Ford,  DTS Engineer

mapkit js erro 401 Unauthorized
 
 
Q