OAuth 2.0の「認可コード横取り」をPKCEで防ぐ!泥棒から家の鍵を守るための基本ガイド
こんにちは。現場で泥臭いインシデント対応を繰り返していると、「完璧なセキュリティなんてない」という現実に直面しますが、それでも「防げる攻撃を確実に防ぐ」ことの重要性は痛感します。
今日は、ウェブ開発の現場で避けては通れない「OAuth 2.0」のセキュリティについてお話しします。特に新人のエンジニアさんがつまづきやすい「認可コード横取り攻撃」と、それを防ぐ最強の盾「PKCE(ピクシー)」について、難しい専門用語をなるべく使わずに紐解いていきましょう。
—
1. そもそも「認可コード」って何?
想像してみてください。あなたは今、とある会員制の高級クラブ(ウェブサービス)に入ろうとしています。
1. あなたは受付(認可サーバー)で身分証を見せます。
2. 受付は「わかった、君は本人だね」と、「一時的な通行証(認可コード)」をあなたに手渡します。
3. あなたは、その通行証をクラブの入り口(アプリサーバー)に持っていきます。
4. 入り口は通行証を受け取り、「よし、本物だ」と確認して、ようやく中(サービス)に入れてくれます。
この「通行証(認可コード)」を、アプリサーバーまで安全に届けるのがOAuthの基本的な流れです。
2. なぜ「横取り」されるの?(泥棒のメカニズム)
ところが、この「通行証」の受け渡しには大きな落とし穴があります。
通行証は、あなたのブラウザを経由してアプリに送られます。もし、あなたのPCやスマホに悪意のあるアプリ(泥棒)が潜んでいたらどうなるでしょう?
- 泥棒の行動: ブラウザの通信をこっそり覗き見して、あなたが受け取ったばかりの「通行証」を横からパッと奪い取ります。
- 結果: 泥棒は奪った通行証を使って、あなたの代わりにクラブ(サービス)に入り込んでしまいます。これが「認可コード横取り攻撃」です。
昔は、この対策が少し甘かったのですが、今は「PKCE」という仕組みを使うことで、泥棒が通行証を盗んでも「使えない」ようにガードできるようになりました。
—
3. PKCE(ピクシー)でどうやってガードするの?
PKCE(Proof Key for Code Exchange)を一言で言うと、「通行証に秘密の合言葉を紐付ける」仕組みです。
家を例にすると、こんな感じです。
1. 出発前: あなたは「自分だけの秘密の合言葉(Code Verifier)」を作り、それを少し加工して「合言葉のヒント(Code Challenge)」を受付に伝えておきます。
2. 通行証の受け取り: 受付は「通行証」と一緒に、あなたが預けた「ヒント」を記録しておきます。
3. 突入時: あなたがクラブの入り口に通行証を見せるとき、一緒に「本物の合言葉」を突き出します。
4. 確認: 入り口は、受け取った「合言葉」を加工して、受付が持っている「ヒント」と一致するか確かめます。
もし泥棒が通行証を盗んでも、「合言葉」を知らないので、入り口で追い返されてしまうのです! これがPKCEの魔法です。
—
4. 実装のステップ:難しく考えないで!
開発でやるべきことは、たったの3ステップです。
ステップ1:合言葉を生成する
フロントエンド(JavaScriptなど)で、ランダムな文字列(Code Verifier)を作成します。
// ランダムな文字列を生成する関数(例)
function generateCodeVerifier() {
const array = new Uint8Array(32);
window.crypto.getRandomValues(array);
return btoa(String.fromCharCode.apply(null, array))
.replace(/\+/g, ‘-‘).replace(/\//g, ‘_’).replace(/=/g, ”);
}
ステップ2:ヒントを作って送信する
生成した文字列をSHA-256でハッシュ化して、「ヒント」として認可サーバーへ送ります。
// 認可リクエストを送る際のパラメーター例
const params = {
response_type: ‘code’,
client_id: ‘YOUR_CLIENT_ID’,
code_challenge: ‘生成したヒントをBase64URLエンコードしたもの’, // これがPKCEの鍵!
code_challenge_method: ‘S256’ // 「SHA-256を使っているよ」と宣言
};
ステップ3:トークン交換時に合言葉を添える
認可コードが返ってきたら、最初に作った「秘密の合言葉」を添えてサーバーに送ります。
// トークン取得リクエストのパラメーター例
const tokenParams = {
code: ‘受け取った認可コード’,
code_verifier: ‘最初に生成した秘密の合言葉(そのままの文字列)’ // サーバーがこれとヒントを照合する
};
—
最後に:一歩ずつ積み上げよう
セキュリティ対策は、最初から完璧を目指すと息切れしてしまいます。ですが、OAuthを使っているなら、PKCEは「標準装備」にするのが今の常識です。
「難しそうだな」と思ったら、まずは「通行証だけでなく、秘密の合言葉も一緒に渡す必要がある」というイメージだけ持ち帰ってください。それだけで、あなたの書くコードはグッと堅牢になります。
何か分からないことがあれば、いつでもまた聞きに来てくださいね。一緒に安全な開発ライフを築いていきましょう!
コメント