会員登録すると
学習することができます。
会員登録する(無料)
学習することができます。
登録済みの方はこちら
ログイン
学ぶ目的
ログインの状態をどこに持つか
ログインしたあと、「この人はログイン済み」という状態をどこかに持つ必要があります。持ち方は大きく2つです。
| 持ち方 | 仕組み | 途中で止めるには |
|---|---|---|
| サーバーに持つ | ブラウザには意味の無いランダムな番号だけを渡し、中身はサーバーが覚える | サーバーの記録を消せば、すぐ止まる |
| トークン自体に持つ | 誰か・権限・期限をトークンの中に書き、署名で改ざんを防ぐ | 期限が来るまで止まらない(止めるには別の仕組みが要る) |
後者の代表が JWT(JSON Web Token)です。3つの部分(ヘッダー・中身・署名)を「.」でつないだ文字列です。なお、Rails の標準のセッションも、中身を暗号化して Cookie に入れる「自分で持つ」側の方式です。
JWT の中身は誰でも読める
手元で JWT を作り、中身の部分を Base64 から戻してみました(Ruby の jwt 3.2.0 で確認)。
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI0MiIsInJvbGUiOiJtZW1iZXIiLCJleHAiOjE3OTMwMDAwMDB9.E8pvJJiZz6lE...
Base64.urlsafe_decode64("eyJzdWIiOiI0MiIsInJvbGUiOiJtZW1iZXIiLCJleHAiOjE3OTMwMDAwMDB9")
# => {"sub":"42","role":"member","exp":1793000000}
鍵が無くても読めました。署名は改ざんを見破るためのもので、中身を隠すものではありません。 中に個人情報や秘密を入れてはいけません。
一方、中身の role を書き換えると、検証で JWT::VerificationError になりました。期限(exp)を過ぎたものは JWT::ExpiredSignature です。改ざんと期限切れは、正しく検証すれば弾けます。
後から困ること
- JWT を長い期間(たとえば30日)有効にする。 漏れたとき、退会させたいとき、期限が来るまで止められません。止めるために「無効にしたトークンの一覧」をサーバーに持つと、結局サーバーに状態を持つことになります
- トークンに権限を書く。 管理者から外しても、手元のトークンには「管理者」と書いてあります。期限が来るまで、古い権限のまま動きます
- ログアウトを「ブラウザの Cookie を消すだけ」にする。 盗まれた写しは、まだ生きています
最初に決める3つのこと
- 有効期限: 使うためのトークンは短く(数分〜1時間程度)、長く使いたいなら、作り直すための別のトークンを持たせる
- 失効の単位: 1つの端末だけ/その人の全部の端末/全員、のどれを止められる必要があるか
- ログアウトの意味: その端末だけか、全部の端末か
naminori の例
- AIアプリとの接続(第5回)に渡すトークンは、中身を持たないランダムな文字列です。サーバーにはトークンそのものではなく照合用の値(ダイジェスト)だけを保存し、一覧から1件ずつ失効できます。使うためのトークンは短い期限で、作り直すためのトークンは使うたびに入れ替わり、古いものは使えなくなります
- 会員がログアウトすると、「ブラウザを閉じてもログインしたままにする」ための印を、他の端末の分も含めて無効にします
このレクチャーで学ぶこと
- ログインの状態をサーバーに持つか、トークンに持つか
- JWT の中身は誰でも読める(手元で確認)
- 長い期限・権限入りのトークンで後から困ること
- 有効期限・失効の単位・ログアウトの意味を決める
質問
まだ質問は投稿されていません。
質問投稿
ログイン後に質問の投稿ができます。
#1
未完了
認証と認可を分けて設計する ― 「誰か」と「何をしてよいか」は別の問い
#2
未完了
セッションとトークン ― 有効期限と「止め方」を最初に決める
#3
未完了
パスワードとログイン試行 ― 後から強くでき、本人を締め出さず、登録の有無を漏らさない
#4
未完了
多要素認証と復旧 ― 「スマホを失くした日」を先に設計する
#5
未完了
OAuth 2.0 と OpenID Connect ― パスワードを渡さずに「代わりに」入らせる
#6
未完了
認可モデル ― 所有者・ロール・権限を、1か所で判定する
#7
未完了
特権の扱い ― 管理者と代理ログインを「普通の権限」と分ける
#8
未完了