「認可コードが盗まれる!?」OAuth 2.0の落とし穴と、PKCEで鉄壁のガードを固める方法
こんにちは!セキュリティの世界へようこそ。
日々開発や運用に励んでいると、「OAuth 2.0」という言葉を耳にする機会は多いですよね。GoogleやLINEでログインする、あの仕組みのことです。
「便利だし、ライブラリを使えば安全でしょ?」と思っていませんか?実は、認可コード(Authorization Code)という「チケット」を横取りされる攻撃が、今もなお開発者の頭を悩ませています。
今日は、専門用語を一切使わず、私たちの身近な「家の鍵」を例にして、なぜ攻撃が起きるのか、そしてそれを防ぐ「PKCE(ピクシー)」という魔法の仕組みについて、一緒に紐解いていきましょう。
—
1. 認可コード横取り攻撃:泥棒はどこからやってくる?
想像してみてください。あなたは今、豪華なホテルのフロント(認可サーバー)で、部屋に入るための「電子カードキー(認可コード)」を受け取ろうとしています。
本来のフローはこうです。
1. あなたが「部屋に入りたい!」と言う。
2. フロントが本人確認をして、あなたに「カードキー」を渡す。
3. あなたはそれを使って部屋に入る。
しかし、攻撃者はここで悪さをします。フロントからあなたにカードキーが手渡されるまでの「一瞬の隙」を狙って、横からサッとカードキーを盗み取るのです。これが「認可コード横取り攻撃」です。
特に、スマホアプリなどでこの隙が生まれやすい理由は、アプリ間の連携(カスタムURLスキーム)が悪用され、攻撃者のアプリが「私にカードキーを渡して!」と横取りしてしまうからなんです。
—
2. PKCE:泥棒が鍵を拾っても「使えない」仕組み
この問題を解決するのが「PKCE(Proof Key for Code Exchange)」です。読み方は「ピクシー」。名前は可愛いですが、セキュリティの実力は折り紙付きです。
PKCEの考え方はとてもシンプル。「カードキー」を渡す前に、あなただけが知っている「秘密の合言葉」をあらかじめ登録しておくのです。
PKCEの3ステップ
1. 秘密の合言葉(Code Verifier)を作る: あなたは適当な長い文字列を自分で決めます。
2. 合言葉のヒント(Code Challenge)を送る: その合言葉を暗号化して、フロント(認可サーバー)に先に預けておきます。
3. 答え合わせ: 認可コードと引き換えに、本物の「合言葉」をフロントに提示します。
もし、攻撃者が途中で認可コードを盗んだとしても、彼は「合言葉」を知りません。鍵を拾っても、フロントで「合言葉が違います」と突き返されるだけ。これなら安心ですよね!
—
3. 実装してみよう:PKCEの書き方
では、実際にコードを書く際のイメージを見てみましょう。ここでは疑似コードで解説します。
// 1. ランダムな合言葉(Code Verifier)を生成
const codeVerifier = generateRandomString(64);
// 2. 合言葉をSHA-256でハッシュ化してヒント(Challenge)を作る
const codeChallenge = sha256(codeVerifier);
// 3. ログイン画面に飛ばす時、ヒントを一緒に送る
const authUrl = `https://auth.example.com/authorize?` +
`response_type=code&` +
`code_challenge=${codeChallenge}&` +
`code_challenge_method=S256`; // 「S256」を使うのが現代のルールです!
// — この後、認可コードが手に入ったら —
// 4. トークンをもらう時に、オリジナルの合言葉を見せる
fetch(‘https://auth.example.com/token’, {
method: ‘POST’,
body: {
code: receivedCode, // 盗まれるかもしれない認可コード
code_verifier: codeVerifier // 本人しか知らない合言葉!
}
});
このように、「事前にヒントを送り、最後に答え合わせをする」というプロセスを加えるだけで、認可コードは単なる「ただの紙切れ」になり、悪用できなくなります。
—
まとめ:セキュリティは「疑う」ことから始まる
今日覚えていただきたいのは、たった一つ。「認可コードは途中で盗まれる可能性がある」という前提で設計することです。
- PKCEは必須: 今やモバイルアプリだけでなく、WebアプリでもPKCEを使うのが「当たり前」のセキュリティ標準になっています。
- ライブラリを信頼しすぎない: 便利なライブラリでも、PKCEの設定がオフになっていないか、必ず確認しましょう。
セキュリティ対策は、完璧な壁を作ることではなく、「泥棒が侵入しても、何も盗めない仕組み」を作ることです。一歩ずつ、こうした仕組みを理解して実装していくことで、あなたのアプリはより強固なものになります。
「これってどう実装するのが最適解?」と迷ったら、いつでもまた聞きに来てくださいね。一緒に安全なコードを書いていきましょう!

コメント