Web サーバアプリケーションで OAuth2 を使う(for Google API)

このページは、 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 の管理者権限が必要です。

  1. Google Apps にログインして、管理コンソールを開きます。
  2. アプリ > その他のサービス から Google Developer Console を選択。
  3. これが「オン」になっている場合は問題ありません。
  4. 「オフ」になっている場合、利用規約に同意の上、メニューから「オン」にします。

Web アプリケーションの認証情報を作成する

OAuth 2.0 を使う Web アプリケーションは、必ず OAuth 2.0 サーバーに 対してそのアプリケーションを識別するための認証情報を持つ必要があります。 認証情報を持っているアプリケーションは、あなたのプロジェクトを有効 にするための API にアクセスできるようになります。

あなたのプロジェクトに関する Web アプリケーションの資格証明を取得するには、 以下の手順に従ってください。:

訳注:画面UIに沿って説明しますので、一部原文とは異なります。

  1. 資格証明のページを開きます。
    1. ログインしていない場合は、Google Developer Console の利用権限がある Google アカウントでログインします。
    2. プロジェクトを作成していない場合は、プロジェクトを作成します。
      Create Project
    3. プロジェクト作成に成功すると、以下のウィザードが表示されますので、 ここから OAuth 2.0 クライアント ID を追加するほうが簡単かもしれません。
      API認証情報 認証情報を追加 プロジェクト・ダッシュボード
  2. まだ作成していない場合は、左メニューの認証情報から 認証情報を追加 > OAuth 2.0 クライアント ID をクリックして作成します。
    クライアントIDを作成
  3. 「同意画面を設定」をクリックし、必要事項を記入して「保存」します。
    OAuth同意画面
  4. 「クライアントIDを作成」画面に戻りますので、アプリケーションの種類を選択し、 必要事項を記入して「作成」します。
    この画面では、リダイレクト URI を生成できます。 リダイレクト URI はあなたのアプリケーションの認証エンドポイントであり、 OAuth 2.0 サーバーからのレスポンスを処理します。OAuth 2.0 を使う前に、 この値をデフォルトの例から、 実際のあなたのアプリケーションの認証エンドポイントに変更してください。 テストのために、http://localhost:8080 のようにローカルマシンを指す URI を指定することも可能です。 認証コードがそのページの別のリソースに漏れることがないように、 あなたのアプリケーションの認証エンドポイントをデザインする必要があります。
    クライアントIDを作成
  5. 完了ダイアログが表示されますので「OK」で進みます。
    クライアントID作成完了ダイアログ
  6. ダッシュボードに戻ります。
    ダッシュボード

(右端のアイコンから)client_secrets.json ファイルをダウンロードして、 あなたのアプリケーションのみがアクセスできるところに保存します。

重要:client_secrets.json ファイルは、 誰でもアクセスできるところには置かないようにしてください。また、たとえば GitHub のようなところであなたのアプリケーションのソースコードを共有する場合は、 あなたのクライアントの認証情報をうっかり共有しないために、client_secrets.json ファイルをソースツリーの外に置くように心がけてください。

OAuth 2.0 の手順を始めるための準備

Google API クライアントライブラリを使って OAuth 2.0 の手順を行う場合、 OAuth 2.0 リクエストを作るのに使うクライアントオブジェクトを構成します。 OAuth 2.0 エンドポイントに対して直接アクセスする方式を取る場合は、 単に直前の手順で作成したクライアント ID 、 およびリクエストに必要なスコープに注意しておけば問題ありません。

クライアントオブジェクトを構成するには:

PHP

あなたのアプリケーションでクライアントオブジェクトを構成するために作成した client_secrets.json ファイルを使います。クライアントオブジェクトを構成する際、 あなたのアプリケーションの認証エンドポイントへの URL に加えて、あなたの アプリケーションがアクセスする必要のあるスコープ(範囲)を指定します。 この URL が OAuth 2.0 サーバーからのレスポンスを処理することになります。

たとえばユーザの Google ドライブへのリードオンリーアクセスを リクエストするなら以下のようになります。:

$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');

あなたのアプリケーションは、認可リクエスト URL を生成したり、 HTTP リクエストへのアクセストークンを適用するなどの OAuth 2.0 の操作を、クライアントオブジェクトを通して行います。

Google の OAuth 2.0 サーバーへのリダイレクト

あなたのアプリケーションがユーザのデータにアクセスする必要がある時は、 ユーザをGoogle の OAuth 2.0 サーバーにリダイレクトします。

PHP

  1. Google の OAuth 2.0 サーバーからアクセスのリクエストをするための URL を生成します。:
    $auth_url = $client->createAuthUrl();
    
  2. ユーザーを $auth_url にリダイレクトします。:
    header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
    

Google の OAuth 2.0 サーバーはユーザーを認証し、 あなたのアプリケーションが要求されたスコープにアクセスするための認可をユーザーから得ます。 そのレスポンスは、あなたが指定したリダイレクト URL を使ってあなたのアプリケーションに返送されます。

OAuth 2.0 サーバ-レスポンスの処理

OAuth 2.0 サーバ-は、あなたのアプリケーションのアクセスリクエストに対し、 リクエスト中で指定された URL を使ってレスポンスを返します。

ユーザーがアクセスリクエストを承認すると、 レスポンスの中に認可コードが埋め込まれます。 ユーザーがアクセスリクエストを承認しなかった場合、 レスポンスの中にエラーメッセージが埋め込まれます。 すべてのレスポンスは Web サーバーに返されますが、 その際以下のようなクエリー文字列が付きます。:

エラーレスポンス

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 にリダイレクトする、 その際レスポンス・パラメーターを含めないようにする、というやり方を推奨します。

Web サーバーが認可コードを受け取った後は、 認可コードをアクセストークンと交換することができるようになります。

PHP

認可コードをアクセストークンと交換する際は authenticate メソッドを使います。:

$client->authenticate($_GET['code']);

getAccessToken メソッドでアクセストークンを取り出します。:

$access_token = $client->getAccessToken();

Google API をコールする

PHP

アクセストークンを使って、以下の手順により Google API をコールします。:

  1. アクセストークンを新しい Google_Client オブジェクトに適用する場合、 - たとえば、アクセストークンをユーザーのセッションに保存している場合 -、 setAccessToken メソッドを使います。:
    $client->setAccessToken($access_token);
    
  2. コールしたい API のサービスオブジェクトをビルドします。認可済みの Google_Client オブジェクトをコールしたい API のコンストラクタに渡すことで、 サービスオブジェクトをビルドします。 たとえば Drive API をコールするなら以下のようになります。:
    $drive_service = new Google_Service_Drive($client);
    
  3. サービスオブジェクトで提供されるインターフェイスを使って API にリクエストを行います。たとえば、認可済みユーザーの Google ドライブのファイル一覧を取得する場合は以下のようになります。:
    $files_list = $drive_service->files->listFiles(array())->getItems();
    

完成例

以下の例では、ユーザー認証後、ユーザーがアプリケーションに対して自分の Google ドライブのファイルへのアクセスの承諾を行い、 その後アプリケーションがファイル一覧を JSON 形式で表示します。

PHP

この例の実行方法:

  1. Developers Console でリダイレクト URL 一覧のところにローカルマシンへの URL を追加します。たとえば http://localhost:8080 を追加します。
  2. 新しいディレクトリを作ってそこに入ります。たとえば、:
    mkdir ~/php-oauth2-example
    cd ~/php-oauth2-example
    
  3. PHP 用の Google API クライアントライブラリを手元にクローンします。:
    git clone https://github.com/google/google-api-php-client
    
  4. index.php と oauth2callback.php を以下の内容で作成します。
  5. PHP を動かせるように構成した Web サーバーでサンプルを実行します。 PHP 5.4 以降を使っている場合は PHP のテスト用ビルトインサーバーを使うこともできます。:
    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));
}

認可の延長

OAuth 2.0 プロトコルにおいて、 あなたのアプリケーションはリソースアクセスのための認可を要求しますが、 そのリソースはスコープで識別されます。 そのユーザの認証が通ってユーザーがそれを承認した場合、 あなたのアプリケーションは短時間有効なアクセストークンを受信します。 これによりこれらのリソースにアクセスできるようになりますが、 (オプションとして)トークンをリフレッシュすることで、 長時間のアクセスを許可してもらうことが可能です。

ユーザーリソースへのアクセス許可のリクエストは、 それが必要になった時にその場で行えるというのが、 ユーザーにとって最も望ましい動きではないでしょうか。たとえば、 楽曲のサンプリングやミキシングをやるようなアプリケーションであれば、 リソースへのサインイン時間は必要最小限であるべきであり、 さらにサインインする人の名前がわかれば十分です。しかしながら、 ミキシング結果の保存には、そのユーザの Google ドライブへのアクセス権が必要となります。 ほとんどユーザは、そのアプリが本当に必要なタイミングで Google ドライブへのアクセスを聞くのがより自然ではないでしょうか。

このケースでは、アプリへのサインインの際、アプリはサインインを実行するために プロファイルスコープを要求し、その後最初にミキシング結果を保存する際に https://www.googleapis.com/auth/drive.file スコープをリクエストします。

Using OpenID Connect Using OAuth 2.0 to Access Google APIs に記載されている手順を使えば、 2つの異なったアクセストークンを管理するようなアプリでも、 正しく結果を得ることが可能です。

この複雑さを避けるため、認可リクエストで事前に許可されたスコープを 含めることが可能です。以下に例を示します。:

PHP

$client->setIncludeGrantedScopes(true);

事前に許可されたスコープを含む認可リクエストを作成すると、 Googleの認可サーバーは、 リクエストしているアプリからリクエストしているユーザに対して事前に承諾されたすべての認可と一緒に、 認可リクエストを処理します。

オフラインアクセス

ケースによっては、あなたのアプリケーションはユーザがいない場合にも Google API へのアクセスを必要とするかもしれません。この例としては、 バックアップサービスや、月曜の朝8時ちょうどに Blogger に投稿するアプリ、 などが考えられます。この種類のアクセスはオフラインと呼ばれますが、 Web サーバーアプリケーションはユーザーにオフラインアクセスを要求することもできます。 通常のデフォルトのスタイルのアクセスはオンラインと呼ばれます。

PHP

もしあなたのアプリが Google API へのオフラインアクセスをする必要がある場合、 API クライアントのアクセスタイプをオフラインにします。

$client->setAccessType("offline");

要求されたスコープへのオフラインアクセスをユーザーが許可した後は、 ユーザーがオフラインの時であっても、あなたはユーザーに代わり、 API クライアントを使って継続的に Google API にアクセスできます。 クライアントオブジェクトは必要に応じてアクセストークンをリフレッシュします。

トークンの無効化

いったんあるアプリケーションに与えたアクセス権を取り消したいというケースもあるかもしれません。 ユーザーはアカウント設定画面でアクセス権を取り消すことができます。 アプリケーションがそれ自身に与えたアクセス権を、プログラム的に剥奪することもできます。 ユーザーは自ら購読の解除やアプリの削除をする可能性もあるので、 プログラム自身が剥奪できるようにしておくのはとても重要なことです。 言い換えると、取消処理の一部には、 アプリケーションに対して許可されたパーミッションを削除するような API リクエストが含まれるということです。

PHP

プログラム的にトークンを取り消すには revokeToken() をコールします。:

$client->revokeToken();
注意:取消処理が内部的に完了するまでは、 成功した取消レスポンスが返ってくるまでに時間がかかる場合があります。

特に記載のない限り、このページのコンテンツは クリエイティブ・コモンズの表示 3.0 ライセンス により使用許諾されます。サンプル コードは Apache 2.0 ライセンス (リンク先は英語)により使用許諾されます。詳しくは、Google のサイトに関するポリシーをご覧ください。

最終更新日: 8月 18, 2015

Go previous