JavaScript アプリケーションからの認証済みリクエストの送信

このページでは、ローカルで実行されている JavaScript アプリケーションから、Cloud Endpoints Frameworks を使用して作成された REST API に認証済みリクエストを送信する方法について説明します。この JavaScript アプリケーションは、Google ログインの使用方法と、リクエストで Google ID トークンを送信してユーザーを認証する方法を示します。JavaScript アプリケーションがリクエストを送信すると、Endpoints Frameworks がユーザーを認証してから、App Engine スタンダード環境で実行されているバックエンド コードにリクエストを渡します。

前提条件

サンプル JavaScript アプリケーションを実行するには:

  • サンプル JavaScript コードに追加する必要があるため、サンプル API 用に作成した Google Cloud プロジェクト ID を確認します。プロジェクト ID を確認する方法がわからない場合は、プロジェクトの一覧表示をご覧ください。

  • ローカルのパソコン上に、JavaScript コードが含まれるサンプル index.html ファイルを提供するウェブサーバーが必要です。このページでは Python を使用して単純なサーバーを実行するための手順を説明しますが、どのウェブサーバーにも使用できます。

サンプル JavaScript クライアント コードをダウンロードする

  1. ローカルマシンにサンプルのクローンを作成します。

    git clone https://github.com/GoogleCloudPlatform/web-docs-samples
    
  2. JavaScript クライアントを含むディレクトリに移動します。

    cd web-docs-samples/endpoints-frameworks
    

OAuth 2.0 クライアント ID を作成する

サンプルで認証を行うための準備として、OAuth 2.0 クライアント ID をサンプル JavaScript コードとバックエンド コードで構成する必要があります。JavaScript アプリはこのクライアント ID を使用して Google の OAuth 2.0 サーバーから Google ID トークンを取得し、この ID トークンをリクエストに含めて送信します。Endpoints Frameworks は、JavaScript アプリからのリクエストに含まれる ID トークンを認証する際に、クライアント ID を使用します。

クライアント ID を作成するには:

  1. Google Cloud Console で、[認証情報] ページに移動します。

    [ドメインの確認] ページに移動

  2. プロジェクト リストから、サンプル API 用に作成したプロジェクトを選択します。

  3. [認証情報を作成] ボタンをクリックし、[OAuth クライアント ID] を選択します。今回初めてこのプロジェクトでクライアント ID を作成する場合は、次のサブステップを使用して同意画面でプロダクト名を設定します。それ以外の場合は、次の手順に進んでください。

    1. [同意画面を構成] ボタンをクリックします。
    2. [アプリケーション名] フィールドに名前を入力します。
    3. [保存] をクリックします。
  4. [アプリケーションの種類] で、[ウェブ アプリケーション] をクリックします。

  5. [承認済みの JavaScript 生成元] フィールドに次のように入力します。

    http://localhost:8080
    
  6. [作成] をクリックします。

  7. クライアント ID をコピーします。完全なクライアント ID は次のようになりますが、プロジェクト内のウェブ アプリケーションによって異なります。

    271473851874-mtll5dk2vultovbtilt31hakqbinpuvd.apps.googleusercontent.com

クライアント ID の作成方法については、OAuth 2.0 の設定をご覧ください。

バックエンド コードを構成して再デプロイする

JavaScript アプリケーションから送信されたリクエストを Cloud Endpoints Frameworks で認証するには、前の手順で作成したクライアント ID をサンプルコードに追加し、更新された OpenAPI ドキュメントとアプリケーションのバックエンド コードを再デプロイします。

以下の手順では、Python での Endpoints Frameworks スタートガイドに従ってすでにサンプル API をデプロイしていることを前提とします。 以下の手順を開始する前に、API にリクエストを送信するの手順に従って API にリクエストを送信し、正常なレスポンスが返されることを確認してください。

バックエンド コードを構成して再デプロイするには:

  1. python-docs-samples リポジトリのクローンを作成したディレクトリで、Python サンプルが格納されているディレクトリに移動します。

    cd YOUR_WORKING_DIRECTORY/python-docs-samples/appengine/standard/endpoints-frameworks-v2/echo
    
  2. テキスト エディタで main.py ファイルを開きます。

  3. get_user_email 関数のデコレータで、your-oauth-client-id.com を先ほど作成したクライアント ID に置き換えます。

  4. main.py ファイルを保存します。

  5. サンプルのメイン ディレクトリにいることを確認します。

    python-docs-samples/appengine/standard/endpoints-frameworks-v2/echo
    
  6. クライアント ID が含まれるように OpenAPI ドキュメントを再生成します。次のコマンドで、YOUR_PROJECT_ID はサンプル API 用に作成したプロジェクトに置き換えます。

    python lib/endpoints/endpointscfg.py get_openapi_spec main.EchoApi \
        --hostname YOUR_PROJECT_ID.appspot.com
    

    正常に完了すると、次のメッセージが表示されます。

    OpenAPI spec written to ./echov1openapi.json
    
  7. Google Cloud CLI(gcloud)が、Google Cloud にある対象のデータとサービスへのアクセスが許可されていることを確認します。

    gcloud auth login
    
  8. Google Cloud CLI のデフォルト プロジェクトを設定します。YOUR_PROJECT_ID は、サンプル API 用に作成したプロジェクトに置き換えます。

    gcloud config set project YOUR_PROJECT_ID
    
  9. 更新された OpenAPI ドキュメントをデプロイします。

    gcloud endpoints services deploy echov1openapi.json
    

    正常に完了すると、次のような行が出力されます。

    Service Configuration [2018-02-13r2] uploaded for service [example-project-12345.appspot.com]
    
  10. 新しいサービス構成 ID をコピーします。

  11. テキストで app.yaml ファイルを開きます。ENDPOINTS_SERVICE_VERSION フィールドの値は、新しいサービス構成 ID で置き換えます。例:

    ENDPOINTS_SERVICE_NAME: example-project-12345.appspot.com
    ENDPOINTS_SERVICE_VERSION: 2018-02-13r2
    
  12. app.yaml ファイルを保存します。

  13. バックエンド コードを再デプロイします。

    gcloud app deploy
    

JavaScript コードを構成する

JavaScript コードを構成するには:

  1. web-docs-samples/endpoints-frameworks ディレクトリで、main.js ファイルをテキスト エディタで開きます。
  2. initGoogleAuth 関数で、YOUR_CLIENT_ID を作成したクライアント ID に置き換えます。

    function initGoogleAuth (clientId = 'YOUR_CLIENT_ID') {
      gapi.auth2.init({
        client_id: clientId,
        scope: 'https://www.googleapis.com/auth/userinfo.email'
      }).then(() => {
        document.getElementById('sign-in-btn').disabled = false;
      }).catch(err => {
        console.log(err);
      });
    }
  3. sendSampleRequest 関数で、YOUR_PROJECT_ID をサンプル API 用に作成したプロジェクト ID に置き換えます。

    function sendSampleRequest (projectId = 'YOUR_PROJECT_ID') {
      var user = gapi.auth2.getAuthInstance().currentUser.get();
      var idToken = user.getAuthResponse().id_token;
      var endpoint = `https://${projectId}.appspot.com/_ah/api/echo/v1/email`;
      var xhr = new XMLHttpRequest();
      xhr.open('GET', endpoint + '?access_token=' + encodeURIComponent(idToken));
      xhr.onreadystatechange = function () {
        if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {
          window.alert(xhr.responseText);
        }
      };
      xhr.send();
    }

認証済みリクエストを送信する

  1. web-docs-samples リポジトリのクローンを作成したディレクトリで、JavaScript サンプルを含むディレクトリに移動します。

    cd YOUR_WORKING_DIRECTORY/web-docs-samples/endpoints-frameworks
    
  2. index.html を提供するウェブサーバーをポート 8080 で起動します。次の例では、Python のシンプルなサーバーを使用します。

    python -m http.server 8080
    
  3. ブラウザに「localhost:8080」と入力します。

    JavaScript アプリケーションが 2 つのボタンを表示します。

    ログイン

  4. [Sign In] をクリックします。[Sign in with Google] ページが表示されます。

  5. ログインした後、[Send sample request] ボタンをクリックします。初めてリクエストを送信するとき、App Engine の起動時に 20 秒ほど遅延が発生する場合があります。Endpoints Frameworks がリクエストを傍受し、クライアント ID(バックエンド コードで構成したもの)を使用してリクエストを認証します。認証が成功した場合、次のように処理が進みます。

    1. Endpoints Frameworks は、App Engine で実行されているサンプル バックエンドにリクエストを渡します。

    2. バックエンド コードの get_user_email メソッドが、ログイン時に使用されたユーザー アカウントのメールアドレスを返します。

    3. JavaScript クライアントが、メールアドレスを含むダイアログ ボックスを表示します。

JavaScript クライアントの概要

この JavaScript クライアントは Google ログインを使用し、Google ログインが OAuth 2.0 のフローを管理します。このセクションでは、JavaScript クライアント コードの概要を示します。

Auth の設定

  1. Google API プラットフォーム ライブラリを読み込んで gapi オブジェクトを作成します。

      <script src="https://apis.google.com/js/platform.js?onload=loadAuthClient" async defer></script>
    </head>
  2. Google API プラットフォーム ライブラリを読み込んだ後、auth2 ライブラリを読み込みます。

    function loadAuthClient () {
      gapi.load('auth2', initGoogleAuth);
    }
  3. GoogleAuth オブジェクトを初期化します。

    function initGoogleAuth (clientId = 'YOUR_CLIENT_ID') {
      gapi.auth2.init({
        client_id: clientId,
        scope: 'https://www.googleapis.com/auth/userinfo.email'
      }).then(() => {
        document.getElementById('sign-in-btn').disabled = false;
      }).catch(err => {
        console.log(err);
      });
    }

GoogleAuth オブジェクトを初期化するとき、OAuth 2.0 クライアント ID と追加オプションを指定してオブジェクトを構成します。通常はアクセス スコープを指定します。スコープを指定すると、アプリケーションからのアクセス リクエストは必要なリソースのみに限定されるようになり、ユーザーはアプリケーションに付与するアクセスレベルを制御できます。OAuth 2.0 認証の実装を開始する前に、アプリケーションがアクセス権限を必要とするスコープを設定しておくことをおすすめします。この例では、https://www.googleapis.com/auth/userinfo.email スコープへのアクセスをリクエストしています。このスコープは、ユーザーのメールアドレスを表示するためのアクセス権を付与します。

ログイン

GoogleAuth オブジェクトを初期化した後、GoogleAuth オブジェクトの signIn 関数を呼び出すことで、ユーザーにログインを求めることができます。

function signIn () {
  gapi.auth2.getAuthInstance().signIn().then(() => {
    document.getElementById('sign-in-btn').hidden = true;
    document.getElementById('sign-out-btn').hidden = false;
    document.getElementById('send-request-btn').disabled = false;
  }).catch(err => {
    console.log(err);
  });
}

ID トークンを指定してリクエストを発行する

ユーザーのログインが完了したら、ユーザーの ID トークンを含む Authorization ヘッダーを付けてリクエストを送信します。

function sendSampleRequest (projectId = 'YOUR_PROJECT_ID') {
  var user = gapi.auth2.getAuthInstance().currentUser.get();
  var idToken = user.getAuthResponse().id_token;
  var endpoint = `https://${projectId}.appspot.com/_ah/api/echo/v1/email`;
  var xhr = new XMLHttpRequest();
  xhr.open('GET', endpoint + '?access_token=' + encodeURIComponent(idToken));
  xhr.onreadystatechange = function () {
    if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {
      window.alert(xhr.responseText);
    }
  };
  xhr.send();
}

次のステップ