Google App Engine

Adding a Method Protected by OAuth

Any client can access your Endpoints API methods unless you protect them with OAuth 2.0. In some scenarios, you may want to restrict access to some or all of the API methods.

To protect a method in the backend API, you need to do two things:

  • Add a User parameter to the method you wish to protect.
  • Add the email scope to your @Api annotation.
  • Specify a clientIds whitelist in the @API annotation. (For Android devices only, you must also specify audiences.)

Adding an OAuth 2.0-protected method

To add the User parameter:

  1. Import one exception class and the App Engine User API in Greetings.java:

    import com.google.api.server.spi.response.UnauthorizedException;
    import com.google.appengine.api.users.User;
    
  2. Include a parameter of type User to the API method you wish to protect, as shown for the method greetings.authed in the snippet below, which you should add to Greetings.java:

    @ApiMethod(name = "greetings.authed", path = "greeting/authed")
    public HelloGreeting authedGreeting(User user) throws UnauthorizedException {
      if (user == null) {
        // Returns status code 401.
        throw new UnauthorizedException("Authorization required");
      }
      HelloGreeting response = new HelloGreeting("hello " + user.getEmail());
      return response;
    }
    
  3. Add a Constants.java class for the client IDs you will be adding, as follows:

    package com.google.appengine.samples.helloendpoints;
    
    /**
     * Contains the client IDs and scopes for allowed clients consuming the helloworld API.
     */
    public class Constants {
      public static final String WEB_CLIENT_ID = "replace this with your web client application ID";
      public static final String ANDROID_CLIENT_ID = "replace this with your Android client ID";
      public static final String IOS_CLIENT_ID = "replace this with your iOS client ID";
      public static final String ANDROID_AUDIENCE = WEB_CLIENT_ID;
    
      public static final String EMAIL_SCOPE = "https://www.googleapis.com/auth/userinfo.email";
      public static final String API_EXPLORER_CLIENT_ID
          = com.google.api.server.spi.Constant.API_EXPLORER_CLIENT_ID;
    }
    

    Notice that the Android audience is set to the value of the web client ID. (You only use audiences for Android clients.) Notice also that we put the email scope and API Explorer client ID constants here to keep the API annotation cleaner. The API Explorer client ID is needed if you want to use the Explorer to test your backend API without building your own client.

    Also, in the snippet above, except for the API Explorer client ID, which we need for testng, we show only dummy values for web, Android, and iOS clients. You replace each of these with a real client ID when you add the corresponding client.

  4. In your Greetings.java class, modify the @Api annotation to add the client IDs, and add the scopes argument, specifying the email scope as shown:

    @Api(
        name = "helloworld",
        version = "v1",
        scopes = {Constants.EMAIL_SCOPE},
        clientIds = {Constants.WEB_CLIENT_ID, Constants.ANDROID_CLIENT_ID,
            Constants.IOS_CLIENT_ID, Constants.API_EXPLORER_CLIENT_ID},
        audiences = {Constants.ANDROID_AUDIENCE}
    )
    

    Although you can add other scopes, you must always include the email scope if you use OAuth.

  5. Deploy the backend you just created to App Engine by invoking the command

    mvn appengine:update
    
  6. The first time you deploy, you may be prompted to supply your Google account email and a password before deployment is allowed. Follow the prompts to supply these.

  7. When the backend finishes deploying it will run at the URL your-appengine-app-id.appspot.com with your-appengine-app-id being the project ID you created during setup and supplied in appengine-web.xml during configuration. Open API Explorer at that location by visiting this URL in your browser:

    http://your-appengine-app-id.appspot.com/_ah/api/explorer
    
  8. In the API Explorer, click helloworld API > helloworld.greetings.authed.

  9. In the upper right of the API Explorer page, locate the toggle control labeled Authorize requests using OAuth 2.0 and click it On.

  10. You may be prompted to manually supply a scope: add the value https://www.googleapis.com/auth/userinfo.email and click Authorize.

  11. Click Execute and observe the authorization in the request, and a greeting with your user name in the response.

Code summary

The main things to note in this sample code are the User parameter and the clientIds whitelist.

Why the User param is required

When you declare a parameter of type User in your API method, the API backend framework automatically authenticates the user and enforces the authorized clientIds whitelist, ultimately by supplying the valid User or not.

If the request coming in from the client has a valid auth token or is in the list of authorized clientIDs, the backend framework supplies a valid User to the parameter. If the incoming request does not have a valid auth token or if the client is not on the clientIDs whitelist, the framework sets User to null.

Your own code must handle both the case where User is null and the case where there is a valid User. If there is no User, for example, you could choose to return a not-authenticated error or perform some other desired action. In this tutorial, we just return a response with 401 HTTP status (Unauthorized).

clientIds and audiences

The IDs in the clientids whitelist are values created for clients in the Google API console. Only those clients whose IDs are in the clientIds whitelist can access the protected method.

Although not shown in this tutorial, if one of the clients is an Android device, you must also supply the audiences attribute. For more information, see Client IDs and Audiences.

For more information on obtaining client IDs, see Using OAuth 2.0 with Endpoints.

Next...

This completes the tutorial.

For the advanced topics such as using datastore and creating clients of the API backend, see the following:

Authentication required

You need to be signed in with Google+ to do that.

Signing you in...

Google Developers needs your permission to do that.