SPA(シングルページアプリケーション)の認証認可は簡単ではありません。クライアントのみでクライアントシークレットを保持できないため、通常のAuthorization Code Flowを使用できません。その代わりに、PKCE(Authorization Code Flow with Proof Key for Code Exchange)を導入するのが一般的です。しかし、PKCEにも問題があります。
PKCEの問題
問題1 アクセストークンの有効期限が長めのため、漏れたらセキュリティ上のリスクが高い
アクセストークンを更新する手段がないから、有効期限が切れるとユーザーは再度ログイン、あるいはAuth0の認証サーバーへリダイレクトする必要があります。頻繁にログインを求めるのはUXが悪いので、アクセストークンの有効期限を長めに設定するのが回避策です。しかし、アクセストークンの有効期限が長いと、漏れた場合のセキュリティ上のリスクがもちろん高くなります。
問題2 アクセストークンの有効期限を長めにしてもUXが悪くなる
XSS攻撃によってアクセストークンの漏れるリスクを軽減するために、アクセストークンをlocalStorageではなく、メモリに保存する必要があります。セキュリティ向上ができるが、下記2つの問題が生じます。
- 画面をリロードすると、Auth0の認証サーバーへリダイレクトされるため、画面が何回も飛ぶことになり、UXが悪くなる。
- 保存ボタンを押した時に、アクセストークンの有効期限が切れている場合、Auth0の認証サーバーへリダイレクトされるため、ユーザが入力される内容が消えてしまう。
PKCE問題の流れ
リフレッシュトークンの導入
PKCEの問題を解決するために、リフレッシュトークンが必要となります。リフレッシュトークンを導入すると、アクセストークンの有効期限が切れても更新できるため、アクセストークンの有効期限を短めに設定できます。
リフレッシュトークンがわからない方はAuth0のドキュメントをご覧ください。
リフレッシュトークンを導入したら処理の流れは下記のようになります。
リフレッシュトークンの導入後の流れ
リフレッシュトークンの導入によって、画面をリフレッシュしても、Auth0の認証サーバーへリダイレクトされることがなくなり、UXが改善されます。アクセストークンの有効期限を短めに設定できるため、セキュリティ上のリスクも軽減できます。
リフレッシュトークンの問題
リフレッシュトークンだけでは銀弾ではありません。画面をリフレッシュとアクセストークンの有効期限が切れる時、PKCEのようなリダイレクトを防ぐために、2つの設定が必要となります。
- リフレッシュトークンをメモリではなく、localStorageに保存
- リフレッシュトークンの有効期限を長めに設定
しかし、これらの設定をすると、アクセストークンのセキュリティ問題及びUXを改善できたが、そもそもクライアントシークレットのようなリフレッシュトークンが漏れたらアクセストークンの取り放題でセキュリティ面でのリスクがもっと深刻になります。
この問題を解決するために、この文章の主人公ーーリフレッシュトークンのローテーションが登場します。
リフレッシュトークンのローテーション
リフレッシュトークンを使うなら、リフレッシュトークンのローテーションが必須だと過言ではありません。ローテーション仕組みを通して、リフレッシュトークンが漏れたとしても、被害を軽減できます。
Auth0の認証サーバー側がリフレッシュトークンの不正利用を検知できたら、すべてのリフレッシュトークンを無効にする上で、ログインしているユーザを強制的にログアウトします。
リフレッシュトークンローテーションの仕組みの説明はAuth0のドキュメントに詳しく書いてあるので、割愛します。詳しくはAuth0のドキュメントをぜひご覧ください。
完了
SPAの認可なら、リフレッシュトークンを使いましょう。その上に、セキュリティのリスクを軽減するために、リフレッシュトークンのローテーションを有効にしましょう。
では、Happy Auth0 Life!