Google Identity Services ライブラリを使用すると、ユーザーはブラウザベースのポップアップまたはリダイレクト UX フローを使用して、Google に認証コードをリクエストできます。これにより、安全な OAuth 2.0 フローが開始され、ユーザーに代わって Google API を呼び出すために使用されるアクセス トークンが生成されます。
OAuth 2.0 認可コードフローの概要:
- ブラウザで、ボタンをクリックするなどの操作を行うと、Google アカウントのオーナーが Google に認可コードをリクエストします。
- Google は、ユーザーのブラウザで実行されている JavaScript ウェブアプリのコールバックに一意の認可コードを送信するか、ブラウザのリダイレクトを使用して認可コード エンドポイントを直接呼び出すことで応答します。
- バックエンド プラットフォームが認証コード エンドポイントをホストし、コードを受け取ります。検証後、このコードは Google のトークン エンドポイントへのリクエストを使用して、ユーザーごとのアクセス トークンと更新トークンと交換されます。
- Google は、認可コードを検証し、リクエストが安全なプラットフォームから送信されたことを確認し、アクセス トークンと更新トークンを発行して、プラットフォームでホストされているログイン エンドポイントを呼び出してトークンを返します。
- ログイン エンドポイントはアクセス トークンと更新トークンを受け取り、更新トークンを後で使用するために安全に保存します。
前提条件
設定に記載されている手順に沿って、OAuth 同意画面を構成し、クライアント ID を取得して、クライアント ライブラリを読み込みます。
コード クライアントを初期化する
google.accounts.oauth2.initCodeClient()
メソッドはコード クライアントを初期化します。
ポップアップ モードまたはリダイレクト モード
リダイレクト モードまたはポップアップ モードのユーザーフローを使用して、認証コードを共有できます。リダイレクト モードでは、OAuth2 認証エンドポイントをサーバーでホストし、Google がユーザー エージェントをこのエンドポイントにリダイレクトして、認証コードを URL パラメータとして共有します。ポップアップ モードでは、JavaScript コールバック ハンドラを定義します。このハンドラは、認証コードをサーバーに送信します。ポップアップ モードを使用すると、訪問者がサイトを離れることなくシームレスなユーザー エクスペリエンスを提供できます。
次のクライアントを初期化するには:
リダイレクト UX フロー。
ux_mode
をredirect
に設定し、redirect_uri
の値をプラットフォームの認可コード エンドポイントに設定します。この値は、Google Cloud コンソールで構成した OAuth 2.0 クライアントの承認済みリダイレクト URI のいずれかと完全に一致する必要があります。また、リダイレクト URI の検証ルールにも準拠している必要があります。ポップアップ UX フロー、
ux_mode
をpopup
に設定、callback
の値を、プラットフォームに認証コードを送信するために使用する関数の名前に設定します。redirect_uri
の値は、デフォルトでinitCodeClient
を呼び出すページのオリジンになります。この値は、後でフローで認証コードをアクセス トークンまたは更新トークンと交換するときに使用されます。たとえば、https://www.example.com/index.html
がinitCodeClient
を呼び出し、オリジンhttps://www.example.com
がredirect_url
の値であるとします。
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_CLIENT_ID',
scope: 'https://www.googleapis.com/auth/calendar.readonly',
ux_mode: 'redirect',
redirect_uri: 'https://oauth2.example.com/code',
state: 'YOUR_BINDING_VALUE'
});
ポップアップ モード
ユーザーがポップアップ ダイアログで認証フローを開始するクライアントを初期化します。同意が得られると、コールバック関数を使用して、Google からユーザーのブラウザに認可コードが返されます。JS コールバック ハンドラからの POST リクエストは、認証コードをバックエンド サーバーのエンドポイントに配信します。このエンドポイントで認証コードが検証され、OAuth フローの残りの部分が完了します。
const client = google.accounts.oauth2.initCodeClient({
client_id: 'YOUR_CLIENT_ID',
scope: 'https://www.googleapis.com/auth/calendar.readonly',
ux_mode: 'popup',
callback: (response) => {
const xhr = new XMLHttpRequest();
xhr.open('POST', "https://oauth2.example.com/code", 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_uri
で指定されたエンドポイントに 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 を直接呼び出す場合は、アクセス トークンをウェブ アプリケーションと共有する方法を実装する必要があります。このガイドでは、その方法については説明しません。このアプローチに従って Google API Client Library for JavaScript を使用する場合は、gapi.client.SetToken()
を使用してアクセス トークンをブラウザのメモリに一時的に保存し、ライブラリが Google API を呼び出せるようにします。