Techioz Blog

App Store Connect APIのトークンを生成する

概要

Store Connect API 用の JWT トークンを生成する必要があります。 jwt Ruby gem Ruby-jwt を使用しようとしています。これは私のトークン生成コードです。

payload = {
      'iss': my_issuer_id_from_db,
      'exp': generated_unix_timestamp, #Time.now + 20min
      'aud': 'hard_coded_string_from_doc'
  }
  header = {
      'alg': 'ES256',
      'kid': my_key_id_from_db,
      'typ': 'JWT'
  }

private_key = OpenSSL::PKey.read(File.read('/tmp/private_key.pem'))
# private_key - <OpenSSL::PKey::EC:0x000000000XXXXXXX>

@token = JWT.encode(payload, private_key, 'ES256', header)
# encoded_header.encoded_payload.emcoded_signature

このトークンをリクエストのヘッダーに追加しました。

headers = { Authorization: 'Bearer' + @token }

私が受け取る応答では:

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

問題はトークン(直接署名付き)にあると思います。オンライン ツールでトークンをデコードしようとすると、ペイロードとヘッダーが正しくデコードされました。ステータス: 無効な署名

私の何が間違っているのでしょうか?適切に行う方法はありますか?

解決策

ここではPython3バージョンを作成しました。 401 認証資格情報が見つからないか無効です。発行時間または期限切れの取得に関連している可能性があります。

関数の取得時間が Apple が推奨する UNIX エポック時間であることを確認してください。

import jwt
import datetime as dt

key_id = '#####' 
alg = 'ES256'
typ = 'JWT'
issue_id = '##########################'
aud = 'appstoreconnect-v1'
bid = '####' # Your app’s bundle ID (Ex: “com.example.testbundleid2021”)

# Define issue timestamp.
issued_at_timestamp = int(dt.datetime.now().timestamp())
# Define expiration timestamp. May not exceed 20 minutes from issue timestamp.
expiration_timestamp = issued_at_timestamp + 20*60

# Define JWT headers.
headers = dict()
headers['alg'] = alg
headers['kid'] = key_id
headers['typ'] = typ

# Define JWT payload.
payload = dict()
payload['iss'] = issue_id
payload['iat'] = issued_at_timestamp
payload['exp'] = expiration_timestamp
payload['aud'] = aud
payload['bid'] = bid
# Path to signed private key.
KEY_FILE = '#########.p8' 

with open(KEY_FILE,'r') as key_file:
     key = ''.join(key_file.readlines())

client_secret = jwt.encode(
payload=payload,  
headers=headers,
algorithm=alg,  
key=key
)

with open('client_secret.txt', 'w') as output: 
     output.write(client_secret)
    
    
# Usage, after run this code by python3
# get token from `client_secret.txt` and replace to [signed token]
# Remember expired time maximum is 20 minutes
#
# curl -v -H 'Authorization: Bearer [signed token]' "https://api.appstoreconnect.apple.com/v1/apps"
#
# More detail https://developer.apple.com/documentation/appstoreconnectapi/generating_tokens_for_api_requests