ユーザー認証

ウェブ認証プロトコルは HTTP 機能を使用しますが、Chrome アプリはアプリコンテナ内で実行されます。HTTP 経由で読み込まれず、リダイレクトを実行したり Cookie を設定したりすることはできません。

Chrome Identity API を使用してユーザーを認証します。Google アカウントにログインしているユーザーの場合は getAuthToken、Google 以外のアカウントにログインしているユーザーの場合は launchWebAuthFlow です。アプリで独自のサーバーを使用してユーザーを認証する場合は、後者を使用する必要があります。

仕組み

Chrome アプリのユーザーは、各自のプロフィールに Google アカウントが関連付けられています。アプリは、getAuthToken API を使用して、これらのユーザーの OAuth2 トークンを取得できます。

Google 以外の ID プロバイダを使用して認証を行うアプリは、launchWebAuthFlow を呼び出す必要があります。この方法では、ブラウザのポップアップを使用してプロバイダのページを表示し、特定の URL パターンへのリダイレクトをキャプチャします。リダイレクト URL がアプリに渡され、アプリが URL からトークンを抽出します。

Google アカウント認証

次の 5 つのステップを完了してください。

  1. マニフェストに権限を追加して、アプリをアップロードします。
  2. インストールされている manifest.json のキーをソース マニフェストにコピーして、開発中にアプリケーション ID が変わらないようにします。
  3. Chrome アプリ用の OAuth2 クライアント ID を取得します。
  4. マニフェストを更新して、クライアント ID とスコープを追加します。
  5. 認証トークンを取得します。

権限を追加してアプリをアップロード

マニフェストに ID 権限が含まれていることを確認する必要があります。その後、アプリと拡張機能の管理ページにアプリをアップロードできます(公開をご覧ください)。

"permissions": [
  "identity"
]

マニフェストにキーをコピーする

Google OAuth コンソールにアプリケーションを登録するときは、アプリケーションの ID を指定します。この ID はトークンのリクエスト時にチェックされます。そのため、開発中は一貫したアプリケーション ID にすることが重要です。

アプリケーション ID を一定に維持するには、インストールされている manifest.json のキーをソース マニフェストにコピーする必要があります。これは最も優雅なタスクではありませんが、次のように進められます。

  1. ユーザーデータ ディレクトリに移動します。MacO での例: ~/Library/Application\ Support/Google/Chrome/Default/Extensions
  2. インストールされているアプリと拡張機能をリストし、アプリと拡張機能の管理ページに表示されているアプリ ID を、ここで同じ ID と一致させます。
  3. インストール済みアプリのディレクトリに移動します(これはアプリ ID 内のバージョンになります)。インストールされている manifest.json を開きます(pico を使用すると簡単にファイルを開くことができます)。
  4. インストールされている manifest.json の「キー」をコピーして、アプリのソース マニフェスト ファイルに貼り付けます。

OAuth2 クライアント ID を取得する

クライアント ID を取得するには、Google API Console にアプリを登録する必要があります。

  1. アプリを Chrome ウェブストアにアップロードする際に使用した Google アカウントで Google API コンソールにログインします。
  2. 左上にあるプルダウン メニューを開き、[作成] メニュー項目を選択して、新しいプロジェクトを作成します。
  3. 作成して名前を付けたら、[サービス] ナビゲーション メニュー項目に移動し、アプリに必要な Google サービスをオンにします。
  4. [API アクセス] ナビゲーション メニュー項目に移動し、[OAuth 2.0 クライアント ID を作成...] 青いボタンをクリックします。
  5. 必要なブランディング情報を入力し、[Installed application] タイプを選択します。
  6. [Chrome Application] を選択し、アプリケーション ID を入力します(アプリと拡張機能の管理ページに表示されるものと同じ ID)。

OAuth2 クライアント ID とスコープを使用してマニフェストを更新する

マニフェストを更新して、クライアント ID とスコープを追加する必要があります。以下は、gdrive サンプルのサンプル「oauth2」です。

"oauth2": {
    "client_id": "665859454684.apps.googleusercontent.com",
    "scopes": [
      "https://www.googleapis.com/auth/drive"
    ]
  }

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

これで、identity.getAuthToken を呼び出して認証トークンを取得する準備が整いました。

chrome.identity.getAuthToken({ 'interactive': true }, function(token) {
  // Use the token.
});

ユーザーの操作

getAuthToken を呼び出すときに、API をインタラクティブ モードとサイレント モードのどちらで呼び出すかを示すフラグ(上記の例では 'interactive': true)を渡すことができます。インタラクティブ モードで API を呼び出すと、次のスクリーンショットのように、必要に応じてログインや承認の UI がユーザーに表示されます。

アプリが Identity API を使用して Google アカウントを認証するときの UI を示すスクリーンショット

サイレント モードで API を呼び出した場合、UI を表示せずにトークンを生成できる場合にのみ、API はトークンを返します。これは、アプリがアプリの起動時にフローを実行する場合など、ユーザー操作が伴わない一般的に便利です。

ユーザー操作が伴わない場合はサイレント モードを使用し、ユーザーがアプリでログインボタンをクリックした場合など、ユーザー操作がある場合はインタラクティブ モードを使用することをおすすめします。なお、ジェスチャーの要件は強制されません。

キャッシュ

Chrome にはアクセス トークンのメモリ内キャッシュがあり、トークンを使用する必要があればいつでも getAuthToken を呼び出すことができます。トークンの有効期限は、キャッシュによって自動的に処理されます。

トークン キャッシュの現在の状態は chrome://identity-internals で確認できます。

ユーザーがパスワードを変更したときなど、期限が切れていないアクセス トークンが機能しなくなることがあります。トークンを使用した API 呼び出しは、HTTP ステータス コード 401 を返すようになります。このことが検出した場合は、identity.removeCachedAuthToken を呼び出して、Chrome のキャッシュから無効なトークンを削除できます。

removeCachedAuthToken の使用例:

// callback = function (error, httpStatus, responseText);
function authenticatedXhr(method, url, callback) {
  var retry = true;
  function getTokenAndXhr() {
    chrome.identity.getAuthToken({/* details */},
                                 function (access_token) {
      if (chrome.runtime.lastError) {
        callback(chrome.runtime.lastError);
        return;
      }

      var xhr = new XMLHttpRequest();
      xhr.open(method, url);
      xhr.setRequestHeader('Authorization',
                           'Bearer ' + access_token);

      xhr.onload = function () {
        if (this.status === 401 && retry) {
          // This status may indicate that the cached
          // access token was invalid. Retry once with
          // a fresh token.
          retry = false;
          chrome.identity.removeCachedAuthToken(
              { 'token': access_token },
              getTokenAndXhr);
          return;
        }

        callback(null, this.status, this.responseText);
      }
    });
  }
}

Google 以外のアカウント認証

次の 3 つの手順を完了してください。

  1. プロバイダに登録します。
  2. アプリがアクセスするプロバイダ リソースに対する権限を追加します。
  3. 認証トークンを取得します。

プロバイダに登録する

プロバイダに OAuth2 クライアント ID を登録し、クライアント ID をウェブサイトとして構成する必要があります。登録時に入力するリダイレクト URI には、https://<extension-id>.chromiumapp.org/<anything-here> という形式の URL を使用します。

たとえば、アプリ ID が abcdefghijklmnopqrstuvwxyzabcdef で、provider_cb をパスにする場合、他のプロバイダのリダイレクト URI と区別するために、https://abcdefghijklmnopqrstuvwxyzabcdef.chromiumapp.org/provider_cb を使用します。

プロバイダの権限を追加する

プロバイダ API エンドポイントにクロスオリジン XHR を作成するには、権限で適切なパターンを許可リストに登録する必要があります。

"permissions": [
  ...
  "https://www.website-of-provider-with-user-photos.com/photos/*"
]

トークンを取得する

トークンを取得するには:

chrome.identity.launchWebAuthFlow(
  {'url': '<url-to-do-auth>', 'interactive': true},
  function(redirect_url) { /* Extract token from redirect_url */ });

<url-to-do-auth> は、ウェブサイトからプロバイダに対して認証を行うための URL です。たとえば、プロバイダで OAuth2 フローを実行していて、アプリをクライアント ID 123456789012345 で登録していて、プロバイダのウェブサイト(https://www.website-of-provider-with-user-photos.com/dialog/oauth?client_id=123456789012345& redirect_uri=https://abcdefghijklmnopqrstuvwxyzabcdef.chromiumapp.org/provider_cb&response_type=token&scope=user_photos)にあるユーザーの写真にアクセスするとします。

プロバイダが認証を実行し、必要に応じて、ログインや承認の UI をユーザーに表示します。その後、https://abcdefghijklmnopqrstuvwxyzabcdef.chromiumapp.org/provider_cb#authToken=<auth-token> にリダイレクトされます。

Chrome はその情報を取得し、完全なリダイレクト URL でアプリのコールバックを呼び出します。アプリは URL からトークンを抽出する必要があります。

インタラクティブ モードとサイレント モード

launchWebAuthFlow を呼び出すときに、API をインタラクティブ モード(サイレント モード)で呼び出すかどうかを示すフラグ(上記の例では 'interactive': true)を渡すことができます。インタラクティブ モードで API を呼び出すと、必要に応じてトークンを取得するための UI がユーザーに表示されます(ログイン UI や承認 UI、あるいはプロバイダ固有の UI)。

サイレント モードで API を呼び出した場合、プロバイダが UI を表示せずにトークンを提供できる場合にのみ、API はトークンを返します。これは、アプリがアプリ起動時にフローを実行している場合など、またはユーザー操作が関与しない一般的な場合に有用です。

ユーザー操作が伴わない場合はサイレント モードを使用し、ユーザーがアプリでログインボタンをクリックした場合など、ユーザー操作がある場合はインタラクティブ モードを使用することをおすすめします。なお、ジェスチャーの要件は強制されません。