SPAアプリでOAuth 2.0/Open ID Connect (OIDC)の実装を検討しているのですが、調べているうちに様々な注意点が出てきたのでまとめておきます。
まずはOauth 2.0における注意点。
認可のフローは以下4つのフローがありますが、
- Authorization Code Grant
- Implicit Grant
- Resource Owner Password Credentials Grant
- Client Credentials Grant
セキュリティを考慮すると使えるフローとしては実質1と4しか無いと考えて良さそうです。
(2はIETFで非推奨が決定済、3はSPAアプリケーションに直接パスワードを入力することになるので不可)
SPAでは2を実装し、BackendのMicroservice間の通信は4を実装するイメージ。
こちらのYoutubeが参考になります。
OpenID Connect & OAuth 2.0 – Security Best Practices - Dominick Baier
そして、実装時には以下についても詳細な検討が必要です。
考慮が必要な実装 | 出自 | 実装領域 | 参考サイト | 目的 |
---|---|---|---|---|
state | OAuth 2.0 protocol RFC6749 | アプリ | OpenID Connectのstateとnonceの違いがわからなかった - Qiita | CSRF対策 |
nonce | OpenID Connect specification | アプリ | OpenID Connectのstateとnonceの違いがわからなかった - Qiita | ID Token偽造対策 |
PKCE (Proof Key for Code Exchange by OAuth Public Clients) | OAuth 2.0 protocol RFC7636 | アプリ | PKCE: 認可コード横取り攻撃対策のために OAuth サーバーとクライアントが実装すべきこと - Qiita | 認可コード横取り攻撃対策 |
DPoP (Demonstration of Proof-of-Possession at the Application Layer) | draft-ietf-oauth-dpop-01 | アプリ | 図解 DPoP (OAuth アクセストークンのセキュリティ向上策の一つ) - Qiita | Tokenをアプリケーションレベルで "Sender-Constrained Token" にする |
mutual TLS | OAuth 2.0 RFC8705 | インフラ | 図解 DPoP (OAuth アクセストークンのセキュリティ向上策の一つ) - Qiita | Client/Server間の通信をTLSで限定する |
また、Tokenをどこに保存するかを検討する必要があります。
Cookie | Local storage | Session storage | |
---|---|---|---|
特徴 | BackendのAPIはSPAと同じドメインとする必要がある Javascriptからのアクセス不可(http-only属性による) | 期限なくtokenが保存されブラウザセッションが閉じてもデータは残る Javascriptから常にアクセス可能 | tokenはセッション内でのみ有効でtabもしくはWindowをとじると削除される Javascriptから常にアクセス可能 |
リスク | CSRF (Croos Site Request Forgery) | XSS (Cross-site scripting) | XSS (Cross-site scripting) |
Cookieに紐付ける場合は情報を暗号化した上で以下のオプションも考慮が必要です。
- httpOnly
- SameSite=strict
- secure=true
- クッキー全体のサイズ制限(4KB)
Tokenをどこに保存するかはこちらも参考になります。
SPAの場合はBrowser in-memoryとシナリオもあるようなのでこれはもう少し深堀が必要です。
Auth0 - Token Storage
その他、以下のサイトやオンラインコースも参考になります。
pluralsight - microservices-security-fundamentals
5.4 Handling of the Access Tokenより