「あなたの家の鍵、配達中にすり替えられたら?」OAuth 2.0とPKCEで守るログインの裏側
こんにちは!セキュリティの世界へようこそ。
日々、技術の進化に追いつくのは大変ですよね。今日は、Webアプリ開発の現場で避けては通れない「OAuth 2.0」と、そのセキュリティを劇的に高める「PKCE(ピーシーケーイー)」という技術について、泥棒に例えてお話しします。
「認証」は、いわばあなたの家の玄関の鍵です。でも、もしその鍵を渡すプロセス自体が狙われていたら?そんな恐ろしいシナリオを一緒に見ていきましょう。
—
1. 認可コード横取り攻撃:鍵を配送する郵便屋さんが悪人だったら?
OAuth 2.0の仕組みを想像してみてください。ユーザーが「Googleアカウントでログイン」ボタンを押すと、Googleが「認可コード」という一時的な鍵を発行します。このコードをあなたのアプリが受け取り、「本人確認完了!どうぞ!」と中に入るのが一般的な流れです。
しかし、この「認可コード」がアプリに届くまでの道中、悪意ある第三者が待ち構えていたらどうでしょう?
- 攻撃の流れ:
1. 攻撃者は、あなたのアプリのふりをしてユーザーを罠にかけます。
2. ユーザーが認可コードを受け取った瞬間、攻撃者がそのコードを横取り(インターセプト)します。
3. 攻撃者はそのコードを使って、ユーザーになりすましてあなたのアプリにログインしてしまいます。
まるで、「鍵を宅配便で送っている最中に、偽の配達員が抜き取って本物の家に入ってしまう」ようなものです。これでは、どんなに頑丈な鍵を持っていても意味がありませんよね。
—
2. PKCEの登場:鍵に「特殊な仕掛け」を施そう
この「横取り」を防ぐために生まれたのが、PKCE(Proof Key for Code Exchange)です。読み方は「ピーシーケーイー」。ちょっと難しそうですが、仕組みはシンプルです。
先ほどの「鍵の配送」に、「合言葉」を追加するイメージです。
1. 準備段階: あなたのアプリは、ログインを開始する前に「秘密の合言葉(Code Verifier)」を作り、それをぐちゃぐちゃに変換したもの(Code Challenge)を先にサーバーへ送っておきます。
2. 鍵の受け取り: 認可コードが届きます。
3. 照合: アプリは認可コードと一緒に、隠しておいた「秘密の合言葉」をサーバーに送ります。
4. 判定: サーバーは「さっき預かった合言葉の変換元と、今届いた合言葉が一致するな。じゃあ横取りしたやつじゃないね!」と判断します。
攻撃者は、最初の「準備段階」を見ていないので、正しい合言葉を知ることができません。これで、コードを盗まれてもログインは成立しなくなります!
—
3. 実装のポイント:PKCEを組み込む
では、実際にどう実装するか、流れをコードのイメージで見ていきましょう。
手順1: 合言葉の生成(クライアント側)
まずは、ランダムな文字列(Code Verifier)を作り、それをSHA-256でハッシュ化して変換したものを用意します。
// 秘密の合言葉(ランダムな文字列)
const codeVerifier = generateRandomString(64);
// それを変換したもの(Code Challenge)
const codeChallenge = base64UrlEncode(sha256(codeVerifier));
手順2: 認可リクエスト(サーバーへ送る)
認可画面に飛ばす際に、code_challengeを忘れずに付与します。
GET /authorize?
response_type=code
&client_id=YOUR_CLIENT_ID
&redirect_uri=YOUR_CALLBACK_URL
&code_challenge=変換した合言葉
&code_challenge_method=S256 // SHA-256を使うよと宣言
手順3: トークン取得(答え合わせ)
認可コードを受け取ったら、元のcode_verifierを添えてトークンを要求します。ここでサーバーが照合を行い、正しければログイン成功です!
—
4. なぜ「PKCE」が必須なのか?
昔は「サーバーサイドで動くアプリなら、秘密鍵を隠せるから大丈夫」とされていました。しかし、今のWeb開発では、ブラウザ上で動くJavaScript(SPA)やスマホアプリが主流です。これらは「秘密鍵」を隠し持っておくことができません。
「誰でもソースコードが見れる環境では、鍵を隠し持てない。だからこそ、その都度『合言葉』を発行して安全を担保する」という考え方がPKCEです。
一歩ずつ対策を学ぶために
- 「とりあえずPKCEを使う」: 今のOAuth 2.0実装では、PKCEは「推奨」ではなく「必須」です。ライブラリを使う際も、
usePkce: trueといった設定が必ずあるはずです。 - ログをチェック: 認証のリクエストに
code_challengeが含まれているか、ブラウザのデベロッパーツールで確認する癖をつけましょう。
—
最後に:セキュリティは「疑うこと」から始まる
セキュリティエンジニアとして一番伝えたいのは、「自分のシステムは常に狙われている」と仮定して設計することの重要性です。
「便利だから」「みんなこうしているから」で済ませるのではなく、「もし郵便屋さんが悪人だったら?」「もし鍵が盗まれたら?」と一歩立ち止まって考える。その視点こそが、あなたを一流のエンジニアにする第一歩です。
PKCEの実装は、最初は少しややこしく感じるかもしれませんが、一度理解してしまえば、あなたのアプリの信頼性を大きく高める強力な武器になります。ぜひ、今日から自分のコードを見直してみてくださいね。応援しています!
コメント