一覧へ

OAuth 2.0 — サードパーティ認証の仕組み

OAuth 2.0とは何か、なぜパスワードを直接受け取らないのか、認可コードフローがどのように機能するかを学びます。

中級
|
14
|
検証済み (2026-07)
OAuthソーシャルログイン認証フロー認可コードアクセストークン
進捗0/55 (0%)

OAuth 2.0 — 第三者認証の原理

このトピックを終えると

OAuth 2.0が解決する問題、Authorization Code Flow の全体の流れ、そして Access Token と Refresh Token の役割を理解できるようになります。


なぜパスワードを受け取らないのか

「Google でログイン」、または「Kakao でログイン」ボタンをクリックすると、ユーザーは自分のサービスにパスワードを入力しません。Google の画面に移動して Google にログインし、その後、元の画面に戻ってきます。

なぜこのような複雑な仕組みになっているのでしょうか?それは簡単です — パスワードを他人のサーバーに渡すべきではないからです

もしあるサービスが「Google アカウントのメールアドレスとパスワードを入力してください」と言う場合、そのサービスは自分のパスワードを保存できることになります。もしそれが漏洩した場合、Google アカウント全体が危険にさらされる可能性があります。OAuth はこの問題を解決します — パスワードの代わりに「許可証」を与えるのです


4 人の登場人物

OAuth には 4 つの役割があります。

役割意味
Resource Ownerユーザー(データの所有者)あなた
Client私たちが作成したサービス私たちのウェブアプリ
Authorization Server認証を担当するサーバーGoogle 認証サーバー
Resource ServerユーザーデータがあるサーバーGoogle プロファイル API

名前が直感的ではありません。「Client」はユーザーではなく、私たちのサーバーであるという点に注意してください。OAuth の観点から見ると、私たちのサービスは Google に「データをお願いします」とリクエストする立場なので、Client となります。


Authorization Code Flow

最も一般的に使用されるフローです。ステップごとに見ていきましょう。

text
1. ユーザーが「Google でログイン」をクリック
2. 私たちのサーバーが Google 認証サーバーにリダイレクト
   → URL に client_id、redirect_uri、scope を含める
3. ユーザーが Google でログインし、「このアプリに許可」をクリック
4. Google が redirect_uri に「認可コード (code)」を送信
5. 私たちのサーバーが認可コードと client_secret を使用して Google にリクエスト
6. Google が Access Token を発行
7. 私たちのサーバーが Access Token を使用してユーザー情報をリクエスト

重要なのは、2 回交換するということです。まず、認可コード(使い捨て)を受け取り、それを使って実際のトークンを受け取ります。なぜ一度にトークンを発行しないのでしょうか?

4 段階で認可コードは URL パラメーターで送信されます。URL はブラウザの履歴に残し、ログにも記録されます。もしここにトークンが含まれていると、誰かがそれを見ることができます。認可コードは使い捨てであり、短時間で期限切れになるため、漏洩しても被害が限定されます。

5 段階で実際のトークン交換は、サーバー間の通信(バックチャネル)で行われます。client_secret が含まれており、これは決してブラウザに公開されることはありません。


Access Token と Refresh Token

javascript
// Google が応答するトークンの構造(例)
{
  "access_token": "ya29.a0AfH6SM...",
  "expires_in": 3600,          // 1 時間
  "refresh_token": "1//0eXyz...",
  "token_type": "Bearer",
  "scope": "email profile"
}
トークン寿命用途
Access Token短い(通常 1 時間)API 呼び出しに使用
Refresh Token長い(数週間〜数ヶ月)Access Token の再発行に使用

Access Token が期限切れになると、Refresh Token を使用して新しい Access Token を取得します。毎回ユーザーに「再度ログインしてください」と言う必要はありません。

なぜ Access Token を長くしないのでしょうか?トークンが漏洩した場合の被害期間を最小限に抑えるためです。1 時間のトークンが漏洩した場合、1 時間だけ危険ですが、1 年のトークンが漏洩した場合、1 年間危険です。


scope — 権限の範囲

text
https://accounts.google.com/o/oauth2/v2/auth?
  client_id=OUR_CLIENT_ID&
  redirect_uri=http://localhost:3000/callback&
  scope=email+profile&
  response_type=code

scope は、どこまでアクセスできるかを定義するものです。email profile の場合、メールアドレスとプロフィール写真だけを取得でき、Google ドライブのファイルは参照できません。

ユーザーが「このアプリに許可」をクリックしたときに表示される画面に「このアプリはあなたのメールアドレスにアクセスします」と表示されるのが scope です。

最小権限の原則 — 必要なものだけをリクエストしてください。「すべての権限」をリクエストすると、ユーザーは警戒して拒否する可能性があります。


私たちのサービスで実装する場合

実際の実装で知っておくべきこと:

  1. プロバイダー登録: Google/Kakao の開発者コンソールでアプリを登録し、client_idclient_secret を取得します。
  2. redirect_uri の設定: 認可コードを受け取るコールバック URL を登録します。登録されていない URL にはリダイレクトされません。
  3. 状態値 (state) の検証: CSRF 対策用のランダムな文字列をリクエストに含め、コールバックで一致するかどうかを確認します。
javascript
// Express でのコールバック処理(概念)
app.get('/callback', async (req, res) => {
  const { code, state } = req.query;

  // 1. state 検証(CSRF 対策)
  if (state !== req.session.oauthState) {
    return res.status(403).send('Invalid state');
  }

  // 2. 認可コードでトークン交換(サーバー → Google、バックチャネル)
  const tokenRes = await fetch('https://oauth2.googleapis.com/token', {
    method: 'POST',
    body: new URLSearchParams({
      code,
      client_id: CLIENT_ID,
      client_secret: CLIENT_SECRET,
      redirect_uri: REDIRECT_URI,
      grant_type: 'authorization_code',
    }),
  });

  const { access_token } = await tokenRes.json();

  // 3. Access Token でユーザー情報をリクエスト
  const userRes = await fetch(
    'https://www.googleapis.com/oauth2/v2/userinfo',
    { headers: { Authorization: `Bearer ${access_token}` } }
  );
  const user = await userRes.json();

  // 4. セッションにユーザーを保存
  req.session.user = user;
  res.redirect('/');
});

核心

OAuth 2.0 は、パスワードの代わりにトークンを使用して権限を委任するプロトコルです。 Authorization Code Flow は、認可コード(使い捨て)→ Access Token(短期)→ API 呼び出しの 2 段階の交換です。 Access Token は短く、Refresh Token で更新 — 漏洩時の被害を最小限に抑える設計です。

→ 次のトピックで、Passport.js + Google OAuth を実際に実装します。

💬 質問・コメント

0件のコメント

ログインせずに投稿できます。ゲスト投稿は投稿者自身で編集・削除できません。

0/2000

読み込み中...