このページは、 Google Identity Platform > OAuth 2.0 Authentication > Web Apps にある Using OAuth 2.0 for Web Server Applications を PHP に特化した形で翻訳しつつ、実際の画面に沿って若干の補足をしたものです。 あくまでも、本家ページの日本語版が公開されるまでのつなぎという位置づけです。 原文は HTML のコメントとして残してあります。自己責任でお使いください。
目次
Google API のクライアントライブラリや Google OAuth 2.0 エンドポイントを 使うと、Oauth 2.0 認可機能を使って Google API にアクセスする Web サーバ アプリケーションを構築できます。OAuth 2.0 ではユーザが自分のユーザ名、 パスワードその他の情報を自分だけが見れる状態に保ったまま、アプリケーション 固有のデータを共有できるようになります。たとえば、ある Web アプリケーションは OAuth 2.0 を使ってユーザからパーミッションを取得し、それをユーザの Google ドライブに保存できます。
この文書では、OAuth 2.0 を使ったユーザの認可について記載しています。 Web アプリケーションで API コールを行う場合、特にクラウド API をコールして ユーザ固有データではなくプロジェクトベースのデータにアクセスする場合、 サービスアカウントを使うことがよくあります。これらのメカニズムは、Web サーバアプリケーションではユーザ認証と組合せて使うことができます。
注意:正しい実装を行うことでセキュリティの影響を排除するために、 Google の OAuth 2.0 エンドポイントとのやり取りを行う際は OAuth 2.0 ライブラリを使うことを強くお勧めします。他の人から提供された、 十分にデバッグが行われているコードを使うことがベストプラクティスであり、 あなたとあなたのユーザーを守ることになります。詳細は クライアントライブラリを参照してください。
Web アプリケーションで OAuth 2.0 を使う場合、まずは Developers Console であなたのプロジェクトの中で、Web アプリケーションの認証情報を作ります。
次に、あなたのアプリケーションが Google API でユーザーのデータに アクセスする必要がある場合、あなたのアプリケーションはそのユーザを Google の OAuth 2.0 にリダイレクトします。OAuth 2.0 サーバーはその ユーザーを認証し、さらにそのユーザーのデータにあなたのアプリケーションが アクセスするためにユーザーからの承諾を得ます。
次に Google の OAuth 2.0 サーバーは、使い捨ての認可コードと共に、 ユーザーをあなたのアプリケーションにリダイレクトで戻します。あなたの アプリケーションは、この認可コードをアクセストークンに交換します。
これでやっと、あなたのアプリケーションはアクセストークンを使って Google の API をコールできるようになります。
あなたのアプリケーションが OAuth 2.0 のフローを使うのに Google API
クライアントライブラリを使っている場合は、格納されたアクセストークンが
いつまで使えるか、アプリケーションが承諾コードをいつ再取得しないといけないか
などをクライアントライブラリが追跡し、また正しいリダイレクト用 URL を生成
したり、認可コードをアクセストークンと交換するためのリダイレクトハンドラの
実装をサポートしてくれたりします。あるアプリケーションがクライアント
ライブラリを使わずに OAuth 2.0 のフローを実行する場合は、これらのことを
すべて自前で面倒見てやる必要があります。
このページにある各言語毎の
Google API クライアントライブラリの使用例により、
2.0 による API の認可をより簡単にできる方法を紹介しています。
サンプルコードを実行するには、まずあなたの言語用のクライアントライブラリを
インストールする必要があります。
以下の言語についてクライアントライブラリが用意されています。:
(訳注:本ページでは PHP に関する部分のみの翻訳を行っています)
OAuth2 を使って Google API にアクセスするためには、
事前に以下の手順で Google Developer Console を有効にしておく必要があります。
この作業には Google Apps の管理者権限が必要です。
OAuth 2.0 を使う Web アプリケーションは、必ず OAuth 2.0 サーバーに
対してそのアプリケーションを識別するための認証情報を持つ必要があります。
認証情報を持っているアプリケーションは、あなたのプロジェクトを有効
にするための API にアクセスできるようになります。
あなたのプロジェクトに関する Web アプリケーションの資格証明を取得するには、
以下の手順に従ってください。:
(右端のアイコンから)client_secrets.json ファイルをダウンロードして、
あなたのアプリケーションのみがアクセスできるところに保存します。
Google API クライアントライブラリを使って OAuth 2.0 の手順を行う場合、
OAuth 2.0 リクエストを作るのに使うクライアントオブジェクトを構成します。
OAuth 2.0 エンドポイントに対して直接アクセスする方式を取る場合は、
単に直前の手順で作成したクライアント ID 、
およびリクエストに必要なスコープに注意しておけば問題ありません。
クライアントオブジェクトを構成するには:
あなたのアプリケーションでクライアントオブジェクトを構成するために作成した
client_secrets.json ファイルを使います。クライアントオブジェクトを構成する際、
あなたのアプリケーションの認証エンドポイントへの URL に加えて、あなたの
アプリケーションがアクセスする必要のあるスコープ(範囲)を指定します。
この URL が OAuth 2.0 サーバーからのレスポンスを処理することになります。
たとえばユーザの Google ドライブへのリードオンリーアクセスを
リクエストするなら以下のようになります。:
あなたのアプリケーションは、認可リクエスト URL を生成したり、
HTTP リクエストへのアクセストークンを適用するなどの OAuth 2.0
の操作を、クライアントオブジェクトを通して行います。
あなたのアプリケーションがユーザのデータにアクセスする必要がある時は、
ユーザをGoogle の OAuth 2.0 サーバーにリダイレクトします。
Google の OAuth 2.0 サーバーはユーザーを認証し、
あなたのアプリケーションが要求されたスコープにアクセスするための認可をユーザーから得ます。
そのレスポンスは、あなたが指定したリダイレクト
URL を使ってあなたのアプリケーションに返送されます。
OAuth 2.0 サーバ-は、あなたのアプリケーションのアクセスリクエストに対し、
リクエスト中で指定された URL を使ってレスポンスを返します。
ユーザーがアクセスリクエストを承認すると、
レスポンスの中に認可コードが埋め込まれます。
ユーザーがアクセスリクエストを承認しなかった場合、
レスポンスの中にエラーメッセージが埋め込まれます。
すべてのレスポンスは Web サーバーに返されますが、
その際以下のようなクエリー文字列が付きます。:
エラーレスポンス
認可コードレスポンス
Web サーバーが認可コードを受け取った後は、
認可コードをアクセストークンと交換することができるようになります。
認可コードをアクセストークンと交換する際は authenticate メソッドを使います。:
getAccessToken メソッドでアクセストークンを取り出します。:
アクセストークンを使って、以下の手順により Google API をコールします。:
以下の例では、ユーザー認証後、ユーザーがアプリケーションに対して自分の
Google ドライブのファイルへのアクセスの承諾を行い、
その後アプリケーションがファイル一覧を JSON 形式で表示します。
この例の実行方法:
OAuth 2.0 プロトコルにおいて、
あなたのアプリケーションはリソースアクセスのための認可を要求しますが、
そのリソースはスコープで識別されます。
そのユーザの認証が通ってユーザーがそれを承認した場合、
あなたのアプリケーションは短時間有効なアクセストークンを受信します。
これによりこれらのリソースにアクセスできるようになりますが、
(オプションとして)トークンをリフレッシュすることで、
長時間のアクセスを許可してもらうことが可能です。
ユーザーリソースへのアクセス許可のリクエストは、
それが必要になった時にその場で行えるというのが、
ユーザーにとって最も望ましい動きではないでしょうか。たとえば、
楽曲のサンプリングやミキシングをやるようなアプリケーションであれば、
リソースへのサインイン時間は必要最小限であるべきであり、
さらにサインインする人の名前がわかれば十分です。しかしながら、
ミキシング結果の保存には、そのユーザの Google ドライブへのアクセス権が必要となります。
ほとんどユーザは、そのアプリが本当に必要なタイミングで Google
ドライブへのアクセスを聞くのがより自然ではないでしょうか。
このケースでは、アプリへのサインインの際、アプリはサインインを実行するために
プロファイルスコープを要求し、その後最初にミキシング結果を保存する際に
https://www.googleapis.com/auth/drive.file スコープをリクエストします。
Using OpenID Connect と
Using OAuth 2.0 to Access Google APIs に記載されている手順を使えば、
2つの異なったアクセストークンを管理するようなアプリでも、
正しく結果を得ることが可能です。
この複雑さを避けるため、認可リクエストで事前に許可されたスコープを
含めることが可能です。以下に例を示します。:
事前に許可されたスコープを含む認可リクエストを作成すると、
Googleの認可サーバーは、
リクエストしているアプリからリクエストしているユーザに対して事前に承諾されたすべての認可と一緒に、
認可リクエストを処理します。
ケースによっては、あなたのアプリケーションはユーザがいない場合にも
Google API へのアクセスを必要とするかもしれません。この例としては、
バックアップサービスや、月曜の朝8時ちょうどに Blogger に投稿するアプリ、
などが考えられます。この種類のアクセスはオフラインと呼ばれますが、
Web サーバーアプリケーションはユーザーにオフラインアクセスを要求することもできます。
通常のデフォルトのスタイルのアクセスはオンラインと呼ばれます。
もしあなたのアプリが Google API へのオフラインアクセスをする必要がある場合、
API クライアントのアクセスタイプをオフラインにします。
要求されたスコープへのオフラインアクセスをユーザーが許可した後は、
ユーザーがオフラインの時であっても、あなたはユーザーに代わり、
API クライアントを使って継続的に Google API にアクセスできます。
クライアントオブジェクトは必要に応じてアクセストークンをリフレッシュします。
いったんあるアプリケーションに与えたアクセス権を取り消したいというケースもあるかもしれません。
ユーザーはアカウント設定画面でアクセス権を取り消すことができます。
アプリケーションがそれ自身に与えたアクセス権を、プログラム的に剥奪することもできます。
ユーザーは自ら購読の解除やアプリの削除をする可能性もあるので、
プログラム自身が剥奪できるようにしておくのはとても重要なことです。
言い換えると、取消処理の一部には、
アプリケーションに対して許可されたパーミッションを削除するような
API リクエストが含まれるということです。
プログラム的にトークンを取り消すには revokeToken() をコールします。:
特に記載のない限り、このページのコンテンツは
クリエイティブ・コモンズの表示 3.0 ライセンス
により使用許諾されます。サンプル コードは
Apache 2.0 ライセンス
(リンク先は英語)により使用許諾されます。詳しくは、Google
のサイトに関するポリシーをご覧ください。
最終更新日: 8月 18, 2015
クライアントライブラリ
(訳注:前提事項)
Web アプリケーションの認証情報を作成する
訳注:画面UIに沿って説明しますので、一部原文とは異なります。
この画面では、リダイレクト URI を生成できます。
リダイレクト URI はあなたのアプリケーションの認証エンドポイントであり、
OAuth 2.0 サーバーからのレスポンスを処理します。OAuth 2.0 を使う前に、
この値をデフォルトの例から、
実際のあなたのアプリケーションの認証エンドポイントに変更してください。
テストのために、http://localhost:8080 のようにローカルマシンを指す
URI を指定することも可能です。
認証コードがそのページの別のリソースに漏れることがないように、
あなたのアプリケーションの認証エンドポイントをデザインする必要があります。
重要:client_secrets.json ファイルは、
誰でもアクセスできるところには置かないようにしてください。また、たとえば
GitHub のようなところであなたのアプリケーションのソースコードを共有する場合は、
あなたのクライアントの認証情報をうっかり共有しないために、client_secrets.json
ファイルをソースツリーの外に置くように心がけてください。
OAuth 2.0 の手順を始めるための準備
PHP
$client = new Google_Client();
$client->setAuthConfigFile('client_secrets.json');
$client->addScope(Google_Service_Drive::DRIVE_METADATA_READONLY);
$client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php');
Google の OAuth 2.0 サーバーへのリダイレクト
PHP
$auth_url = $client->createAuthUrl();
header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
OAuth 2.0 サーバ-レスポンスの処理
https://oauth2-login-demo.appspot.com/auth?error=access_denied
https://oauth2-login-demo.appspot.com/auth?code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7
重要:あなたのレスポンスのエンドポイントが HTML ページを描画
する場合、そのページのすべてのリソースから認可コードが参照可能となります。
スクリプトからはその URL を直接読めますし、すべてのリソースは HTTP
ヘッダのリファラーとしてその URL を送るかもしれません。
そのページのすべてのリソース
(特にソーシャルプラグインやアナリティクスなどのサードパーティ製スクリプト)
に対して認証情報を見せても構わないのかを、注意深く検討してください。
この問題を避けるには、サーバーがまずリクエストを処理して、
その後別の URL にリダイレクトする、
その際レスポンス・パラメーターを含めないようにする、というやり方を推奨します。
PHP
$client->authenticate($_GET['code']);
$access_token = $client->getAccessToken();
Google API をコールする
PHP
$client->setAccessToken($access_token);
$drive_service = new Google_Service_Drive($client);
$files_list = $drive_service->files->listFiles(array())->getItems();
完成例
PHP
mkdir ~/php-oauth2-example
cd ~/php-oauth2-example
git clone https://github.com/google/google-api-php-client
php -S localhost:8080 ~/php-oauth2-example
index.php
<?php
require_once 'google-api-php-client/autoload.php';
session_start();
$client = new Google_Client();
$client->setAuthConfigFile('client_secrets.json');
$client->addScope(Google_Service_Drive::DRIVE_METADATA_READONLY);
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
$client->setAccessToken($_SESSION['access_token']);
$drive_service = new Google_Service_Drive($client);
$files_list = $drive_service->files->listFiles(array())->getItems();
echo json_encode($files_list);
} else {
$redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php';
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
oauth2callback.php
<?php
require_once 'google-api-php-client/autoload.php';
session_start();
$client = new Google_Client();
$client->setAuthConfigFile('client_secrets.json');
$client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php');
$client->addScope(Google_Service_Drive::DRIVE_METADATA_READONLY);
if (! isset($_GET['code'])) {
$auth_url = $client->createAuthUrl();
header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
} else {
$client->authenticate($_GET['code']);
$_SESSION['access_token'] = $client->getAccessToken();
$redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/';
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
認可の延長
PHP
$client->setIncludeGrantedScopes(true);
オフラインアクセス
PHP
$client->setAccessType("offline");
トークンの無効化
PHP
$client->revokeToken();
注意:取消処理が内部的に完了するまでは、
成功した取消レスポンスが返ってくるまでに時間がかかる場合があります。