LoginSignup
4
4

More than 3 years have passed since last update.

Rails Backend で Sign in with Apple の認証処理を実装する

Posted at

はじめに

とある理由により Sign in with Apple (以下、SIWA) の実装をしなければならなくなったのですが、Appleの公式ドキュメント を読んでいても、 iOSアプリ + Railsバックエンド という構成のサービスが、一体どのようにして SIWA 機能を実装するかなどの手順や情報が乏しすぎて非常に理解に苦しんだので、OpenID Connect などの知識と組み合わせながら、実装した結果とSIWAで調べたことなどをここに残します。

前提

こちらの記事は、OAuth2認証OpenID Connect の知識を前提に書いております。
僕は、以下の記事が参考になりました。
https://qiita.com/TakahikoKawasaki/items/200951e5b5929f840a1f
https://qiita.com/TakahikoKawasaki/items/498ca08bbfcc341691fe

アプリの実装に関しては一切触れていません。あくまでサーバ側のみです。

各種Appleでの設定に関してはこことかが参考になりそうです。
https://medium.com/identity-beyond-borders/how-to-configure-sign-in-with-apple-77c61e336003

実装例

認証処理の流れと全体像

  1. ユーザが アプリから AppleID での認証を開始する
  2. アプリが Appleから authorization_codeid_token を入手する
  3. アプリが 2で手に入れた情報を サーバ側に渡す
  4. サーバが authorization_codeを Appleの認可サーバに渡す
  5. Appleの認可サーバが authorization_codeと引き換えにid_tokenなどの情報を サーバに返す
  6. サーバが 3で手に入れた id_token 5で手に入れたid_token 検証する
  7. サーバが リソースへのアクセスを ユーザに付与する (※こちらは各種サービスの実装依存なので割愛)

Untitled Diagram-Page-1.jpg

シーケンス図で描くと以下のようになります
bPEzRkim38LtFmNXvTuxv0KoN2H0bonjWQ1RW82Hc5g8AmaKxRHz-kh7AfIWImTBiCbppaV1sWH1bkbjx0QZ2SxEoSczTnqgSGmlWHWmm1JtpiT6eun7Az0_efYPjjuVx5_pjF_NfpRq_hPh-xo3FV5C7DiOpHXM9rGNihe8GgxTQRmVgTgDb57CZ4A58Ysm-f-AQp3MJm9PiNi0j1eyXd1rh1jPeehF8Xff3Tj91h8nihh2.png

SIWAの細かい話

認証処理の実装について

上記の 1と2 の処理において Apple Server は [authorization_code および id_token] を アプリに返却しているため、OpenID Connect Section 3. を根拠に Sign in with Apple は "Hybrid Flow" を採用していることが導き出せる。

Hybrid Flow の場合、
https://openid.net/specs/openid-connect-core-1_0.html#HybridFlowSteps
に記載されている方法でユーザの情報を取得しなければならないことが明記されている。
(以下では、SIWA仕様に読み替えて、手順を簡略化する)

  1. 「クライアント」が、Appleの認可エンドポイントにエンドユーザの認証を行うためのリクエストを送る。
  2. Apple の認可エンドポイント から「クライアント」に authorization_code とレスポンスタイプによって1つ以上の付加パラメータを送る。SIWA場合、付加パラメータが id_tokenname である。
  3. 「クライアント」が、authorization_code を利用して Apple の トークンエンドポイントにリクエストを送り、id_tokenaccess_token が含まれるレスポンスをもらう。
  4. 「クライアント」は トークンエンドポイントから返ってきた id_token の検証を行い エンドユーザの識別情報を得る。

ここで、「クライアント」(client)と言っているのは 「アプリ + サーバ」 であることに留意したい。
そのため、「誰が」認証エンドポイントにリクエストを投げ、「誰が」トークンエンドポイントにリクエストを投げて検証するかは、完全に実装する側に委ねられている。
OAuth 2.0 RFC 6749 の clientの定義より

client
An application making protected resource requests on behalf of the
resource owner and with its authorization. The term "client" does
not imply any particular implementation characteristics (e.g.,
whether the application executes on a server, a desktop, or other
devices).

1と2 (ユーザ認証処理) をアプリが行い、3と4 (認証情報の検証)に関しては サーバが行うような実装とするのが適切であろう。

サーバ側で行わなければならない検証項目は、OpenID Connect Section 3.3.3.5. を根拠に特に以下の2つである。

A. authorization_code の検証
B. id_token の 検証

以下に、それぞれについて詳しく書く。

A. authorization_code の検証について

検証方法
検証内容
  • アプリからサーバに送られてきた authorization_codeid_token とペアであることを検証する。
    • この検証に失敗する場合、第三者が不正に取得した authorization code あるいは、id_token を忍び込ませている可能性がある

B. ID Token の検証について

検証方法
検証内容について
  • 発行者(iss)情報が、両方のid_token で一致していること
  • ユーザの一意な識別子(sub)が、両方のid_token で一致していること
  • nonce 値が、両方のid_token で一致していること
    • All Claims about the Authentication event present in either SHOULD be present in both. の解釈より
  • email などのユーザ情報に関する値が 両方のid_token で存在する場合に一致していること
    • If either ID Token contains Claims about the End-User, any that are present in both SHOULD have the same values in both. の解釈より
  • id_token が失効していないこと
    • 失効しているトークンを受けないようにするため
  • id_token の jwt の署名を確認すること
    • Appleの秘密鍵によって、署名が行われていることを確かめることで発行者情報を強固にする
    • 逆に署名が誤っている場合は、元のトークン情報が改ざんされている可能性がある

SIWA と 一般的な OpenID Connect 準拠の認証方法との違いについて

丁寧にも、OpenID Connect財団の方たちが、「SIWA が 一般的なOpenID Connectの仕様と、どういう点で異なるのか」を Peculiarities の欄で全て列挙してくれている。
https://bitbucket.org/openid/connect/src/default/How-Sign-in-with-Apple-differs-from-OpenID-Connect.md
以下、Peculiarities 欄を一部訳すると以下のような事が書かれている。

  • Discovery document 用のエンドポイントが提供されていないので、開発者がエンドポイントやスコープ、署名アルゴリズムなどの情報を得たいと思ったときに、毎度Appleのドキュメントを精読する必要があること。本来は Discovery document を用意するのが推奨されている。

  • UserInfo エンドポイントが提供されていないので、ユーザに関する情報は全て(失効する・潜在的に大きなデータになり得る)id_token に含まれる事になっていること。

  • アプリケーションからの scope の指定は、「最も最初のリクエスト(すなわち連携時)」のときのみ有効になっている。もし、連携時のときに 氏名(name)だけの scope を指定してユーザが許可した場合、そのユーザの email は二度とアプリケーション側から取得しに行くことは出来ない。
    (アプリケーションからユーザ情報の取得を行う処理の不自由さを指している)

... など、かなり独自の実装が行われている事が伺える。

公式ドキュメント

Apple

OpenID Connect

OAuth 2.0

その他の参考資料

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4