概要 重要なポイント
トークンの保存方法の選択は、悪意のある攻撃からアプリケーションを守るうえで非常に重要です。
アプリケーションの種類ごとのシナリオを確認します。
使用している技術に最も適した方法を選択します。
API 呼び出しを行う SPA の保護には、特有の考慮事項があります。トークンやその他の機密データが クロスサイト スクリプティング (XSS) に対して脆弱にならず、悪意のある JavaScript に読み取られないようにする必要があります。
詳しくは、JWT Handbook および The Ultimate Guide to Next.js Authentication with Auth0 を参照してください。
Next.js アプリケーションを構築する際、認証が必要になるのは主に次のケースです。
ページにアクセスするとき
API ルートにアクセスするとき
アプリケーションがユーザーに代わって、Next.js アプリケーション外でホストされている API を呼び出すとき
サーバーを利用できる場合、アプリは Auth0 とのやり取りを処理してセッションを作成できますが、このモデルにはバックエンドがありません。すべての処理はフロントエンドで行われます。
ユーザーは Auth0 にリダイレクトされます。
ユーザーが正常にサインインすると、アプリケーションにリダイレクトされます。
クライアントサイドで Auth0 との code の交換を完了し、ユーザーの id_token と access_token を取得してメモリに保存します。
従来の Web アプリ
ネイティブ/モバイルアプリ
シングルページアプリ
アプリで API 呼び出しを必要としないサインインシナリオを使用している場合、必要なのは IDトークンのみです。これを保存する必要はありません。検証したうえで、必要なデータを取得できます。 アプリがユーザーに代わって API を呼び出す必要がある場合は、アクセストークンと、必要に応じてリフレッシュトークンが必要です。これらはサーバー側またはセッションクッキーに保存できます。Cookie は暗号化されている必要があり、最大サイズは 4 KB です。保存するデータが大きい場合、セッションクッキーにトークンを保存する方法は現実的ではありません。 これらのシナリオでは、次のフロータイプを使用します。 OS が提供する安全なストレージにトークンを保存し、そのストレージへのアクセスを制限してください。たとえば、Android では KeyStore、iOS では KeyChain を活用します。 これらのシナリオでは、次のフロータイプを使用します。 トークンの保存、セッション管理、その他の詳細を処理するには、Auth0 SPA SDK の使用を推奨します。 SPA が、SPA のドメインと Cookie を共有できるドメインから提供される API だけを呼び出す場合は、トークンは不要です。OAuth は追加の価値をもたらさない一方で攻撃ベクトルを増やすため、従来の Cookie ベースのアプローチを優先し、使用は避けるべきです。 SPA が異なるドメイン上にある複数の API を呼び出す場合は、アクセストークンと、必要に応じてリフレッシュトークンが必要です。
SPA のバックエンドで API 呼び出しを処理できる場合は、次を使用してサーバー側でトークンを処理する従来の Web アプリケーションと同様に機能します。
SPA のバックエンドで API 呼び出しを処理できない場合は、SPA バックエンドにトークンを保存するモバイルアプリケーションと同様に機能しますが、SPA は API へのリクエストを実行するためにバックエンドからトークンを取得する必要があります。バックエンドから SPA にトークンを安全に転送できるように、バックエンドと SPA の間でプロトコルを確立する必要があります。
対応するバックエンドサーバーがない SPA の場合は、ログイン時に新しいトークンを要求し、永続化せずにメモリに保存する必要があります。その後 API を呼び出す際は、メモリ内のトークンのコピーを使用します。
OAuth2 仕様に準拠するため、ブラウザーが /token エンドポイントからリフレッシュトークンを要求した場合、Auth0 はそのクライアントで リフレッシュトークンローテーション が有効になっている場合にのみ リフレッシュトークン を返します。 詳細については、GitHub の Auth0 SPA SDK を参照してください。
Auth0 では、最も安全な選択肢として、ブラウザのメモリにトークンを保存することを推奨しています。トークンの送信と保存の処理には Web Workers を使用するのが、トークンを保護する最善の方法です。これは、Web Workers がアプリケーションの他の部分とは別のグローバルスコープで実行されるためです。既定の保存オプションとして、Web Workers を活用したインメモリ保存を使用する Auth0 SPA SDK を使用してください。
Web Workers を使用できない場合、代替手段として、プライベートメソッドをエミュレートするために JavaScript クロージャ を使用することを Auth0 は推奨しています。
トークンの種類に応じて Web Workers と JavaScript クロージャを活用するには、既定の保存オプションとしてインメモリ保存を使用する Auth0 SPA SDK を使用してください。
ブラウザストレージのインメモリ方式では、ページの再読み込み後やブラウザタブ間でデータは保持されません 。
ブラウザーのローカルストレージの使用は、ブラウザーの制限 (たとえば ITP2) により、iframe から アクセストークン を取得する必要がある仕組みや、ドメイン間の Cookie ベースの認証が利用できない場合に、有効な代替手段となることがあります。
ブラウザーのローカルストレージにトークンを保存すると、ページの再読み込み後やブラウザーのタブをまたいでも保持されます。ただし、攻撃者がクロスサイトスクリプティング (XSS) 攻撃によって SPA 上で JavaScript を実行できた場合、ローカルストレージに保存されたトークンを取得される可能性があります。XSS 攻撃の成功につながる脆弱性は、SPA のソースコードに存在する場合もあれば、SPA に含まれるサードパーティの JavaScript コード (Bootstrap、jQuery、Google Analytics など) に存在する場合もあります。
SPA で implicit フロー (代わりに PKCE を使用する認可コードフローの使用を推奨します) または hybrid フローを使用している場合は、セキュリティリスクを低減するために、トークンの絶対有効期限を短くできます。これにより、反射型 XSS 攻撃の影響は軽減できます (ただし、持続型 XSS 攻撃には効果がありません) 。有効期限を短くするには、Dashboard > APIs > Settings > Token Expiration For Browser Flows (Seconds) に移動します。
ドメイン外のソースから取り込むサードパーティ JavaScript コードは、必要最小限 (jQuery、Bootstrap、Google Analytics などへのリンクなど) に抑えてください。サードパーティ JS コードを減らすことで、XSS 脆弱性の可能性を低減できます。また、取得したリソースが予期しない改変を受けずに配信されていることを確認するため、可能な場合はサードパーティスクリプトに対して Subresource Integrity (SRI) チェックを実施することも、セキュリティ向上につながります。