概要
- Sign In With Appleをアプリに組み込む際に調べたことをまとめました。
- 今回の内容はサーバーサイドのみの内容となります。
開発環境
- 使用言語:PHP(v7.3.11)
- フレームワーク:Laravel(v7.20.0)
- DB:Sqlite
事前準備
- Apple Developerに登録してSign In With Appleの設定をしておく
以下の値、ファイルを取得 - アプリのバンドルID
- KeyID
- 秘密鍵の.p8ファイル(1度しかダウンロードできないので注意)
- TeamID
認証の流れ
以下の手順で認証を行いました
- クライアント側でSign In With Appleの認証をする
- 認証結果のcode値をサーバに送る
- サーバ側でcodeの検証
- 検証結果がJWT形式で返ってくるのでJWTデコードする
codeの検証
検証はAppleが提供している検証APIに以下のパラメータをPOSTして行います。
API:POST https://appleid.apple.com/auth/token
パラメータ
- client_id:アプリのバンドルIDのこと
- client_secret
- code:クライアント側から取得する
- grant_type:検証なので'authorization_code'を設定
- redirect_uri:あらかじめDevelopperサイトで登録しておく
client_secretの作成
- client_secretとは検証に必要なJWTでエンコードされた値
- JWTとは3種類の文字列をドットで繋げた文字列
- JWTの作成にはfirebaseが提供しているライブラリを使用(他にもありましたが今回は以下を使用しました)
client_secret作成に必要な値
- alg:ES256
- kid:KeyID
- iss:TeamID
- iat:現在時刻
- exp:有効期限
- aud:'https://appleid.apple.com'(固定)
- sub:ClientID(アプリのバンドルID)
今回は以下のように実装しました
$key = openssl_pkey_get_private('file://'.PRIVATE_KEY_PASS); // 秘密鍵ファイルのパス
$now = time();
$expire = time() + 86400 * 180; // 有効期限を半年に設定
$payload = array(
'iss' => TEAM_ID,
'iat' => $now,
'exp' => $expire,
'aud' => 'https://appleid.apple.com',
'sub' => CLIENT_ID
);
return JWT::encode($payload, $key, 'ES256', KEY_ID); // ES256は署名アルゴリズム
検証結果からユーザーを一意に特定するIDを取得
- ユーザーを特定する文字列はid_tokenの中に含まれているのですが、JWT形式のためそのまま取り出すことはできません。
- id_tokenは「ヘッダー.ペイロード.署名」のように情報をドット区切りで持っています
- ユーザーを特定するIDはペイロードの中に含まれる「sub」値がそれに該当します
以下のようにしてsub値を取得しました
$jwt_token = expload('.', 'id_token');
$payload = base64_decode($jwt_token[1]);
$decode_payload = json_decode($payload, true);
$sub = $decode_payload['sub'];