「鍵」を渡す怖さを知っていますか?——アクセストークンとリフレッシュトークンで守るWeb APIの安全
こんにちは。ネットワークの深淵を愛するエンジニアの皆さん、今日も元気にパケットを追いかけていますか?
Web APIを作っていると、必ずぶつかる壁があります。それは「どうやってユーザーの本人確認をし続けるか」という問題です。一度ログインしたら、ページを移動するたびにパスワードを打たせたくはありませんよね。そこで登場するのが「トークン」という名の「通行手形」です。
今回は、この通行手形を安全に扱うためのベストプラクティス、「アクセストークン」と「リフレッシュトークン」の使い分けについて、現実世界の例を交えて紐解いていきましょう。
—
「一生使える通行手形」が一番危ない理由
まず、想像してみてください。あなたが高級ホテルのオーナーだとします。お客様に「部屋に入るための鍵」を渡す際、もしその鍵が「一度渡したら、お客様がチェックアウトするまで永久に使えるマスターキー」だったらどうでしょう?
もし、その鍵を廊下で落としてしまったら……。誰かがその鍵を拾えば、滞在中ずっと好き勝手に部屋へ出入りできてしまいますよね。これこそが、Web APIにおいて「有効期限のないトークン」を使ってはいけない理由です。
そこで、私たちは「短命な鍵」と「予備の鍵」を組み合わせて使うことにしました。
—
2つの鍵:アクセストークンとリフレッシュトークン
Web APIの世界では、以下の2種類の鍵(トークン)を使い分けるのが鉄則です。
1. アクセストークン(短命な鍵)
- 役割: APIにリクエストを送る際の「通行手形」。
- 寿命: 数分〜1時間程度と極めて短い。
- たとえ: 「今日の日付が入った1日限りの入館証」。
2. リフレッシュトークン(長命な鍵)
- 役割: アクセストークンが切れたときに、新しいアクセストークンを再発行するための「引換券」。
- 寿命: 数日〜数週間と比較的長い。
- たとえ: 「本人確認書類を提示して、新しい入館証をもらうための引換券」。
なぜこの組み合わせが最強なのか?
アクセストークンの寿命を短くしておけば、万が一誰かに盗まれても、すぐに無効化されます。盗んだ犯人は「あれ、さっきまで使えたのに!」と数十分で締め出されるわけです。一方で、リフレッシュトークンは厳重に保管しておけば、ユーザーは毎回ログインし直す手間から解放されます。
—
実装のイメージ:Python(Flask)でのトークン発行フロー
実際にコードで見てみると、イメージが湧きやすいはずです。あくまで概念的なコードですが、やり取りの流れを見てみましょう。
# ユーザーがログインした時に発行するイメージ
def login(username, password):
if authenticate(username, password):
# 短命なアクセストークン(例: 15分で期限切れ)
access_token = generate_token(user_id, expires_in=900)
# 長命なリフレッシュトークン(例: 7日間有効)
refresh_token = generate_token(user_id, expires_in=604800)
# クライアントへ返す(リフレッシュトークンはHttpOnlyクッキーに入れるのが安全!)
return {
"access_token": access_token,
"refresh_token": refresh_token
}
ここで重要なのが、「リフレッシュトークンは、JavaScriptから直接触れない(HttpOnly属性を付けた)クッキーに入れる」という点です。こうすることで、万が一ブラウザに悪意のあるスクリプト(XSS攻撃など)が仕込まれても、犯人がリフレッシュトークンを盗み出すハードルが格段に上がります。
—
運用時のチェックポイント:もしも盗まれたら?
ネットワークの現場では、「想定外の事態」が必ず起きます。もしリフレッシュトークンさえも盗まれてしまったらどうするか。
ここで有効なのが「リフレッシュトークン・ローテーション」という手法です。
1. 新しいアクセストークンを発行するとき、「あわせて新しいリフレッシュトークンも一緒に発行する」。
2. 古いリフレッシュトークンは、使った瞬間に「無効」にする。
もし犯人が古いリフレッシュトークンを使い、同時に正当なユーザーが新しいリフレッシュトークンを使ってしまったら?システム側は「おや、同じ鍵が二箇所で使われているぞ。これは不正アクセスの予兆だ!」と検知し、そのユーザーの全セッションを強制終了させることができるのです。
—
まとめ:安全は「手間」と「制約」から生まれる
APIの設計において、「便利さ」を追求しすぎると、セキュリティという大切な土台が揺らぎます。
- アクセストークンは短く。
- リフレッシュトークンは厳重に管理。
- ローテーションで不正の芽を摘む。
最初は少し面倒に感じるかもしれませんが、これこそがユーザーの信頼を守るための「ネットワークエンジニアの作法」です。
皆さんの作るAPIが、今日も安全に、軽快にパケットを届けてくれることを願っています。もしトラブルが起きたら、パケットを眺めて「このトークンは今、どの期限の中にいるんだ?」と冷静に分析してみてください。きっと答えは見つかるはずです。
それでは、また次回の深淵でお会いしましょう!
コメント