Sending an authenticated request from a JavaScript application

This page describes how to send an authenticated request from a JavaScript application running locally to a REST API created by using Cloud Endpoints Frameworks. The JavaScript application shows how to use Google Sign-In and how to send a Google ID token in the request to authenticate the user. When the JavaScript application sends the request, Endpoints Frameworks authenticates the user before passing the request to the backend code that is running on the App Engine standard environment.

Prerequisites

To run the sample JavaScript application:

  • Find the Google Cloud Platform (GCP) project ID that you created for the sample API because you need to add it to the sample JavaScript code. If you need help finding your project ID, see Listing projects.

  • You need a web server on your local computer to serve the sample index.html file that contains the JavaScript code. This page includes steps for running SimpleHTTPServer, which comes with Python 2.7, but you can use any web server.

Download the sample JavaScript client code

  1. Clone the sample to your local machine:

    git clone https://github.com/GoogleCloudPlatform/web-docs-samples
    
  2. Change to the directory that contains the JavaScript client:

    cd web-docs-samples/endpoints-frameworks
    

Creating OAuth 2.0 client IDs

To set up the sample for authentication, you need to configure an OAuth 2.0 client ID in the sample JavaScript code and in the backend code. The JavaScript app uses the client ID to obtain a Google ID token from Google's OAuth 2.0 server and sends the Google ID token in the request. Endpoints Frameworks uses the client ID to authenticate the ID token that the JavaScript app sent in the request.

To create a client ID:

  1. In the Google Cloud Platform Console, go to the Credentials page.

    Go to the Credentials page

  2. From the projects list, select the project that you created for the sample API.

  3. Click the Create credentials button, and then select OAuth client ID. If this is your first time creating a client ID in this project, use the sub-steps to set a product name on the consent screen; otherwise, skip to the next step.

    1. Click the Configure consent screen button.
    2. Enter a name in the Application name field.
    3. Click Save.
  4. Under Application type, click Web application.

  5. In the Authorized JavaScript origins field, enter the following:

    http://localhost:8080
    
  6. Click Create.

  7. Copy your client ID. Your complete client ID is similar to the following, but it is unique to the web application in your project.

    271473851874-mtll5dk2vultovbtilt31hakqbinpuvd.apps.googleusercontent.com

For more information about creating client IDs, see Setting up OAuth 2.0.

Configuring the backend code and redeploying

For Cloud Endpoints Frameworks to authenticate the request sent from the JavaScript application, you have to add the client ID you just created to the sample code and redeploy an updated OpenAPI document and the application's backend code.

The following procedure assumes that you have already deployed the sample API from Getting started with Endpoints Frameworksfor Python. Make sure that you get a successful response when you send a request to the API as described in Sending a request to the API before starting the following procedure.

To configure the backend code and redeploy:

  1. In the directory where you cloned the python-docs-samples repository, change to the directory that contains the Python sample:

    cd YOUR_WORKING_DIRECTORY/python-docs-samples/appengine/standard/endpoints-frameworks-v2/echo
    
  2. Open the main.py file in a text editor.

  3. In the decorator for the get_user_email function, replace your-oauth-client-id.com with the client ID you just created.

  4. Save the main.py file.

  5. Make sure you are in the sample main directory:

    python-docs-samples/appengine/standard/endpoints-frameworks-v2/echo
    
  6. Regenerate the OpenAPI document so that it contains the client ID. In the following command, replace YOUR_PROJECT_ID with the project that you created for the sample API.

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

    On successful completion, the following message is displayed:

    OpenAPI spec written to ./echov1openapi.json
    
  7. Make sure that the Cloud SDK (gcloud) is authorized to access your data and services on GCP:

    gcloud auth login
    
  8. Set the default project for the gcloud command-line tool. Replace YOUR_PROJECT_ID with the project that you created for the sample API:

    gcloud config set project YOUR_PROJECT_ID
    
  9. Deploy the updated OpenAPI document:

    gcloud endpoints services deploy echov1openapi.json
    

    On successful completion, the command outputs a line similar the following:

    Service Configuration [2018-02-13r2] uploaded for service [example-project-12345.appspot.com]
    
  10. Copy the new service configuration ID.

  11. Open the app.yaml file in text. Replace the value of the ENDPOINTS_SERVICE_VERSION field with the new service configuration ID. For example:

    ENDPOINTS_SERVICE_NAME: example-project-12345.appspot.com
    ENDPOINTS_SERVICE_VERSION: 2018-02-13r2
    
  12. Save the app.yaml file.

  13. Redeploy the backend code:

    gcloud app deploy
    

Configuring the JavaScript code

To configure the JavaScript code:

  1. In the web-docs-samples/endpoints-frameworks directory, open the main.js file in a text editor.
  2. In the initGoogleAuth function, replace YOUR_CLIENT_ID with the client ID that you created.

    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. In the sendSampleRequest function, replace YOUR_PROJECT_ID with the project ID that you created for the sample API.

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

Sending an authenticated request

  1. In the directory where you cloned the web-docs-samples repository, change to the directory that contains the JavaScript sample:

    cd YOUR_WORKING_DIRECTORY/web-docs-samples/endpoints-frameworks
    
  2. Start your web server to serve index.html on port 8080. The following example uses Python 2.7's SimpleHTTPServer:

    python -m SimpleHTTPServer 8080
    
  3. In your browser, enter localhost:8080.

    The JavaScript application displays two buttons.

    Sign In

  4. Click Sign In. The Sign in with Google page appears.

  5. After you've signed in, click the Send sample request button. The first time you send a request, you might experience a delay of about 20 seconds as App Engine starts up. Endpoints Frameworks intercepts the requests and uses the client ID that you configured in the backend code to authenticate the request. If the authentication is successful:

    1. Endpoints Frameworks passes the request to the sample backend running on App Engine.

    2. In the backend code, the get_user_email method returns the email address of the user account that you used when you signed in.

    3. The JavaScript client displays a dialog box with the email address.

Overview of the JavaScript client

The JavaScript client uses Google Sign-In, which manages the OAuth 2.0 flow. This section provides a brief overview of the JavaScript client code.

Auth set up

  1. Load the Google APIs Platform Library to create the gapi object:

      <script src="https://apis.google.com/js/platform.js?onload=loadAuthClient" async defer></script>
    </head>
  2. After the Google APIs Platform Library loads, load the auth2 library:

    function loadAuthClient () {
      gapi.load('auth2', initGoogleAuth);
    }
  3. Initialize the GoogleAuth object:

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

When you initialize the GoogleAuth object, you configure the object with your OAuth 2.0 client ID and any additional options you want to specify. Typically, you specify the access scope. Scopes enable your application to only request access to the resources that it needs while also enabling users to control the amount of access that they grant to your application. Before you start implementing OAuth 2.0 authorization, we recommend that you identify the scopes that your application needs permission to access. This example requests access to the https://www.googleapis.com/auth/userinfo.email scope, which grants access to view the user's email address.

Sign in

After you've initialized the GoogleAuth object, you can prompt the user to sign in by calling the signIn function of the GoogleAuth object:

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

Make a request with the ID token

When the user finishes signing in, send a request with an Authorization header with the user's ID token:

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

What's next

Bu sayfayı yararlı buldunuz mu? Lütfen görüşünüzü bildirin:

Şunun hakkında geri bildirim gönderin...

Cloud Endpoints Frameworks for App Engine
Yardım mı gerekiyor? Destek sayfamızı ziyaret edin.