Carpe Diem

備忘録

セキュアなトークン管理方法

概要

クライアント↔サーバ間の認証・認可情報としてのトークン管理はWebサービスとしては必ずつきまとうものですが、一方できちんと実装しないとセキュアに管理はできません。

今回はそのトークン管理方法の一例を紹介します。

要件

今回の主な要件は以下です。

  • AuthサーバとResourceサーバは別で管理する(負荷特性が異なるので)
  • 認証するとAuthサーバはrefresh tokenとaccess tokenを返す
  • access tokenはJWT形式
  • access tokenはクライアントのオンメモリで管理する
  • access tokenの期限は短く(1時間以内)
  • refresh tokenを使ってaccess tokenを発行できる
  • refresh tokenはrevoke可能である
    • 認証情報に変更があれば(パスワード変更など)refresh tokenをrevokeできる
  • Resourceサーバは起動時などにAuthサーバから公開鍵を取得し、access tokenの署名検証に使用する

ネイティブクライアントの場合

ネイティブクライアントの場合、keychainなどセキュアな管理ストレージがあるためrefresh tokenを保存することができます。

認証時

認証時はID&PWなどを渡すことでrefresh token/access tokenを取得します。
refresh tokenはアプリのストレージ(keychainなど)に保存します。

f:id:quoll00:20210216050133p:plain

トークンのリフレッシュ時

access tokenのリフレッシュにはrefresh tokenをAuthサーバに渡すことで発行します。
refresh tokenが有効であればaccess tokenを発行し、revoke済みであれば再度認証させるようにします。

f:id:quoll00:20210216050204p:plain

Webブラウザの場合

Webブラウザの場合は基本的にセキュアでないため、refresh tokenをlocalStorageやIndexedDBなどに直接保存することはしません

refresh tokenはサーバ上で管理し、WebクライアントはCookieでセッションを保持します。

認証時

認証時はID&PWなどを渡し、レスポンスとしてaccess tokenとcookieにセッションIDを受け取ります。

f:id:quoll00:20210216060650p:plain

Cookieの設定として以下の属性は必須にします。

属性 役割
httpOnly XSS対策
JavaScriptで触れないように)
secure HTTPSでのみ
SameSite CSRF対策

session_idとrefresh tokenはペアで保持しておきます。
session_idとuserIdだけ紐付けていると、refresh tokenをrevoke&再発行してもこのセッションが有効なままになってしまうためです。

トークンのリフレッシュ時

access tokenのリフレッシュ時はCookieが自動送信されます。
session_idに紐づくrefresh tokenが有効かチェックして、有効であればaccess tokenを発行する流れです。

f:id:quoll00:20210216060709p:plain

Q&A

外部サービスを使うのは?

認証サービスに外部サービスを使うのは

  • 実装コスト
    • 多くのケースで似たような開発になる(=歯車の再発明)
  • セキュリティ
    • 独自で実装することで考慮漏れが起き脆弱性が残る

を考慮したときに大きなメリットを享受できます。

一方でそのSaaSにロックインされるということであり、

といった注意が必要です。

ほぼGCPだからFirebase Auth(Identity Platform)にロックインしても大丈夫だけど?

特定のパブリッククラウドを利用しており、そこが提供している認証サービスを使うのは先程のケースよりはクローズリスクなどが低減されます。

Identity Platform  |  ID プラットフォーム  |  Google Cloud

一方でこういったサービスは簡単に使えることセキュリティトレードオフの関係になっていたりします。

例えばWeb SDKのトークンはIndexedDBで管理されています。
こちらはlocalStorageと同様にJavaScriptでアクセスできるため、XSS脆弱性を残すこととなりセキュアとは言えません。

かといってセキュアに実装する場合は独自で対応する箇所が出てくるため、SaaSとしてのメリットが半減してしまいます。

まとめ

セキュアなトークン管理のアーキテクチャ例を紹介しました。

参考