コードモデルの使用

Google Identity Services ライブラリを使用すると、ユーザーはブラウザベースのポップアップまたはリダイレクト UX フローを使用して、Google から認可コードをリクエストできます。これにより、安全な OAuth 2.0 フローが開始され、ユーザーに代わって Google API を呼び出すために使用されるアクセス トークンが生成されます。

OAuth 2.0 認可コードフローの概要:

  • Google アカウントのオーナーは、ブラウザでボタンのクリックなどの操作で、Google に認可コードをリクエストします。
  • Google は、ユーザーのブラウザで実行されている JavaScript ウェブアプリのコールバックに一意の認可コードを送信するか、ブラウザのリダイレクトを使用して認可コード エンドポイントを直接呼び出します。
  • バックエンド プラットフォームが認可コード エンドポイントをホストし、コードを受信します。検証後、このコードは Google のトークン エンドポイントへのリクエストを使用して、ユーザーごとのアクセス トークンと更新トークンと交換されます。
  • Google は認可コードを検証し、リクエストが安全なプラットフォームから発信されたことを確認して、アクセス トークンと更新トークンを発行します。また、プラットフォームでホストされているログイン エンドポイントを呼び出して、トークンを返します。
  • ログイン エンドポイントはアクセス トークンと更新トークンを受け取り、後で使用できるように更新トークンを安全に保存します。

前提条件

設定の手順に沿って、OAuth 同意画面を構成し、クライアント ID を取得して、クライアント ライブラリを読み込みます。

Code クライアントを初期化する

google.accounts.oauth2.initCodeClient() メソッドはコード クライアントを初期化します。

認証コードを共有するには、リダイレクト モードまたはポップアップ モードのユーザーフローのいずれかを使用します。リダイレクト モードでは、サーバー上で OAuth2 認可エンドポイントをホストします。Google はユーザー エージェントをこのエンドポイントにリダイレクトし、認証コードを URL パラメータとして共有します。ポップアップ モードの場合は、認可コードをサーバーに送信する JavaScript コールバック ハンドラを定義します。ポップアップ モードを使用すると、ユーザーがサイトを離れることなくシームレスなユーザー エクスペリエンスを提供できます。

次のクライアントを初期化するには:

  • UX フローをリダイレクトし、ux_moderedirect に設定し、redirect_uri の値をプラットフォームの認可コード エンドポイントに設定します。この値は、API Console で構成した OAuth 2.0 クライアントの承認済みリダイレクト URI のいずれかと完全に一致する必要があります。また、リダイレクト URI の検証ルールにも準拠している必要があります。

  • ポップアップ UX フローの場合、ux_modepopup に設定し、callback の値を、プラットフォームに認証コードを送信するために使用する関数の名前に設定します。

CSRF 攻撃を防ぐ

クロスサイト リクエスト フォージェリ(CSRF)攻撃を防ぐため、リダイレクト モードとポップアップ モードの UX フローでは、若干異なる手法が採用されています。リダイレクト モードでは、OAuth 2.0 の state パラメータが使用されます。state パラメータの生成と検証について詳しくは、RFC6749 の 10.12 クロスサイト リクエスト フォージェリをご覧ください。ポップアップ モードでは、リクエストにカスタム HTTP ヘッダーを追加し、サーバーで想定される値と送信元と一致することを確認します。

UX モードを選択して、認証コードと CSRF 処理を示すコード スニペットを表示します。

リダイレクト モード

クライアントを初期化して、Google がユーザーのブラウザを認証エンドポイントにリダイレクトし、認証コードを URL パラメータとして共有します。

const client = google.accounts.oauth2.initCodeClient({
  client_id: 'YOUR_GOOGLE_CLIENT_ID',
  scope: 'https://www.googleapis.com/auth/calendar.readonly',
  ux_mode: 'redirect',
  redirect_uri: "https://your.domain/code_callback_endpoint",
  state: "YOUR_BINDING_VALUE"
});

ユーザーのブラウザが Google から認証コードを受信し、サーバーに送信するクライアントを初期化します。

const client = google.accounts.oauth2.initCodeClient({
  client_id: 'YOUR_GOOGLE_CLIENT_ID',
  scope: 'https://www.googleapis.com/auth/calendar.readonly',
  ux_mode: 'popup',
  callback: (response) => {
    const xhr = new XMLHttpRequest();
    xhr.open('POST', code_receiver_uri, true);
    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    // Set custom header for CRSF
    xhr.setRequestHeader('X-Requested-With', 'XmlHttpRequest');
    xhr.onload = function() {
      console.log('Auth code response: ' + xhr.responseText);
    };
    xhr.send('code=' + response.code);
  },
});

OAuth 2.0 コードフローをトリガーする

コード クライアントの requestCode() メソッドを呼び出して、ユーザーフローをトリガーします。

<button onclick="client.requestCode();">Authorize with Google</button>

この場合、ユーザーは Google アカウントにログインし、リダイレクト エンドポイントまたはコールバック ハンドラのいずれかに認可コードを返す前に、個々のスコープの共有に同意する必要があります。

認証コードの処理

Google はユーザーごとに一意の認可コードを生成し、バックエンド サーバーで受け取って検証します。

ポップアップ モードでは、callback で指定されたハンドラがユーザーのブラウザで実行され、認可コードをプラットフォームでホストされているエンドポイントにリレーします。

リダイレクト モードの場合、redirect_url で指定されたエンドポイントに GET リクエストが送信され、URL の code パラメータで認可コードが共有されます。認証コードを受け取るには:

  • 既存の実装がない場合は、新しい認可エンドポイント作成します。

  • GET リクエストと URL パラメータを受け入れるように既存のエンドポイントを更新します。以前は、ペイロードに認証コード値を含む PUT リクエストが使用されていました。

承認エンドポイント

認証コード エンドポイントは、次の URL クエリ文字列パラメータを使用して GET リクエストを処理する必要があります。

名前
authuser ユーザーのログイン認証をリクエストする
コード Google によって生成された OAuth2 認証コード
HD ユーザー アカウントのホストされているドメイン
プロンプト ユーザーの同意ダイアログ
スコープ 承認される 1 つ以上の OAuth2 スコープのスペース区切りリスト
state CRSF 状態変数

example.com でホストされている auth-code という名前のエンドポイントへの URL パラメータを含む GET リクエストの例:

Request URL: https://www.example.com/auth-code?state=42a7bd822fe32cc56&code=4/0AX4XfWiAvnXLqxlckFUVao8j0zvZUJ06AMgr-n0vSPotHWcn9p-zHCjqwr47KHS_vDvu8w&scope=email%20profile%20https://www.googleapis.com/auth/calendar.readonly%20https://www.googleapis.com/auth/photoslibrary.readonly%20https://www.googleapis.com/auth/contacts.readonly%20openid%20https://www.googleapis.com/auth/userinfo.email%20https://www.googleapis.com/auth/userinfo.profile&authuser=0&hd=example.com&prompt=consent

認可コードフローが以前の JavaScript ライブラリによって開始された場合、または Google OAuth 2.0 エンドポイントへの直接呼び出しによって開始された場合、POST リクエストが使用されます。

HTTP リクエスト本文に認証コードをペイロードとして含む POST リクエストの例:

Request URL: https://www.example.com/auth-code
Request Payload: 4/0AX4XfWhll-BMV82wi4YwbrSaTPaRpUGpKqJ4zBxQldU\_70cnIdh-GJOBZlyHU3MNcz4qaw

リクエストを検証します

サーバーで次の操作を行い、CSRF 攻撃を回避します。

リダイレクト モードの場合は、state パラメータの値を確認します。

X-Requested-With: XmlHttpRequest ヘッダーがポップアップ モードに設定されていることを確認します。

認証コード リクエストを正常に検証した場合にのみ、Google から更新トークンとアクセス トークンを取得する必要があります。

アクセス トークンと更新トークンを取得する

バックエンド プラットフォームが Google から認可コードを受信してリクエストを検証したら、認可コードを使用して Google からアクセス トークンと更新トークンを取得し、API 呼び出しを行います。

ウェブサーバー アプリケーションに OAuth 2.0 を使用するガイドのステップ 5: 認証コードを更新トークンとアクセス トークンと交換するから手順に沿って対応します。

トークンを管理する

プラットフォームが更新トークンを安全に保存している。ユーザー アカウントが削除されたとき、またはユーザーの同意が google.accounts.oauth2.revoke によって取り消されたとき、または https://myaccount.google.com/permissions から直接取り消されたときに、保存されている更新トークンを削除します。

必要に応じて、RISC を使用してクロスアカウント保護でユーザー アカウントを保護することもできます。

通常、バックエンド プラットフォームはアクセス トークンを使用して Google API を呼び出します。ウェブアプリがユーザーのブラウザから Google API を直接呼び出す場合も、アクセス トークンをウェブ アプリケーションと共有する方法を実装する必要があります。この方法については、このガイドの範囲外です。この方法で JavaScript 用 Google API クライアント ライブラリを使用する場合は、gapi.client.SetToken() を使用してアクセス トークンをブラウザのメモリに一時的に保存し、ライブラリが Google API を呼び出すようにします。