Please note that the contents of this offline web site may be out of date. To access the most recent documentation visit the online version .
Note that links that point to online resources are green in color and will open in a new window.
We would love it if you could give us feedback about this material by filling this form (You have to be online to fill it)



Adding a Method Protected by OAuth

In this tutorial, we are adding a new protected method called greetings.authed .

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 the following:

  • Use the allowed_client_ids argument in the @endpoints.api decorator to provide a whitelist of allowed clients.
  • Add the email scope ( endpoints.EMAIL_SCOPE ) to your @endpoints.api decorator.
  • Add a current user check ( endpoints.get_current_user ) to each method you wish to protect.

Adding an OAuth 2.0-protected method

To protect a method by OAuth:

  1. In the helloworld_api.py file created previously, add the following client ID whitelist under the imports:

    import endpoints
    from protorpc import messages
    from protorpc import message_types
    from protorpc import remote
    
    WEB_CLIENT_ID = 'replace this with your web client application ID'
    ANDROID_CLIENT_ID = 'replace this with your Android client ID'
    IOS_CLIENT_ID = 'replace this with your iOS client ID'
    ANDROID_AUDIENCE = WEB_CLIENT_ID
    
    package = 'Hello'
    

    In the snippet above, 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.

    For more information on creating client IDs, see Creating OAuth 2.0 client IDs .

  2. In the @endpoints.api add the allowed_client_ids argument, supplying the list of client IDs that you want to authenticate, and add the scopes argument, specifying the email scope as shown:

    @endpoints.api(name='helloworld', version='v1',
                   allowed_client_ids=[WEB_CLIENT_ID, ANDROID_CLIENT_ID,
                                       IOS_CLIENT_ID, endpoints.API_EXPLORER_CLIENT_ID],
                   audiences=[ANDROID_AUDIENCE],
                   scopes=[endpoints.EMAIL_SCOPE])
    class HelloWorldApi(remote.Service):
        """helloworld API v1."""
    

    In the snippet above, notice the ID endpoints.API_EXPLORER_CLIENT_ID ; this is needed for testing against the API Explorer in production.

    Also, notice the use of the audiences argument ( ANDROID_AUDIENCE ), which is defined as the web client. This argument is required for Android clients and is not used by other clients. As shown, it must be set to the web client ID. For more information, see Allowed Client IDs and Audiences .

    Finally, notice that we supplied the email scope, endpoints.EMAIL_SCOPE . Although you can add other scopes, you must always include the email scope if you use OAuth.

  3. After the method definition for greetings.getGreeting , add the following code:

    @endpoints.method(message_types.VoidMessage, Greeting,
                      path='hellogreeting/authed', http_method='POST',
                      name='greetings.authed')
    def greeting_authed(self, request):
        current_user = endpoints.get_current_user()
        email = (current_user.email() if current_user is not None
                 else 'Anonymous')
        return Greeting(message='hello %s' % (email,))
    
  4. When you are finished, your file should look like this:

    """Hello World API implemented using Google Cloud Endpoints.
    
    Defined here are the ProtoRPC messages needed to define Schemas for methods
    as well as those methods defined in an API.
    """
    
    import endpoints
    from protorpc import messages
    from protorpc import message_types
    from protorpc import remote
    
    WEB_CLIENT_ID = 'replace this with your web client application ID'
    ANDROID_CLIENT_ID = 'replace this with your Android client ID'
    IOS_CLIENT_ID = 'replace this with your iOS client ID'
    ANDROID_AUDIENCE = WEB_CLIENT_ID
    
    package = 'Hello'
    
    class Greeting(messages.Message):
        """Greeting that stores a message."""
        message = messages.StringField(1)
    
    
    class GreetingCollection(messages.Message):
        """Collection of Greetings."""
        items = messages.MessageField(Greeting, 1, repeated=True)
    
    
    STORED_GREETINGS = GreetingCollection(items=[
        Greeting(message='hello world!'),
        Greeting(message='goodbye world!'),
    ])
    
    
    @endpoints.api(name='helloworld', version='v1',
                   allowed_client_ids=[WEB_CLIENT_ID, ANDROID_CLIENT_ID,
                                       IOS_CLIENT_ID, endpoints.API_EXPLORER_CLIENT_ID],
                   audiences=[ANDROID_AUDIENCE],
                   scopes=[endpoints.EMAIL_SCOPE])
    class HelloWorldApi(remote.Service):
        """helloworld API v1."""
    
        MULTIPLY_METHOD_RESOURCE = endpoints.ResourceContainer(
                Greeting,
                times=messages.IntegerField(2, variant=messages.Variant.INT32,
                                            required=True))
    
        @endpoints.method(MULTIPLY_METHOD_RESOURCE, Greeting,
                          path='hellogreeting/{times}', http_method='POST',
                          name='greetings.multiply')
        def greetings_multiply(self, request):
            return Greeting(message=request.message * request.times)
    
    
        @endpoints.method(message_types.VoidMessage, GreetingCollection,
                          path='hellogreeting', http_method='GET',
                          name='greetings.listGreeting')
        def greetings_list(self, unused_request):
            return STORED_GREETINGS
    
        ID_RESOURCE = endpoints.ResourceContainer(
                message_types.VoidMessage,
                id=messages.IntegerField(1, variant=messages.Variant.INT32))
    
        @endpoints.method(ID_RESOURCE, Greeting,
                          path='hellogreeting/{id}', http_method='GET',
                          name='greetings.getGreeting')
        def greeting_get(self, request):
            try:
                return STORED_GREETINGS.items[request.id]
            except (IndexError, TypeError):
                raise endpoints.NotFoundException('Greeting %s not found.' %
                                                  (request.id,))
        @endpoints.method(message_types.VoidMessage, Greeting,
                          path='hellogreeting/authed', http_method='POST',
                          name='greetings.authed')
        def greeting_authed(self, request):
            current_user = endpoints.get_current_user()
            email = (current_user.email() if current_user is not None
                     else 'Anonymous')
            return Greeting(message='hello %s' % (email,))
    
    APPLICATION = endpoints.api_server([HelloWorldApi])
    

Deploying and Testing

To test the backend API with real Auth, you must deploy your backend API to the App Engine project you created at the beginning of this tutorial.

To deploy and run:

  1. Deploy the backend you just created to App Engine by invoking the following:

    ~/path/to/python/sdk/google_appengine/appcfg.py update helloworld
    

    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.

    When the backend finishes deploying, a message similar to this one is displayed:

    09:08 AM Completed update of app: your-app-id, version: 1
    
  2. Check the logs for your project to make sure the backend deployed successfully.

  3. Open API Explorer at this URL in your browser:

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

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

  6. You'll be prompted to manually supply a scope: supply the value https://www.googleapis.com/auth/userinfo.email and click Authorize .

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

Code summary

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 when endpoints.get_current_user() is invoked. If the incoming request does not have a valid auth token or if the client is not on the clientIDs whitelist, endpoints.get_current_user() returns Null .

Accordingly, if the request comes from a client that isn't in the whitelist, there will be no current user. Your own code must handle both the case where the current user is null and the case where there is a valid current 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 simply identify the non authenticated user as Anonymous .

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.