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 ドキュメントとアプリケーションのバックエンド コードを再デプロイします。

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

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

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

    cd YOUR_WORKING_DIRECTORY/java-docs-samples/appengine-java8/endpoints-v2-backend
    
  2. テキスト エディタで src/main/java/com/example/echo/Echo.java ファイルを開きます。

  3. getUserEmail メソッドの @ApiMethod アノテーションで、属性 audiencesclientIdsYOUR_OAUTH_CLIENT_ID を、作成したクライアント ID に置き換えます。

    @ApiMethod(
        httpMethod = ApiMethod.HttpMethod.GET,
        authenticators = {EspAuthenticator.class},
        audiences = {"YOUR_OAUTH_CLIENT_ID"},
        clientIds = {"YOUR_OAUTH_CLIENT_ID"}
    )
    public Email getUserEmail(User user) throws UnauthorizedException {
      if (user == null) {
        throw new UnauthorizedException("Invalid credentials");
      }
    
      Email response = new Email();
      response.setEmail(user.getEmail());
      return response;
    }
  4. Echo.java ファイルを保存します。

  5. プロジェクトを削除してから API をビルドします。

    Maven

    mvn clean package

    Gradle

          gradle clean
          gradle build
  6. クライアント ID を含むように OpenAPI ドキュメント openapi.json を作り直します。

    Maven

    mvn endpoints-framework:openApiDocs

    Gradle

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

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

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

    gcloud endpoints services deploy target/openapi-docs/openapi.json
    
  10. コマンドが終了するのを待ってから、アプリケーションを再デプロイします。

    Maven

    mvn appengine:deploy

    Gradle

    gradle appengineDeploy

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. バックエンド コードの getUserEmail メソッドが、ログイン時に使用されたユーザー アカウントのメールアドレスを返します。

    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();
}

次のステップ