There are a few helpers built-in to Ferris for utilizing OAuth2 with the Google APIs. There are easy ways to initiate the web server flow, get user credentials, and utilize service accounts.

This documentation assumes you have an understand of OAuth2. If you’d like to read more on the subject of OAuth2 and how Google uses it please read Google’s documentation.


In order to use Ferris’ OAuth2 features, you must first configure client settings in settings.py or use the Settings plugin:

app_config['oauth2'] = {
    'client_id': 'XXXXXXXXXXXXXXX.apps.googleusercontent.com',
    'client_secret': 'XXXXXXXXXXXXXXX'

You can generate your own Client ID and Secret at the Google API Console.


A quick example of how to use the OAuth2 features to interact with a Google API:

from ferris import Controller
from ferris.components import oauth
from apiclient.discovery import build

class Example(Controller):
    class Meta:
        components = (oauth.OAuth,)
        oauth_scopes = ['https://www.googleapis.com/auth/userinfo.profile']

    # Require credentials for the current user with the scopes listed above.
    def list(self):

        # Signed HTTP instance.
        http = self.oauth.http()

        # Access to Google's OAuth info API
        service = build('oauth2', 'v2', http=http)

        user_info = service.userinfo().get().execute()

        return "Hello, you are: %s" % user_info['name']

This example uses the Google user info service to create a friendly message. When you first navigate to /example, you’ll be taken through the entire OAuth Flow. You will only have to complete this once, as it stores the credentials for subsequence requests.

The OAuth Component

class ferris.components.oauth.OAuth(controller)[source]

The OAuth component handles providing credentials to your handler’s actions and automatically initiating the flow to acquire credentials if needed.

As in the example above, to use the component add it to the component list and be sure to specify the needed scopes using Meta.oauth_scopes:

class Example(Controller):
    class Meta:
        components = (oauth.OAuth,)
        oauth_scopes = ['https://www.googleapis.com/auth/userinfo.profile']

You must decorate every action that needs credentials with either @require_credentials, @provide_credentials, or @require_admin_credentials:

def list(self):
    http = self.oauth.http()

def test(self):
    if not self.oauth.has_credentials():
        return "No credentials"

Requires that valid credentials exist for the current user before executing the controller. Will redirect the user for authorization. User controller.oauth_scopes to specify which scopes are required.


Similar to require_credentials() but instead of automatically redirecting the user when credentials are required it allows you to take your own action.

You can use OAuth.has_credentials() to interrogate.

Admin Credentials

Sometimes you need to use one account for every user sort of like a service account. You can achieve this using admin credentials. These sort of credentials can only be created by an administrator of an application but will be available for all requests to use.


Requires that valid credentials exist for the administrator before executing the controller. Will redirect the user for authorization if the user is an admin.

To create admin credentials use the OAuthManager plugin (enabled by default) located at /admin/oauth_manager <http://localhost:8080/admin/oauth_manager>.

Using Credentials

Usually you’ll want an http object that’s signed with the credentials:


Returns a signed httplib2.Http instance that can be readily used for making authorized requests.

You can use this to build a service object:

http = self.oauth.http()
service = build('oauth2', 'v2', http=http)

Sometimes you want access to the credentials object directly:


Returns an Oauth2Credentials object that can be used to sign a request

To check if the credentials exist and are valid, you can use:


Returns true if credentials exist for the current user.

If you want to request that the user grant you access (if you’re using provide instead of require) redirect them to the result of:

OAuth.authorization_url(redirect=None, admin=False, force_prompt=False)[source]

Generates an authorization url to start the OAuth flow for the current user.

Finding Credentials

Sometimes you need to use credentials outside of a controller context (such as in a task). You can find credentials using find_credentials.

ferris.core.oauth2.find_credentials(user=None, scopes=None, admin=None)

Finds credentials that fit the criteria provided. If no user is provided, the first set of credentials that have the given scopes and privilege level.

Returns None if no credentials are found.


import httplib2
from ferris.core.oauth2 import find_credentials

creds = find_credentials(scopes=["https://www.googleapis.com/drive/file"], admin=True)
http = httplib2.Http()

The Oauth Manager

The OAuth Manager plugin allows you to view, add, and delete credentials from the admin interface. Enable it in app/routes.py:


Once enabled you can access it via /admin/oauth_manager.

OAuth2 Service Accounts

The included OAuth2 Service Account plugin can help you when using Google’s Service Account Flow.

To use, first enable the plugin in app/routes.py:


Setup configuration in settings.py or use the Settings plugin:

defaults['oauth2_service_account'] = {
    'domain': None,  # Google Apps Domain
    'defaul_user': None,  # The default user to impersonate (email address)
    'client_email': None,  # ..@developer.gserviceaccount.com
    'private_key' None,  # The private key in PEM format

By default Google gives you the private key in pkcs12 format. To convert use this command on linux:

openssl pkcs12 -in key.p12 -out key.pem -nodes -nocerts

Now you’re ready to go.

plugins.service_account.build_credentials(scope, user=None)[source]

Builds service account credentials using the configuration stored in settings and masquerading as the provided user.


credentials = service_account.build_credentials(



Service account credentials will not work properly on local development environments that are missing the PyCrypto or PyOpenSSL modules.