File: google_app_engine.md

package info (click to toggle)
python-googleapi 1.7.11-4
  • links: PTS
  • area: main
  • in suites: bullseye
  • size: 110,952 kB
  • sloc: python: 7,784; javascript: 249; makefile: 59; sh: 53; xml: 5
file content (149 lines) | stat: -rw-r--r-- 9,193 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# Using Google App Engine

The Google APIs Client Library for Python has special support for [Google App Engine](https://developers.google.com/appengine) applications. In particular, there are decorators and classes that simplify the OAuth 2.0 protocol steps. Before reading this page, you should be familiar with the content on this library's [OAuth 2.0](https://developers.google.com/api-client-library/python/guide/aaa_oauth) page.

## Decorators

The easiest way to handle OAuth 2.0 is to use the App Engine [Python decorators](http://en.wikipedia.org/wiki/Python_syntax_and_semantics#Decorators) supplied by this library. These decorators handle all of the OAuth 2.0 steps without you having to use any `Flow`, `Credentials`, or `Storage` objects.

There are two decorator classes to choose from:

*   **OAuth2Decorator**: Use the [OAuth2Decorator](https://oauth2client.readthedocs.io/en/latest/source/oauth2client.contrib.appengine.html#oauth2client.contrib.appengine.OAuth2Decorator) class to contruct a decorator with your client ID and secret.
*   **OAuth2DecoratorFromClientSecrets**: Use the [OAuth2DecoratorFromClientSecrets](https://oauth2client.readthedocs.io/en/latest/source/oauth2client.contrib.appengine.html#oauth2client.contrib.appengine.OAuth2DecoratorFromClientSecrets) class to contruct a decorator using a `client_secrets.json` file described in the [flow\_from\_clientsecrets()](https://developers.google.com/api-client-library/python/guide/aaa_oauth#flow_from_clientsecrets) section of the OAuth 2.0 page.

There are also two decorator types to choose from:

*   **oauth\_required**: Any method decorated with `oauth_required` completes all OAuth 2.0 steps before entering the function. Within the body of the function, you can use the decorator's `http()` function to get an `Http` object that has already been authorized.
*   **oauth\_aware**: This decorator type requires a little more code than `oauth_required`, but it is preferred because it gives you control over the user experience. For example, you can display a page explaining why the user is being redirected to an authorization server. This decorator does not perform any OAuth 2.0 steps, but within the body of the decorated function you can call these convenient decorator functions:
    *   **has\_credentials()**: Returns `True` if there are valid access credentials for the logged in user.
    *   **authorize\_url()**: Returns the first URL that starts the OAuth 2.0 steps.

When using these decorators, you need to add a specific URL handler to your application to handle the redirection from the authorization server back to your application. This handler takes care of the final OAuth 2.0 steps required to finish authorization, and it redirects the user back to the original path where your application first detected that authorization was needed.

```py
def main():
  application = webapp.WSGIApplication(
    [
      ('/', MainHandler),
      ('/about', AboutHandler),
      (decorator.callback_path, decorator.callback_handler()),
    ],
    debug=True)
  run_wsgi_app(application)
```

In the following code snippet, the `OAuth2Decorator` class is used to create an `oauth_required` decorator, and the decorator is applied to a function that accesses the [Google Calendar API](https://developers.google.com/google-apps/calendar/):

```py
from apiclient.discovery import build
from google.appengine.ext import webapp
from oauth2client.contrib.appengine import OAuth2Decorator

decorator = OAuth2Decorator(
  client_id='your_client_id',
  client_secret='your_client_secret',
  scope='https://www.googleapis.com/auth/calendar')

service = build('calendar', 'v3')

class MainHandler(webapp.RequestHandler):

  @decorator.oauth_required
  def get(self):
    # Get the authorized Http object created by the decorator.
    http = decorator.http()
    # Call the service using the authorized Http object.
    request = service.events().list(calendarId='primary')
    response = request.execute(http=http)
    ...
```

In the following code snippet, the `OAuth2DecoratorFromClientSecrets` class is used to create an `oauth_aware` decorator, and the decorator is applied to a function that accesses the [Google Tasks API](https://developers.google.com/google-apps/tasks/):

```py
import os
from apiclient.discovery import build
from google.appengine.ext import webapp
from oauth2client.contrib.appengine import OAuth2DecoratorFromClientSecrets

decorator = OAuth2DecoratorFromClientSecrets(
  os.path.join(os.path.dirname(__file__), 'client_secrets.json'),
  'https://www.googleapis.com/auth/tasks.readonly')

service = build('tasks', 'v1')

class MainHandler(webapp.RequestHandler):

  @decorator.oauth_aware
  def get(self):
    if decorator.has_credentials():
      response = service.tasks().list(tasklist='@default').execute(decorator.http())
      # Write the task data
      ...
    else:
      url = decorator.authorize_url()
      # Write a page explaining why authorization is needed,
      # and provide the user with a link to the url to proceed.
      # When the user authorizes, they get redirected back to this path,
      # and has_credentials() returns True.
      ...
```

## Service Accounts

If your App Engine application needs to call an API to access data owned by the application's project, you can simplify OAuth 2.0 by using [Service Accounts](https://developers.google.com/accounts/docs/OAuth2ServiceAccount). These server-to-server interactions do not involve a user, and only your application needs to authenticate itself. Use the [AppAssertionCredentials](https://oauth2client.readthedocs.io/en/latest/source/oauth2client.contrib.appengine.html#oauth2client.contrib.appengine.AppAssertionCredentials) class to create a `Credentials` object without using a `Flow` object.

In the following code snippet, a `Credentials` object is created and an `Http` object is authorized:

import httplib2from google.appengine.api import memcachefrom oauth2client.contrib.appengine import  AppAssertionCredentials  
...credentials \=  AppAssertionCredentials(scope\='https://www.googleapis.com/auth/devstorage.read\_write')http \= credentials.authorize(httplib2.Http(memcache))

Once you have an authorized `Http` object, you can pass it to the [build()](https://google.github.io/google-api-python-client/docs/epy/googleapiclient.discovery-module.html#build) or [execute()](https://google.github.io/google-api-python-client/docs/epy/googleapiclient.http.HttpRequest-class.html#execute) functions as you normally would.

## Flows

Use App Engine's [Memcache](https://developers.google.com/appengine/docs/python/memcache/usingmemcache) to store `Flow` objects. When your application is simultaneously going through OAuth 2.0 steps for many users, it's normally best to store per-user `Flow` objects before the first redirection. This way, your redirection handlers can retrieve the `Flow` object already created for the user. In the following code snippet, `Memcache` is used to store and retrieve `Flow` objects keyed by user ID:

```py
import pickle
from google.appengine.api import memcache
from google.appengine.api import users
from oauth2client.client import OAuth2WebServerFlow
...
flow = OAuth2WebServerFlow(...)
user = users.get_current_user()
memcache.set(user.user_id(), pickle.dumps(flow))
...
flow = pickle.loads(memcache.get(user.user_id()))
```

## Credentials

Use the [oauth2client.contrib.appengine.CredentialsProperty](https://oauth2client.readthedocs.io/en/latest/source/oauth2client.contrib.appengine.html#oauth2client.contrib.appengine.CredentialsProperty) class as an [App Engine Datastore](https://developers.google.com/appengine/docs/python/datastore/overview) `Property`. Creating a `Model` with this `Property` simplifies storing `Credentials` as explained in the [Storage](#Storage) section below. In the following code snippet, a `Model` class is defined using this `Property`.

```py
from google.appengine.ext import db
from oauth2client.contrib.appengine import CredentialsProperty
...
class CredentialsModel(db.Model):
  credentials = CredentialsProperty()
```

## Storage

Use the [oauth2client.contrib.appengine.StorageByKeyName](https://oauth2client.readthedocs.io/en/latest/source/oauth2client.contrib.appengine.html#oauth2client.contrib.appengine.StorageByKeyName) class to store and retrieve `Credentials` objects to and from the [App Engine Datastore](https://developers.google.com/appengine/docs/python/datastore/overview). You pass the model, key value, and property name to its constructor. The following shows how to create, read, and write `Credentials` objects using the example `CredentialsModel` class above:

```py
from google.appengine.api import users
from oauth2client.contrib.appengine import StorageByKeyName
...
user = users.get_current_user()
storage = StorageByKeyName(CredentialsModel, user.user_id(), 'credentials')
credentials = storage.get()
...
storage.put(credentials)
```

## Samples

To see how these classes work together in a full application, see the [App Engine sample applications](https://github.com/google/google-api-python-client/tree/master/samples/appengine) section of this library’s open source project page.