このリポジトリは Expo のAuthSessionを使ったAuthorization Code Flow with PKCE extensionを実装したサンプルコードです。このリポジトリでは次のトピックスを扱います。
- iOS/ Web での Expo AuthSession の実装
- Facebook 認証
- Twitter OAuth2による認証
- Twitter 3-legged authorizationによる認証(Twitter OAuth 1-0a)
demo.mov
OAuth とはユーザーにリソースへの限定的なアクセスを許可するための仕組みのことで、Browser-based OAuth Flows ではこの処理をブラウザとリダイレクト URI を使って行います。
OAuth ではプライバシーとセキュリティ保護をテーマに色々なプラクティスが考案されてきました。ここでは代表的な OAuth Flow であるImplicit Flow
とAuthorization Code Flow with PKCE extension
を題材に現在のベストプラクティスを説明します。
- 現在のベストプラクティスは
Authorization Code Flow with PKCE extension
- Public Client と認可サーバーとのやり取りには
state parameter
を使って CSRF 対策をしよう - リダイレクト URI は認可サーバーに登録されたものと厳密に一致させよう。Ex. 末尾に/があるかないかも含めてチェック!
- フロントチャンネルでアクセストークンをやり取りしない!なので Implicit Flow は非推奨。 認可サーバーとのアクセストークンのやり取りは登録済みの Confidential client で行う!
- 秘密鍵はフロントに出さない!
主体 | 概要 | 例 |
---|---|---|
Authorization Server | ユーザーに developer によるリソースへのアクセスを許可するかを確認し、アクセストークンを発行する。認可サーバーに登録された Public/ Confidential Client 以外からのリクエストを拒否する。 | |
Public Client | ソースコードが公開されているユーザーのインターフェースとなるクライアント。秘密鍵を持つことは許されない。認可サーバーからの認可レスポンスを登録されたリダイレクト URI で受け取る。 | Web SPA/ Mobile アプリ |
Confidential Client | 認可サーバーに登録されたバックエンドサーバー。クライアント ID、秘密鍵、リダイレクト URI など登録された情報で認可サーバーにアクセストークンを要求する。 | バックエンド |
endpoints | 概要 |
---|---|
Authorization Endpoint | 認可サーバーが提供するユーザーの認可を求めるためのエンドポイント。操作しているユーザーにログイン認証 -> 権限の認可を求めるのがよくある流れ。ユーザーによる認可が完了したら Public Client に認可レスポンスをリダイレクトする。 |
Token Endpoint | 認可レスポンスで受け取った認可コードをアクセストークンに交換するためのエンドポイント。Confidential client が認可サーバーとやり取りする。認可コード単体では何の効果もない。 |
Flow | 概要 |
---|---|
Implicit Flow | Authorization Endpoint からの認可レスポンスで Public Client が直接アクセストークンを受け取る。認可レスポンス横取り攻撃のため現在では非推奨となっている。 |
Authorization Code Flow with PKCE extension | 現在のベストプラクティス。Authorization Endpoint からの認可レスポンスで Public Client は短命の認可コードを受け取り、それを Confidential client にわたす。Confidential client は認可サーバーの Token Endpoint に対して認可コードを使ってアクセストークンを発行してもらう。この際、登録情報や秘密鍵、PKCE を使ってセキュアな発行要求をする。 |
フロントチャンネルでやり取りされるリダイレクト URI にアクセストークンを含むため、リダイレクト URI を横取りされたり、ブラウザ履歴から漏洩したりと様々なリスクに晒されています。そのため現在ではフロントチャンネルでアクセストークンを直接やり取りする Inplicit Flow は非推奨となっています。
- Interception of the Redirect URI
- Access Token Leak in Browser History
- Manipulation of Scripts
- Access Token Leak to Third Party Scripts
- Implicit Flow にはない Token Endpoint が Flow に追加されている。
- フロントチャンネルでは短命かつそれ自体ではリソースにアクセスできない認可コードを受け取る。
- 認可コードとアクセストークンの交換は、登録されたバックエンドサーバー(Confidential client)が秘密鍵などと一緒に行い、フロントチャンネルでアクセストークンを露出させない。
Authorization Endpoint
とToken Endpoint
への実行が同一者によって行われたことを証明するための仕組み。codeVerifier
というランダムの文字列をPublic Client
で生成して、Sha-2 アルゴリズム でcodeChallenge
にハッシュ化する。[注]Confidential Client
で発行すべきとの意見もあります。Public Client
がAuthorization Endpoint
を叩くときにcodeChallenge
を URL に付与して、認可サーバーに実行者を認識してもらう。Confidential Client
がToken Endpoint
を叩くときにcodeVerifier
を付与して、認可サーバーにAuthorization Endpoint
と同じ実行者がアクセストークンを要求していることを認識してもらう。- これにより認可コードの横取り攻撃対策となっている。
- OAuth 2.0 全フローの図解と動画 https://qiita.com/TakahikoKawasaki/items/200951e5b5929f840a1f
- OAuth 2.0 for Browser-Based Apps https://datatracker.ietf.org/doc/html/draft-parecki-oauth-browser-based-apps
-
expo にサインアップして、アカウント名を取得
https://expo.dev/ -
twitter dev > User authentication settings
https://developer.twitter.com/
リダイレクト URI を登録https://auth.expo.io/@{Expo Account Name}/expo-authsession-authcodeflow
,https://localhost:19006/twitterOAuth2
,https://localhost:19006/
-
facebook dev > Facebook Login setting
https://developers.facebook.com/
リダイレクト URI を登録https://auth.expo.io/@{Expo Account Name}/expo-authsession-authcodeflow
,https://localhost:19006/
cp .env.sample .env
### you get credential info at Authorization Server(Twitter/ Facebook), and write them in .env
### clone source
git clone git@github.com:Minminzei/expo-authsession-authcodeflow.git
cd expo-authsession-authcodeflow
yarn
### docker
docker-compose up -d
docker-compose exec app bash
yarn server
### simulatar
yarn ios
yarn web