DEV Community

Cover image for 開発者向けChatGPTログイン:OAuthフロー、プラン利用、API請求額への影響
Akira
Akira

Posted on Originally published at apidog.com

開発者向けChatGPTログイン:OAuthフロー、プラン利用、API請求額への影響

「ChatGPTでサインイン」は、OpenAIのOAuth 2.0およびOpenID Connect(OIDC)を使ったログイン機能です。世界中のChatGPTユーザーが利用でき、アプリは安定したアカウントIDに加えて、氏名、メールアドレス、プロフィール写真を取得できます。2026年9月29日のDevDay以降、参加アプリではPlusおよびProユーザーがAPIキーではなくChatGPTプランに基づいてAIリクエストを実行できます。アプリごとの週次上限はありますが、アプリがユーザーの会話、記憶、OpenAI APIキーを受け取ることはありません。

今すぐApidogを試す

この記事では、実装フロー、プラン利用の制約、APIキーとの使い分け、そしてApidogでOAuthフローと失敗ケースを検証する方法を説明します。イベント全体についてはDevDay 2026のまとめ、OAuthとOIDCの役割の違いについてはOAuthとOpenIDを参照してください。

ChatGPTでサインインの概要

項目 OpenAIがドキュメント化している内容
IDスコープ openid profile email
プラン使用スコープ(オープンソースフロー) offline_access resource.invoke chatgpt.tokens.use.direct と resource=https://api.openai.com/v1
アプリが受け取るもの IDトークン。プラン利用時はアクセストークンとリフレッシュトークン
プラン使用の資格 参加アプリのPlusおよびProユーザー
使用量がカウントされる場所 プランのChatGPT WorkおよびCodexの使用量
アプリごとの制御 全体の週次使用量に対する週次上限。上限超過後のクレジットはデフォルトで無効
プラン利用トークン アクセストークンは1時間、リフレッシュトークンは30日。有効な更新時にリフレッシュトークンは置換される
開発者アクセス 商用アプリは興味表明フォーム経由の限定トライアル、オープンソースアプリはセルフサービス

情報源:Sign in with ChatGPTドキュメント、トークンリファレンス、他のアプリでChatGPTプランを使用する方法。

アプリが受け取るものと、受け取らないもの

まず、ID取得とプラン利用を別の認可として扱います。

ID取得

openid profile email を要求すると、アプリはIDトークンを受け取ります。ウェブサイトガイドによると、各スコープは次を対象にします。

  • openid: OIDCログインとIDトークン
  • profile: 氏名、プロフィール画像などの利用可能なクレーム
  • email: メールアドレスとメール認証クレーム

このIDスコープだけでは、ChatGPTの会話やOpenAI APIリソースへアクセスできません。

ローカルアカウントを識別する際は、メールアドレスではなく、検証済みの次の組み合わせをキーにしてください。

issuer + client_id + sub
Enter fullscreen mode Exit fullscreen mode

OpenAIは、メールアドレスの一致だけではアカウント所有権の証明にならないと説明しています。既存アカウントと関連付ける場合は、ユーザーにリンク確認を求める実装にします。

プラン利用

プラン利用には、IDスコープとは別に追加スコープへの同意が必要です。ユーザーが許可すると、対象のResponses APIリクエストで使用できるアクセストークンが返されます。

IDのみのログインで必要なのは id_token です。access_token は不要です。

OAuthフローを実装する

ウェブアプリでは、OIDCを含むPKCE付き認可コードグラントを実装します。エンドポイントは https://auth.openai.com/.well-known/openid-configuration から取得できます。

Issuer:                 https://auth.openai.com
Authorization endpoint: https://auth.openai.com/api/accounts/authorize
Token endpoint:         https://auth.openai.com/api/accounts/oauth/token
JWKS URI:               https://auth.openai.com/.well-known/jwks.json
Enter fullscreen mode Exit fullscreen mode

実装は次の順序で進めます。

  1. バックエンドで state、nonce、PKCEベリファイアを生成する
  2. S256のPKCEチャレンジを作成する
  3. 認可エンドポイントへブラウザをリダイレクトする
  4. コールバックで state を照合する
  5. 認可コードをトークンエンドポイントで交換する
  6. IDトークンの署名、発行者、オーディエンス、有効期限、nonce を検証する
  7. sub を使ってローカルユーザーを検索・作成・リンクする
  8. アプリ独自のセッションを発行する

認可リクエストでは、登録済みのリダイレクトURIを完全一致で指定してください。

scope=openid profile email
Enter fullscreen mode Exit fullscreen mode

プラン利用も要求するオープンソースフローでは、必要なスコープとリソースを追加します。

offline_access resource.invoke chatgpt.tokens.use.direct
resource=https://api.openai.com/v1
Enter fullscreen mode Exit fullscreen mode

PKCE付きOAuth 2.0認可コードフローの一般的な実装は、PKCE付きOAuth 2.0フローも参照してください。

クライアントシークレットの扱い

公開クライアントはクライアントシークレットを送信しません。

機密クライアントで client_secret_basic を使う場合は、シークレットをHTTP Basic認証ヘッダーでのみ送信します。リクエストボディやフロントエンドコードに含めないでください。

オープンソースツールの登録

オープンソースかつローカルホスト型のツールでは、オープンソースのサインインガイドに従って、次の値から始めます。

client_id=dynamic_agent_client
agent_name_hint=<アプリ名>
ext_agent_host_id=<ホストごとに永続化するID>
Enter fullscreen mode Exit fullscreen mode

コールバックでは、oaiapp_... 形式などの発行済みクライアントIDが返されます。このIDは保存し、以後のフローで再利用します。

  • リダイレクトURIには 127.0.0.1 のループバックURIを使用する
  • クライアントシークレットは使用しない
  • ext_agent_host_id はホストごとに安定して保持する

ユーザーに表示すべきプラン利用の挙動

プラン利用を提供する場合、UIとサポートドキュメントで次を明確にしてください。

  • 対象リクエストはユーザーのプラン使用量にカウントされる

    PlusまたはProのChatGPT WorkおよびCodex使用量に基づきます。

  • アプリごとに週次上限がある

    ユーザーは週ごとの全体使用量に対する割合として上限を設定します。ドキュメントの例では10%から100%です。これは予約済み枠ではないため、他の場所での利用によって先に上限へ達する場合があります。

  • 上限後のクレジット継続はオプトイン

    上限超過後もクレジットを使い続ける設定はデフォルトでオフです。利用するにはアプリ上限を100%に設定する必要があります。

  • Plusには共有の5時間制限がある

    アカウントとセッションのページによると、この制限はプラン利用を行うすべてのアプリに共有されます。Proには適用されません。

  • 接続解除後、以後の利用は停止する

    過去の消費量は戻りません。また、OpenAIからアプリへ切断通知は送られません。リクエストまたはトークン更新の失敗で検知します。

ユーザーは chatgpt.com/settings/usage で利用状況を管理します。UIガイドラインに従い、アプリ内には使用量を管理へのリンクを表示してください。

参加対象とクライアントIDの取得

OpenAIのDevDayまとめには、CognitionのDevin、Notion、Vercel、T3、OpenClaw、Dactylを含む16のプラン利用パートナーが記載されています。The New StackはAmp、Warp、Kilo Code、OpenCodeなどを挙げ、Lovableは近日公開予定としています。OpenClawは両方のリストに掲載されています。

The New Stackは、サム・アルトマンによる次のステージ発言を報じています。

今や、ユーザーを動かすためにトークン費用を負担する必要はありません。

参加方法はアプリの提供形態で異なります。

  • 商用またはホスト型アプリ

    サインインは限定トライアルです。ID取得のみでもプラン利用を含む場合でも、OpenAIの興味表明フォームを通じてウェイトリストに参加し、クライアントIDをリクエストします。ドキュメントではプラン利用を「トークン共有」と呼んでいます。

  • オープンソースおよびローカルホスト型ツール

    プラン利用は、前述のセルフサービスフローを通じてすべてのオープンソースパートナーに開放されています。

APIキー利用とChatGPTプラン利用の使い分け

プラン利用では、モデルコストがユーザーのサブスクリプション側に移ります。ただし、利用可能なユーザー、リクエスト形式、失敗時の挙動には制約があります。

アプリのAPIキー ユーザーのChatGPTプラン
誰が支払うか アプリ側。トークンごとに課金 ユーザーのプラン。上限後のクレジットはオプトイン時のみ
誰が使えるか すべてのユーザー chatgpt.tokens.use.direct を許可したPlusおよびProユーザー
制限 アプリ側のレート制限ティア 週次プラン使用量、アプリごとの上限、Plusの5時間枠
リクエスト形式 Responses API全体 store: false と stream: true が必須
使用できない機能 アプリ側の設計による temperature、max_output_tokens、ファイル検索、Code Interpreter
典型的な失敗 ティア超過時の429 429 subscription_sharing_usage_limit_exceeded、またはストリーム中の response.failed
フォールバック アプリ側で設計 自動切り替えなし。OpenAIは請求先を切り替えない
UI表示 アプリの料金と使用量 「ChatGPTプランを使用中」、使用量管理リンク、対応プラン

制限の詳細はプレビュー制限ページにあります。保存済み会話状態やホスト型ツールを必要とする機能は、現時点ではユーザーのプランでは実行できません。

実装上は、次のハイブリッド構成が実用的です。

Plus / Proユーザーの対話操作
  → ChatGPTプラン利用

無料ユーザー、バックグラウンドジョブ、CI、定期実行エージェント
  → アプリ側のAPIキー
Enter fullscreen mode Exit fullscreen mode

プラン利用の上限に達したときは、次の順序で処理します。

  1. プラン利用リクエストを停止する
  2. 使用量を管理へのリンクを表示する
  3. 必要であれば、アプリ側クレジットまたは別の請求パスを選択肢として提示する

一般的な選択基準はAPIキーとOAuthの比較、ユーザーの代理で安全に実行する設計はAIエージェント向けのOAuthを参照してください。

Apidogでサインインフローと失敗パスをテストする

ApidogはChatGPTでサインインする機能そのものではありません。OAuth設定、トークン交換、レスポンス検証、失敗処理をテストするために使用します。

Apidogをダウンロードし、まずテスト用環境を作成してください。

1. クライアント設定を環境変数へ保存する

次の変数を環境に追加します。

SIWC_CLIENT_ID
SIWC_REDIRECT_URI
SIWC_CLIENT_SECRET
ACCESS_TOKEN
Enter fullscreen mode Exit fullscreen mode

SIWC_CLIENT_SECRET は機密値として設定します。保存済みリクエストへシークレットを直接書かず、変数参照を使います。

{{SIWC_CLIENT_ID}}
{{SIWC_REDIRECT_URI}}
{{SIWC_CLIENT_SECRET}}
{{ACCESS_TOKEN}}
Enter fullscreen mode Exit fullscreen mode

2. PKCE付き認可コードフローを実行する

ApidogのAuthタブで、OAuth 2.0の認可コードフローとPKCEを選択します。

設定する値は次のとおりです。

Authorization URL:
https://auth.openai.com/api/accounts/authorize

Token URL:
https://auth.openai.com/api/accounts/oauth/token

Scope:
openid profile email
Enter fullscreen mode Exit fullscreen mode

プラン利用をテストするオープンソースフローでは、追加スコープとリソースも設定します。

offline_access resource.invoke chatgpt.tokens.use.direct
resource=https://api.openai.com/v1
Enter fullscreen mode Exit fullscreen mode

リダイレクトURIはクライアントに登録したものをそのまま使います。各設定項目はApidog OAuth 2.0ガイドで確認できます。

3. トークン交換とIDトークンを検証する

トークン交換リクエストを、再利用できるPOSTリクエストとして保存します。バックエンドでは署名とnonceを必ず検証してください。Apidogでは、レスポンス形式と主要クレームをテストします。

const body = pm.response.json();

pm.test("token exchange returned an ID token", () => {
  pm.expect(pm.response.code).to.eql(200);
  pm.expect(body.id_token).to.be.a("string");
});

const decode = require("atob");
const part = body.id_token
  .split(".")[1]
  .replace(/-/g, "+")
  .replace(/_/g, "/");

const claims = JSON.parse(
  decode(part + "=".repeat((4 - (part.length % 4)) % 4))
);

pm.test("ID token claims match this client", () => {
  pm.expect(claims.iss).to.eql("https://auth.openai.com");
  pm.expect(claims.aud).to.include(pm.environment.get("SIWC_CLIENT_ID"));
  pm.expect(claims.sub).to.be.a("string").and.not.empty;
  pm.expect(claims.exp * 1000).to.be.above(Date.now());
});
Enter fullscreen mode Exit fullscreen mode

name、email、picture は利用可能な場合に返されます。常に存在するものとしてアサートせず、ログへ記録するか、存在する場合だけ処理してください。

プラン利用をテストする場合は、scope に chatgpt.tokens.use.direct が含まれることも検証します。

pm.test("plan usage scope is granted", () => {
  pm.expect(body.scope).to.include("chatgpt.tokens.use.direct");
});
Enter fullscreen mode Exit fullscreen mode

4. 失敗パスをモックする

実際のPlusアカウントを失敗テストのフィクスチャにしないでください。Apidogモックサーバーで以下のレスポンスを用意し、アプリの分岐をテストします。

プラン利用が拒否された場合

トークンレスポンスの scope に chatgpt.tokens.use.direct を含めません。

期待するアプリの挙動は次のとおりです。

  • サインイン状態は維持する
  • プラン利用の有効化を案内する、または別の請求パスへ進める
  • ログイン失敗として扱わない

上限に達した場合

HTTP 429と次のエラーコードを返します。

{
  "error": {
    "code": "subscription_sharing_usage_limit_exceeded"
  }
}
Enter fullscreen mode Exit fullscreen mode

ストリーミング中の失敗もテストします。

event: response.failed
data: {"error":{"code":"subscription_sharing_usage_limit_exceeded"}}
Enter fullscreen mode Exit fullscreen mode

このケースでは、プラン利用リクエストを停止し、使用量管理への導線を表示します。

資格がない場合

HTTP 403
subscription_sharing_user_not_eligible
Enter fullscreen mode Exit fullscreen mode

この場合、再試行ループやOAuthフローの再開始を行わないでください。

接続が解除された場合

トークン更新で次を返します。

invalid_grant
Enter fullscreen mode Exit fullscreen mode

またはAPI呼び出しで次を返します。

HTTP 401
subscription_sharing_invalid_user
Enter fullscreen mode Exit fullscreen mode

この場合は保存済みトークンを削除し、再サインインを求めます。

これらのモックをテストシナリオとして連結し、Apidog CLIでCI実行します。全エラーセットはエラーと回復のページで確認できます。

5. 実際のプラントークンでストリーミングを確認する

実際のプラントークンを使い、Bearer {{ACCESS_TOKEN}} を指定してResponses APIへリクエストします。

プラン利用では、store: false と stream: true が必須です。成功判定はHTTPステータスだけでなく、ストリームが response.completed で終了することまで確認してください。

curl --no-buffer https://api.openai.com/v1/responses \
  -H "Authorization: Bearer ${ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-6.1-sol",
    "input": [{"role": "user", "content": "Say exactly: Hello, world!"}],
    "store": false,
    "stream": true
  }'
Enter fullscreen mode Exit fullscreen mode

よくある質問

無料ユーザーはChatGPTでサインインできますか?

できます。サインインは世界中のChatGPTユーザーが利用できます。ただし、他のアプリでChatGPTプランを利用するにはPlusまたはProが必要です。

アプリはユーザーのOpenAI APIキーを取得しますか?

いいえ。アプリが取得するのはIDトークンと、プラン利用時に対象のResponses APIリクエストで使うOAuthアクセストークンです。

ユーザーがプラン上限に達するとどうなりますか?

リクエストは subscription_sharing_usage_limit_exceeded で失敗します。HTTP 429として返る場合と、ストリーム開始後に response.failed イベントとして返る場合があります。プラン利用を停止し、使用量管理へのリンクを表示してください。

PlusユーザーはパートナーアプリでGPT-6.1 Solを実行できますか?

ドキュメントの例では、プラントークンで gpt-6.1-sol を使用しています。ただし、提供前にそのトークンでアカウントの利用可能モデルを確認してください。詳細はGPT-6.1 Solは無料かを参照してください。

次のステップ

商用アプリを運営している場合は、まずウェイトリストに参加し、クライアントIDを待つ間に失敗処理を実装してください。

優先順位は次のとおりです。

  1. PKCE、state、nonce を含むOAuthコールバックを実装する
  2. IDトークンの署名とクレームをバックエンドで検証する
  3. sub、発行者、クライアントIDでアカウントを関連付ける
  4. subscription_sharing_usage_limit_exceeded、invalid_grant、401、403をモックでテストする
  5. プラン利用とアプリ側APIキーのフォールバック方針を決める
  6. トークン検証と失敗シナリオをApidogに保存し、CIで実行する

クライアントIDが発行された時点で、既存のテスト環境へ実トークンを設定すれば、すぐに統合検証を開始できます。

Top comments (0)