为了账号安全,请及时绑定邮箱和手机立即绑定

无法使用 JWT 令牌连接到 Apple App Store API

无法使用 JWT 令牌连接到 Apple App Store API

catspeake 2023-10-20 15:12:52
我需要为 Store Connect API 生成 JWT 令牌。这是我的令牌生成代码:console.log("🏃 appStoreConnectAPIFromNode.js running 🏃‍")const fs   = require('fs');const jwt  = require('jsonwebtoken'); // npm i jsonwebtoken// You get privateKey, apiKeyId and issuerId from your Apple App Store Connect accountconst privateKey = fs.readFileSync("./AuthKey-XXXXXXXX.p8") // this is the file you can only download once and should treat like a real, very precious key.const apiKeyId = "XXXXXXXX"const issuerId = "XXXXXXXX-XXXX-XXXX-XXX-XXXXXXXXXX"let now = Math.round((new Date()).getTime() / 1000); // Notice the /1000 let nowPlus20 = now + 1199 // 1200 === 20 minuteslet payload = {    "iss": issuerId,    "exp": nowPlus20,    "aud": "appstoreconnect-v1",    "iat": now}let signOptions = {    "algorithm": "ES256", // you must use this algorythm, not jsonwebtoken's default    header : {        "alg": "ES256",        "kid": apiKeyId,        "typ": "JWT"    }};let token = jwt.sign(payload, privateKey, signOptions);console.log('@token: ', token);fs.writeFile('Output.txt', token, (err) => {           // In case of a error throw err.     if (err) throw err; })我收到了这个回复 "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"        }]我认为问题在于令牌(直接带有签名)。当我尝试在https://jwt.io/#debugger-io上解码令牌时,我的有效负载和标头已正确解码。状态:签名无效我做错了什么?有什么想法如何正确地做到这一点吗?
查看完整描述

4 回答

?
绝地无双

TA贡献1946条经验 获得超4个赞

我也遇到这个问题,我和队友解决了。。。。。


解决方案:


删除有效负载中的“iat”(这很重要):像这样,

let payload = {

     iss: *******,

     exp: *******,

     aud: "appstoreconnect-v1",

     bid: "your_bundle_id",

   };

网址:我用的是axios:

const { data } = await axios({

     method: "GET",

     url: "https://api.storekit.itunes.apple.com/inApps/v1/history/",

     headers: {

       "Content-type": "application/json",

       Authorization: `Bearer ${token}`,

     },

   });

res.json(data);


查看完整回答
反对 回复 2023-10-20
?
慕标5832272

TA贡献1966条经验 获得超4个赞

我最近也需要解决这个问题,在学习了很多教程之后,这些教程经常给出应用程序商店连接 api 的错误答案。我找到了一种让它发挥作用的方法。我在 Java 中就是这样做的。


import com.auth0.jwt.JWT;

import com.auth0.jwt.algorithms.Algorithm;

import org.bouncycastle.openssl.PEMParser;

import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;

import java.security.spec.PKCS8EncodedKeySpec;

import java.security.interfaces.ECPrivateKey;

import java.security.KeyFactory;

import java.io.FileReader;

import java.util.Base64;

import java.time.Instant;

import java.time.temporal.ChronoUnit;


// The code is like this so try it in whatever method you want, 

// break it up into pieces so it's a bit more readable


// These variables are the minimum you should need

String keyFile = "/path/to/app_store_AuthKey_XXXX.p8";

// The XXXX is the same XXXX from the keyFile filename itself

String keyId = "XXXX";

String issuerId = "1234-1234-1234-1234-1234";


FileReader kfReader = new FileReader(keyFile);

PEMParser pemParser = new PEMParser(kfReader);

PrivateKeyInfo info = (PrivateKeyInfo) pemParser.readObject();

byte[] pkData = info.getEncoded();


// Convert the PrivateKeyInfo object to a PKCS8EncodedKeySpec object

PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pkData);


KeyFactory keyFactory = KeyFactory.getInstance("EC");

ECPrivateKey privateKey = (ECPrivateKey) keyFactory.generatePrivate(keySpec);


Algorithm algorithm = Algorithm.ECDSA256(null, privateKey);


Instant expiration = Instant.now().plus(TIMEOUT_MINUTES, ChronoUnit.MINUTES);


return JWT.create()

          .withKeyId(keyId)

          .withIssuer(issuerId)

          .withExpiresAt(expiration)

          .withAudience("appstoreconnect-v1")

          .sign(algorithm);


查看完整回答
反对 回复 2023-10-20
?
Helenr

TA贡献1780条经验 获得超3个赞

我试图解决我自己的问题,即使用 JWT 连接到 Apple Music API,我在您的有效负载中注意到了两件事。首先,您将 1200 添加到 IAT 中,修复了我的问题,所以谢谢您。第二个是函数现在返回一个浮点数。我认为 API 需要一个 int。我会尝试"iat": parseInt(now)或者now = Math.floor(new Date().getTime() / 1000)



查看完整回答
反对 回复 2023-10-20
?
呼啦一阵风

TA贡献1802条经验 获得超6个赞

根据jsonwebtoken使用说明。options您可以直接在空负载上使用,如下所示:


let signOptions = {

    issuer: issuerId,

    keyid: apiKeyId,

    expiresIn: '20m',

    audience: 'appstoreconnect-v1',

    algorithm: 'ES256'

};


let token = jwt.sign({}, privateKey, signOptions);


查看完整回答
反对 回复 2023-10-20
  • 4 回答
  • 0 关注
  • 214 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信