CYBIRD Advent Calendar 2024 22日目担当の@cy-tsuzawaです。
21日目は@R_araiさんの「AGPの更新でBuildConfig.VERSION_CODEが参照出来なくなったお話」でした。
はじめに
普段はサーバーサイドエンジニアをしています。
今回、Sign in with Apple を使用しているアプリを別の開発者チームに移行する機会があり、その時に直面した課題やおこなった作業について書いていきたいと思います。
概要
Sign in with Apple を使用しているサービスを別の開発者チームに移行する場合、移行後に既存のアカウントにログインできない状況が発生することがあります。
原因として、Sign in with Apple を使用してユーザーが認証をおこなう際に、「メールを非公開」を選択するとprivaterelay.appleid.com
のようなメールアドレスが自動生成されるのですが、生成にチームIDやキーID等のチーム固有の情報が使用されるためとなります。
ちなみに自動生成されたメールアドレスは以下で確認できます。
iPhoneの設定 > Apple ID > サインインとセキュリティ > Apple でサインイン > 対象のアプリ
Appleにて移行手順について詳細な記事が公開されていますが、結構手順が多く準備に時間がかかるので注意が必要です。
準備
記事を確認すると、以下の手順が記載されています。
- ユーザーアクセストークンを取得する
- client_secret (JWT) の生成
- 転送識別子を生成する
- 移行先のチームに転送識別子を共有
それぞれ1つずつ実行していきます。
ユーザーアクセストークンを取得する
ユーザーアクセストークンを取得するには、移行元の client_id
と client_secret
を取得する必要があります。
client_id
は、App ID
または Services ID
を指定します。Sign in with Apple を使用しているのがアプリなのかWebなのかで指定するIDが変わります。
client_secret
の取得には、JWTの生成が必要なため次の項目で説明します。
client_secretを取得する
client_secret
は こちらに生成手順が記載されています。
生成には、以下の情報が必要です。Apple Developer サイトで確認できます。
- kid:Certificates, Identifiers & Profilesにて作成されている Sign In with Apple 用のキーのID
- iss:チームID
- sub:App ID または Services ID
情報が揃ったら、kidの秘密キーで署名されたJWTを作成します。
Pythonで作成してみました。
import pathlib
from datetime import datetime, timezone, timedelta
import jwt
header = {
"alg": "ES256",
"kid": kid
}
payload = {
"iss": iss,
"iat": datetime.now(timezone.utc).timestamp(),
"exp": (
datetime.now(timezone.utc) + timedelta(days=1)
).timestamp(),
"aud": "https://appleid.apple.com",
"sub": sub
}
client_secret = jwt.encode(
payload,
(pathlib.Path('secrets/AuthKey_XX.p8')).read_text(),
algorithm="ES256",
headers=header
)
これでclient_secret
の準備ができました。
ユーザーアクセストークンをPOSTメソッドで取得する
client_id
と client_secret
が取得できたので、ユーザーアクセストークンを取得します。
import requests
access_token_response = requests.post(
"https://appleid.apple.com/auth/token",
data=dict(
grant_type="client_credentials",
scope="user.migration",
client_id=client_id,
client_secret=client_secret
),
headers={"Content-Type": "application/x-www-form-urlencoded"}
)
access_token = access_token_response.json()
以下のようなレスポンスが返ってくれば成功です。
{
"access_token":"XXXXXXXXXXXXX",
"token_type":"Bearer",
"expires_in":3600
}
転送識別子を生成する
ユーザーアクセストークンの取得ができたら、やっと転送識別子の生成です。
今まで使用した情報の他に、以下の情報が必要になります。
- sub:Apple が提供するチームスコープのユーザー識別子。
000000.00000000000000000000000000000000.0000
のような構成 - target:移行先のチームID
transfer_sub_response = requests.post(
"https://appleid.apple.com/auth/usermigrationinfo",
headers={"Authorization": "Bearer " + access_token['access_token']},
data=dict(
sub=sub,
target=target,
client_id=client_id,
client_secret=client_secret
)
)
transfer_sub = transfer_sub_response.json()
以下のようなレスポンスが返ってくれば成功です。
{
"transfer_sub":"XXXXXXXXXXXXX"
}
移行先のチームに転送識別子を共有
ユーザー分の転送識別子の生成が終わったら、転送識別子を移行先に共有します。
移行先は転送識別子を使用して、ユーザーの移行先でのメールアドレスを取得することができます。
最後に
Sign in with Apple を使用したサービスを開発する機会は多いと思うのですが、ユーザーの移行の機会はほとんどないので、貴重な経験となりました。
移行後の猶予が60日間となっているので、計画的な準備・移行作業をおすすめします。
ここまで読んでいただきありがとうございました!
明日のCYBIRD Advent Calendar 2024 23日目は@cy-yamakenさんの記事です。お楽しみに!