Sign in with Apple で利用される各種 ID, Key, Email 等とその適用範囲

自分のブログに以下の2記事書いてきたけど、ちょっと Qiita の実験のためこちらにも (2) の方の一部を転載。

* [Sign in With Apple の特徴分析 (1)](https://oauth.jp/blog/2019/06/08/sign-in-with-apple-analysis/) 
* [Sign in With Apple の特徴分析 (2)](https://oauth.jp/blog/2019/06/12/sign-in-with-apple-analysis-2/) 

---

Sign in with Apple で利用される各種 ID の適用範囲をまとめました。
これだけそろってれば、UX 面はともかく、一通り自社サービスの DB 設計レベルに落とせるんでは無いかと思います。

アプリ1つしか出してない事業者さんには大して複雑では無いですけど、1 Team で複数アプリ出してる事業者さんとか、複数 Team ID でアプリ出してる事業者さんとかにとっては、他の IdP と同じ感覚で導入すると、いろいろ齟齬が出てくるのでは無いかと思うので、ご注意ください。

### OAuth Client に紐づく IDs etc.

* Team ID
    * 個人向け Apple Developer Account では Developer Account に1つ
    * Enterprise 向け Apple Developer Account での話はしらない
* App ID
    * App Store に並べるアプリ毎に1つ
    * MacOS App と iOS App では別 App ID
    * Native SDK で Sign in with Apple する場合の Client ID に相当
    * App ID に対して Sign in with Apple の設定をする際には以下が必要
        * Primary App ID の指定
    * Sign in with Apple の設定を通じて Primary App ID に紐づく
* Service ID
    * App Store に並べるアプリには紐づかない ID
    * 現状この Service ID を使ってできることは Sign in with Apple のみ
    * Service ID に対して Sign in with Apple の設定をする際には以下が必要
        * Primary App ID の指定
        * Web Domain の設定と Domain Verification
        * Return URIs (= redirect_uri) の指定
            * 複数可
            * 上記 Verified Domain 外の URL でも指定可
                * Domain Verification の存在意義は不明..
    * Native SDK の外で Sign in with Apple する場合の Client ID に相当
    * Sign in with Apple の設定を通じて Primary App ID に紐づく
* Primary App ID
    * App ID および Service ID に対して Sign in with Apple の設定をする際に指定
    * Primary App ID 単位で Key を発行
    * Primary App ID 単位で Client Access を Revoke
    * (たぶん) Primary App ID 単位で Private Email を発行
* Key
    * Client Secret に指定する JWT に署名するための EC 秘密鍵
    * Primary App ID に紐づく
    * 1つの Primary App ID に複数の Key を発行可能
* Client Secret に指定する JWT
    * iss
        * Team ID
    * aud
        * Apple IdP の Issuer Identifier
    * sub
        * Native SDK で code を受け取った場合は当該アプリの App ID
        * Native SDK 以外で code を受け取った場合は当該サービスの Service ID
        * code を access_token と交換する役目を負う Backend Server の Client ID とは限らない点に注意
    * iat
        * 現在時刻 (UNIX Timestamp)
    * exp
        * 現在より未来かつ6ヶ月以内の時刻 (UNIX Timestamp)
        * 通常は Token Request 毎に動的に JWT を生成し数分後くらいの exp を指定するものと思われる
    * 署名鍵
        * 当該 Client に紐づく Primary App ID に紐づいた Key
* Private Email Relay Service 設定
    * Team ID に紐づく
    * 当該 Team ID 配下の全 App ID / Service ID に対して発行された Private Email Address にメール送信できる送信元ドメイン & メールアドレスを指定
    * 10 ドメインまでしか登録できない
        * 10+ サービスを同一 Team ID 配下に登録しつつサービス毎に送信元ドメイン変えるとかは無理かも

## User に紐づく IDs etc.

* ID Token の sub
    * Team ID 単位で異なる PPID
* Private Email
    * 現状これがどの単位で異なる値となるのか不明 (実機の iOS 13 beta も Simulator も挙動が不安定)
        * Team ID 単位？
        * Primary App ID 単位？ <= Revoke 単位見る限りたぶんこれ
        * App ID 単位？
        * Primary App ID 単位？
    * Revoke 毎に変わる
        * sub は Revoke 前後でも変わらないんだしメアドだけ変わる意味は無いのだが...
    * 当該アドレスに紐づく Team ID の Private Email Relay Service に登録された送信元ドメイン & メールアドレスからしかメールが届かない
        * Revoke 画面で Revoke はせずにメール転送を OFF にすることも可能
    * 単一 Team ID 内に複数の Primary App ID がある場合は単一 sub に複数 Private Email を紐づけて保存する必要あり
        * sub は Team ID 単位でメアドは Primary App ID 単位であることからくる現象
            * ※ あくまで Private Email が Primary App ID 単位で発行されるという前提で話をしている
        * Email の転送 ON/OFF 設定は Revocation 単位 (= Primary App ID 単位) なので、転送 OFF したつもりが別アプリ向けメアドにメール来たりすると問題
* Client Access の Revocation
    * Primary App ID 単位