LOCKED
ブログ一覧に戻る
SSO・IDaaSLOCKED MSO

OpenID Connect完全実装ガイド【OAuth 2.0との違いを徹底解説】

多くの企業が OAuth 2.0 と OpenID Connect(OIDC)を混同しています。OAuth 2.0 は認可を、OpenID Connect は認証を行うプロトコルですが、実装時にはその違いを明確に理解することが重要です。本記事では、OIDC と OAuth 2.0 の根本的な違い、Authorization Code Flow の実装フロー、IDトークン・アクセストークンの役割、OIDC を支える技術仕様、SAML 認証との対比を含むセキュアな実装パターンを詳細に解説します。

OAuth 2.0 と OpenID Connect:本質的な違い

OAuth 2.0:認可を行うプロトコル

OAuth 2.0 は、ユーザーがアプリケーションに対して、自分のリソースへのアクセス権を委譲するプロトコルです。

具体例:

  • Spotify アプリが Facebook のあなたの友達情報にアクセスする権限をもらう
  • Slack が Google Drive のドキュメント一覧を読み取る権限をもらう

OAuth 2.0 の本質:

ユーザー → アプリケーション:「Google の友達リストにアクセスしてもいい?」
    ↓
ユーザー → Google:「アプリに許可を与える」(同意画面)
    ↓
Google → アプリケーション:「アクセストークン」を発行
    ↓
アプリケーション → Google:「アクセストークン」を使用して友達リストを取得

重要なポイント:

  • OAuth 2.0 はユーザーの**認証(Who you are)**を行わない
  • リソースサーバーへのアクセス権(スコープ)を管理するだけ -「このユーザーは誰か」という情報は含まれていない

実装では、アクセストークンが発行されても、それがどのユーザーのものか、アプリケーションからは直接わかりません。

OpenID Connect:認証を行うプロトコル

OpenID Connect(OIDC)は OAuth 2.0 の上に構築された認証レイヤーです。OIDC は、ユーザーが「誰であるか」を確認する情報を提供します。

具体例:

  • Slack にサインアップするとき、Google アカウントでログインする
  • Notion で Microsoft 365 アカウントを使用してログインする

OIDC の本質:

ユーザー → アプリケーション:「Google でログインしたい」
    ↓
ユーザー → Google:「ログイン認証」(パスワード・MFA)
    ↓
Google → アプリケーション:「IDトークン」+「アクセストークン」を発行
    ↓
アプリケーション → Google:「IDトークン」を検証し、ユーザー情報を確認

OIDC が OAuth 2.0 に追加するもの:

  1. IDトークン(JWT形式)

    • ユーザーの身元情報(ユーザーID、メールアドレス、表示名など)を含む
    • デジタル署名されており、改ざん検知が可能
  2. UserInfo エンドポイント

    • アクセストークンを使用して、ユーザーの詳細情報を取得
  3. 認証フロー標準化

    • Authorization Code Flow、Implicit Flow、Hybrid Flow など複数の認証フローを定義
RFPテンプレート(無料)

IDaaS導入RFPテンプレート

IDaaS導入の社内稟議に使えるRFPテンプレート。SSO、MFA、プロビジョニングなどの要件を網羅したフォーマットです。

無料でダウンロード

Authorization Code Flow:最も安全なフロー

OIDC/OAuth 2.0 で最も一般的で安全な実装パターンは Authorization Code Flow です。

フロー図:7ステップの認証プロセス

┌─────────────────┐                    ┌──────────────────┐
│                 │                    │                  │
│   ユーザー      │                    │  ブラウザ        │
│  (リソース      │                    │  (User Agent)    │
│   オーナー)    │                    │                  │
└────────┬────────┘                    └────────┬─────────┘
         │                                      │
         │   1. ログインクリック                 │
         │───────────────────────────────────────→
         │                                      │
         │                                  ┌──────────────────┐
         │                                  │  アプリケーション │
         │                                  │   (Client)       │
         │                                  │                  │
         │                                  │  2. Authorization
         │                                  │     リクエスト
         │   3. Google/Microsoft           │     を構成       │
         │      ログイン画面表示             │                  │
         │←─────────────────────────────────│
         │                                  │
         │   4. ユーザー認証                 │
         │      (ID + パスワード)            │
         │───────────────────────────────────→
         │                                  │
         │   5. 同意画面表示                 │
         │←─────────────────────────────────│
         │                                  │
         │   6. 「同意する」クリック         │
         │───────────────────────────────────→
         │                                  │
         │                                 ┌──────────────────┐
         │                                 │ IdP              │
         │                                 │ (Google/         │
         │                                 │  Microsoft)      │
         │                                 │                  │
         │   7. Authorization Code         │                  │
         │      リダイレクト                 │                  │
         │←─────────────────────────────────│
         │                                  │
         │       ↓↓↓  バックチャネル通信  ↓↓↓
         │
         │                            ┌──────────────────┐
         │                            │ アプリケーション  │
         │ 8. IDトークン              │ バックエンド      │
         │    + アクセストークン       │ サーバー          │
         │←──────────────────────────│                  │
         │                            │ Authorization    │
         │                            │ Code を使って    │
         │                            │ トークン要求      │
         │                            │─────────────→   │
         │                            │                  │
         │                            └──────────────────┘
         │
    ログイン完了

実装の具体的なステップ

ステップ 1-2:ユーザーがログインをリクエスト

// ブラウザ側の処理
const authorizationUrl = new URL(
  'https://accounts.google.com/o/oauth2/v2/auth'
);
authorizationUrl.searchParams.append('client_id', 'xxxxx.apps.googleusercontent.com');
authorizationUrl.searchParams.append('response_type', 'code');
authorizationUrl.searchParams.append('scope', 'openid email profile');
authorizationUrl.searchParams.append('redirect_uri', 'https://myapp.com/callback');
authorizationUrl.searchParams.append('state', generateRandomState());  // CSRF 対策

window.location.href = authorizationUrl.toString();

ステップ 3-6:Identity Provider(IdP)でユーザー認証

IdP(Google、Microsoft など)がユーザーの身元を確認します。

  • 認証: パスワード、MFA(SMS/TOTP/セキュリティキー)
  • 同意: ユーザーがアプリケーションへの情報提供に同意

ステップ 7:Authorization Code をブラウザにリターン

ブラウザが以下の URL にリダイレクト:
https://myapp.com/callback?code=4/0AX4...(長いコード)&state=random123

ステップ 8:バックエンド サーバーが Authorization Code をトークンと交換

このステップはバックチャネル通信(ブラウザを経由しない直接通信)で実行されます。

# バックエンド サーバーから Google へ直接 POST リクエスト
curl -X POST https://oauth2.googleapis.com/token \
  -d "client_id=xxxxx.apps.googleusercontent.com" \
  -d "client_secret=yyyyy" \
  -d "code=4/0AX4..." \
  -d "redirect_uri=https://myapp.com/callback" \
  -d "grant_type=authorization_code"

# レスポンス:
{
  "access_token": "ya29.xxx",
  "expires_in": 3599,
  "refresh_token": "1//xxx",
  "scope": "openid email profile",
  "token_type": "Bearer",
  "id_token": "eyJhbGci..."  ← これが OIDC のキー
}

IDトークン と アクセストークン:役割の違い

OIDC/OAuth 2.0 では、2 種類のトークンが発行されます。その役割は全く異なります。

IDトークン(ID Token):ユーザー身元を証明

形式: JWT(JSON Web Token)

IDトークンのペイロード例:

{
  "iss": "https://accounts.google.com",
  "azp": "xxxxx.apps.googleusercontent.com",
  "aud": "xxxxx.apps.googleusercontent.com",
  "sub": "110169547860073334883",  ← ユーザーの一意 ID
  "email": "user@example.com",
  "email_verified": true,
  "at_hash": "HK3E...",
  "iat": 1312883113,
  "exp": 1312886713,
  "name": "山田太郎",
  "picture": "https://lh3.googleusercontent.com/...",
  "locale": "ja"
}

IDトークンの特徴:

  • JWT 形式で、署名によって改ざん検知が可能
  • ユーザーの身元情報(name、email、picture など)を含む
  • ブラウザでも検証可能(署名鍵は IdP が公開)
  • 通常は短命(1 時間程度)

IDトークンの検証ロジック(重要):

# バックエンド サーバーでの検証
import jwt

def verify_id_token(id_token, client_id):
    try:
        # 公開鍵を取得(IdP から)
        public_keys = get_public_keys_from_idp()

        # JWT を検証
        decoded = jwt.decode(
            id_token,
            public_keys,
            algorithms=['RS256'],
            audience=client_id,
            issuer='https://accounts.google.com'
        )

        # iss, aud, exp などを検証
        assert decoded['iss'] == 'https://accounts.google.com'
        assert decoded['aud'] == client_id
        assert decoded['exp'] > time.time()

        return decoded  # ユーザー情報

    except jwt.InvalidSignatureError:
        raise Exception("署名が無効です(改ざんの可能性)")
    except jwt.ExpiredSignatureError:
        raise Exception("トークンが期限切れです")

アクセストークン(Access Token):リソースアクセス権を許可

形式: Bearer token(不透明な文字列、通常は JWT)

アクセストークンの役割:

  • リソースサーバーへのアクセス権を表現
  • UserInfo エンドポイントへのアクセスに使用
  • 他の API(Google Drive API など)へのアクセスに使用

アクセストークンの使用例:

# Google UserInfo エンドポイントにアクセス
curl -H "Authorization: Bearer ya29.xxx" \
  https://www.googleapis.com/oauth2/v2/userinfo

# レスポンス(IDトークンとは異なるデータ取得可能性):
{
  "id": "110169547860073334883",
  "email": "user@example.com",
  "verified_email": true,
  "name": "山田太郎",
  "picture": "https://lh3.googleusercontent.com/...",
  "locale": "ja"
}

重要な違いまとめ

項目IDトークンアクセストークン
目的ユーザー認証リソースアクセス権
形式JWTBearer token
内容ユーザー身元情報アクセス権限
有効期限短い(1時間程度)中程度(1日~数週間)
署名検証必須不要(IdP が信頼)
漏洩時の影響ユーザーになりすまし可能リソースアクセスのみ可能
送信方法ブラウザ・API 両方API のみ

セキュアな実装パターン

パターン 1:SPA(Single Page Application)+ バックエンド

最も推奨される実装パターンです。

アーキテクチャ:

ブラウザ (SPA) ← Auth Cookie
    ↓
バックエンド サーバー ← Secure HttpOnly Cookie (IDトークン)
    ↓
Google / Microsoft / LOCKED MSO

実装の流れ:

// フロントエンド(SPA)
const response = await fetch('https://myapp.com/api/auth/login', {
  method: 'POST',
  credentials: 'include',  // クッキーを自動送信
  body: JSON.stringify({ provider: 'google' })
});

// バックエンドが Authorization URL を返す
const { authorizationUrl } = await response.json();
window.location.href = authorizationUrl;

// ↓ IdP で認証後、以下にリダイレクト

// バックエンド(Secure HttpOnly Cookie を設定)
app.get('/callback', (req, res) => {
  const code = req.query.code;

  // トークン交換
  const tokens = await exchangeCodeForTokens(code);

  // IDトークンを検証
  const userInfo = verifyIdToken(tokens.id_token);

  // Secure HttpOnly Cookie を設定
  res.cookie('session_id', generateSessionId(), {
    httpOnly: true,
    secure: true,
    sameSite: 'Strict'
  });

  res.redirect('https://myapp.com/dashboard');
});

このパターンの利点:

  • IDトークン・アクセストークンはブラウザに保存されない(XSS 攻撃対策)
  • バックエンド サーバーでトークン検証を実施
  • Secure HttpOnly Cookie を使用(CSRF 攻撃対策)

パターン 2:ネイティブアプリ(iOS/Android)

ネイティブアプリでは、デバイス内の安全なストレージを活用します。

// iOS での OIDC 実装例(ASWebAuthenticationSession 使用)
import AuthenticationServices

func initiateLogin() {
    let authorizationUrl = URL(string: "https://idp.com/oauth/authorize?client_id=...")!

    let session = ASWebAuthenticationSession(
        url: authorizationUrl,
        callbackURLScheme: "myapp"
    ) { callbackURL, error in
        guard let code = callbackURL?.queryItems?.first(where: { $0.name == "code" }) else {
            return
        }

        // トークン交換
        exchangeCodeForTokens(code.value) { tokens in
            // トークンは Keychain に安全に保存
            KeychainStorage.save(tokens.id_token, forKey: "id_token")
            KeychainStorage.save(tokens.access_token, forKey: "access_token")
        }
    }

    session.presentationContextProvider = self
    session.start()
}

パターン 3:BFF パターン(Backends for Frontends)

複数のフロントエンド(Web、iOS、Android)がある場合、BFF パターンが効果的です。

Web SPA ←→ Web BFF ←→ Google / Microsoft / LOCKED MSO
iOS App ←→ iOS BFF ←→
Android App ←→ Android BFF ←→

各 BFF がプラットフォーム固有の認証フローを実装し、バックエンド API はすべての BFF から認証されたリクエストを受け取ります。

LOCKED MSO での OpenID Connect 実装

標準搭載機能

LOCKED MSO は OIDC(OpenID Connect)対応の IdP として動作します。

主要機能:

  • 完全な OIDC 2.0 準拠: Authorization Code Flow、Implicit Flow、Hybrid Flow に対応
  • マルチプロトコル対応: SAML 2.0、OAuth 2.0 と同時対応
  • UserInfo エンドポイント: アクセストークンを使用した詳細ユーザー情報取得
  • アクセス制御: 12 項目の条件組み合わせによる動的フロー
  • 日本語対応: ドキュメント・サポート完全日本語対応

実装手順

ステップ 1:アプリケーションを登録

LOCKED MSO 管理画面:

セッティング → アプリケーション → 新規登録

アプリケーション名:MyWebApp
プロトコル:OpenID Connect
リダイレクト URI:https://myapp.com/callback

ステップ 2:Authorization URL を構成

https://locked.jp/oauth2/authorize?
  client_id=xxxxx
  &response_type=code
  &scope=openid email profile
  &redirect_uri=https://myapp.com/callback
  &state=random123

ステップ 3:IDトークン検証設定

oidc_config:
  verify_signature: true
  verify_expiration: true
  verify_issuer: true
  issuer: "https://locked.jp"
  allowed_algorithms: ["RS256"]

ステップ 4:テスト

# 実装したアプリケーションをテスト
curl -X POST https://locked.jp/oauth2/token \
  -d "grant_type=authorization_code" \
  -d "code=xxxx" \
  -d "client_id=yyyy" \
  -d "client_secret=zzzz" \
  -d "redirect_uri=https://myapp.com/callback"

# レスポンス
{
  "id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "access_token": "ya29.c.xxx",
  "token_type": "Bearer",
  "expires_in": 3600
}

実装企業の事例

事例 1:SaaS スタートアップ(ユーザー数 10,000 名)

導入前:

  • カスタム認証実装による開発リソース消費
  • パスワード再設定の対応で月 50 時間

LOCKED MSO + OIDC 導入:

  • Authorization Code Flow で安全に実装
  • SPA + バックエンド パターンを採用

導入結果(3 ヶ月後):

  • 開発時間削減:月 50 時間 → 0 時間
  • ユーザー登録フロー簡素化:5 ステップ → 1 ステップ
  • パスワードリセット対応削減:月 50 時間 → 月 5 時間

事例 2:エンタープライズ SaaS(従業員 500 名)

導入前:

  • Azure AD / Google Workspace / HENNGE One との連携が複雑
  • Protocol により対応状況が異なる

LOCKED MSO + マルチプロトコル対応:

  • OIDC(Google Workspace)
  • SAML 2.0(Azure AD)
  • を同時対応

導入結果(4 ヶ月後):

  • 統一認証基盤の確立
  • ユーザー管理の一元化
  • インシデント対応の簡素化(年間 200 時間削減)

まとめ:OIDC で安全で使いやすい認証を実現

OpenID Connect は OAuth 2.0 の上に認証レイヤーを追加することで、セキュアで標準化された認証をもたらします。Authorization Code Flow を正しく実装することで、XSS・CSRF・トークン盗難などの攻撃に強い認証基盤が実現できます。

LOCKED MSO を活用することで、複雑な OIDC 実装を避け、数日で本番環境への展開が可能です。


外部参考リンク

関連記事

LOCKED MSO で OIDC 実装を簡素化しませんか?

セキュアな Authorization Code Flow をわずか数日で展開できます。複数の IdP 連携も簡単に実現可能です。

資料請求・無料デモはこちら →

商標について:本記事に記載されているHENNGE OneAzure ADGoogle WorkspaceMicrosoft 365Slack等の製品名・サービス名は、各社の商標または登録商標です。

免責事項:本記事の情報は執筆時点のものであり、各製品の最新の機能・料金・仕様については、各社の公式サイトをご確認ください。本記事の内容に基づく判断・行動について、当社は一切の責任を負いかねます。

LOCKED MSO

この課題、LOCKEDで解決できます

「IDaaS導入RFPテンプレート」など、検討に役立つ資料を無料でご用意しています

LOCKEDシリーズの詳細資料を無料でダウンロード

導入事例、機能詳細、他社比較など、検討に必要な情報をまとめた資料をご用意しています

まずは資料で詳細を確認

製品資料で機能・料金・導入事例をまとめてご確認いただけます

資料をダウンロード