概要
本記事では、Apple Store Server API のリクエストに必要な JWT について説明し、Go言語で JWT を生成・使用する方法を紹介する。
また、実際に生成したJWTを利用して、Apple Server Notifications API のテストを要求する方法を紹介する。
JWT とは
JWT は、JSON Web Token の略で、属性情報を JSON 形式で記述したトークンのことである。
JWT には関連する仕様として、JWS と JWE がある。
JWS は、JSON 形式で署名されたデータを記述する仕様であり、JWE は、JSON 形式で暗号化されたデータを記述する仕様である。
Apple Store Server API では、JWS を利用するため、今回は JWS を用いた JWT の生成を行う。
なお、Apple Store Server API のリクエスト用トークンの生成方法はこちらに記載されている。
以降は、このドキュメントを参考に説明する。
JWT の構成
JWT は、3つの部分に分かれている。
- Header
- Payload
- Signature
各部分は、Base64URL でエンコードされ、 .
で連結した文字列で表現される。
<BASE64URL Header>.<BASE64URL Payload>.<BASE64URL Signature>
Header
Headerには、署名に使用するアルゴリズムなどの情報を含む。
Apple Store Server API では、以下のキーを利用する。
{
"alg": "ES256",
"kid": "2X9R4HXF34",
"typ": "JWT"
}
- alg: 署名に使用するアルゴリズム。ES256 を利用する。
- kid: 秘密鍵のID。Apple Store Connect のページから取得する。
- typ: JWT を指定する。
Payload
Payload には、Apple Store Server API で利用する情報を含む。
{
"iss": "57246542-96fe-1a63e053-0824d011072a",
"iat": 1623085200,
"exp": 1623086400,
"aud": "appstoreconnect-v1",
"bid": "com.example.testbundleid2021"
}
- iss: 発行者のID。Apple Store Connect のページから取得する。
- iat: 署名の発行日時。UNIX時間で指定する。
- exp: 署名の有効期限。UNIX時間で指定する。
- aud: appstoreconnect-v1 を指定する。
- bid: アプリのバンドルID。Apple Store Connect のページから取得する。
Signature
Signatureには、Header の kid
で指定した秘密鍵を使用して、alg
の署名アルゴリズムで署名したデータを含む。
このとき、Base64Urlエンコードした Header と Payload を .
で連結した文字列を署名対象とする。
JWT の生成
JWT の生成には、jwg-go を利用する。
func CreateJWT() string {
// Payload
now := time.Now()
payload := jwt.MapClaims{
"iss": "57246542-96fe-1a63e053-0824d011072a",
"iat": json.Number(strconv.FormatInt(now.Unix(), 10)),
"exp": json.Number(strconv.FormatInt(now.Add(20*time.Minute).Unix(), 10)),
"aud": "appstoreconnect-v1",
"bid": "com.example.testbundleid2021",
}
// JWT 生成
token := jwt.NewWithClaims(jwt.SigningMethodES256, payload)
token.Header["kid"] = "2X9R4HXF34"
// 秘密鍵の読み込み
keyFile, err := ioutil.ReadFile("YOUR_PRIVATE_KEY.p8")
if err != nil {
panic(err)
}
key, err := jwt.ParseECPrivateKeyFromPEM(keyFile)
if err != nil {
panic(err)
}
// JWT の署名
signedToken, err := token.SignedString(key)
if err != nil {
panic(err)
}
fmt.Println(signedToken)
return signedToken
}
JWT の利用方法
JWT を利用するには、リクエストヘッダに Authorization
を指定し、 Bearer
とトークンを指定する。
Authorization: Bearer <JWT>
これを使ってGoでサンドボックス環境のサーバ通知テストをリクエストする関数を実装すると以下のようになる。
[https://developer.apple.com/documentation/appstoreserverapi/request_a_test_notification]
func RequestTestNotification(token string) {
httpClient := http.DefaultClient
req, err := http.NewRequestWithContext(context.Background(), "POST", "https://api.storekit-sandbox.itunes.apple.com/inApps/v1/notifications/test", nil)
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer "+token)
resp, err := httpClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
panic(err)
}
fmt.Println(string(body))
}
最後に
今回は、サーバ通知APIのテストをリクエストを利用するために、Apple Store Server API を利用する必要があったのですが、あまりGo言語を使った記事を見かけなかったので、書いてみました。
一応、調べて動かしながら書いたのですが、間違っているところがあればご指摘いただけると幸いです。