### Navigation
- [index](# "General Index")
- [modules](# "Python Module Index") |
- [next](# "tornado.wsgi — Interoperability with other Python frameworks and servers") |
- [previous](# "Integration with other services") |
- [Tornado 4.4.dev1 documentation](#) »
- [Integration with other services](#) »
# `tornado.auth` — Third-party login with OpenID and OAuth
This module contains implementations of various third-partyauthentication schemes.
All the classes in this file are class mixins designed to be used withthe [`tornado.web.RequestHandler`](# "tornado.web.RequestHandler") class. They are used in two ways:
- On a login handler, use methods such as `authenticate_redirect()`,`authorize_redirect()`, and `get_authenticated_user()` toestablish the user's identity and store authentication tokens to yourdatabase and/or cookies.
- In non-login handlers, use methods such as `facebook_request()`or `twitter_request()` to use the authentication tokens to makerequests to the respective services.
They all take slightly different arguments due to the fact all theseservices implement authentication and authorization slightly differently.See the individual service classes below for complete documentation.
Example usage for Google OAuth:
~~~
class GoogleOAuth2LoginHandler(tornado.web.RequestHandler,
tornado.auth.GoogleOAuth2Mixin):
@tornado.gen.coroutine
def get(self):
if self.get_argument('code', False):
user = yield self.get_authenticated_user(
redirect_uri='http://your.site.com/auth/google',
code=self.get_argument('code'))
# Save the user with e.g. set_secure_cookie
else:
yield self.authorize_redirect(
redirect_uri='http://your.site.com/auth/google',
client_id=self.settings['google_oauth']['key'],
scope=['profile', 'email'],
response_type='code',
extra_params={'approval_prompt': 'auto'})
~~~
Changed in version 4.0: All of the callback interfaces in this module are now guaranteedto run their callback with an argument of `None` on error.Previously some functions would do this while others would simplyterminate the request on their own. This change also ensures thaterrors are more consistently reported through the `Future` interfaces.
### Common protocols
These classes implement the OpenID and OAuth standards. They willgenerally need to be subclassed to use them with any particular site.The degree of customization required will vary, but in most casesoverridding the class attributes (which are named beginning withunderscores for historical reasons) should be sufficient.
*class *`tornado.auth.``OpenIdMixin`[[source]](#)
Abstract implementation of OpenID and Attribute Exchange.
Class attributes:
- `_OPENID_ENDPOINT`: the identity provider's URI.
`authenticate_redirect`(*callback_uri=None, ax_attrs=['name', 'email', 'language', 'username'], callback=None*)[[source]](#)
Redirects to the authentication URL for this service.
After authentication, the service will redirect back to the givencallback URI with additional parameters including `openid.mode`.
We request the given attributes for the authenticated user bydefault (name, email, language, and username). If you don't needall those attributes for your app, you can request fewer withthe ax_attrs keyword argument.
Changed in version 3.1: Returns a [`Future`](# "tornado.concurrent.Future") and takes an optional callback. These arenot strictly necessary as this method is synchronous,but they are supplied for consistency with[`OAuthMixin.authorize_redirect`](# "tornado.auth.OAuthMixin.authorize_redirect").
`get_authenticated_user`(*callback*, *http_client=None*)[[source]](#)
Fetches the authenticated user data upon redirect.
This method should be called by the handler that receives theredirect from the [`authenticate_redirect()`](# "tornado.auth.OpenIdMixin.authenticate_redirect") method (which isoften the same as the one that calls it; in that case you wouldcall [`get_authenticated_user`](# "tornado.auth.OpenIdMixin.get_authenticated_user") if the `openid.mode` parameteris present and [`authenticate_redirect`](# "tornado.auth.OpenIdMixin.authenticate_redirect") if it is not).
The result of this method will generally be used to set a cookie.
`get_auth_http_client`()[[source]](#)
Returns the [`AsyncHTTPClient`](# "tornado.httpclient.AsyncHTTPClient") instance to be used for auth requests.
May be overridden by subclasses to use an HTTP client other thanthe default.
*class *`tornado.auth.``OAuthMixin`[[source]](#)
Abstract implementation of OAuth 1.0 and 1.0a.
See [`TwitterMixin`](# "tornado.auth.TwitterMixin") below for an example implementation.
Class attributes:
- `_OAUTH_AUTHORIZE_URL`: The service's OAuth authorization url.
- `_OAUTH_ACCESS_TOKEN_URL`: The service's OAuth access token url.
- `_OAUTH_VERSION`: May be either “1.0” or “1.0a”.
- `_OAUTH_NO_CALLBACKS`: Set this to True if the service requiresadvance registration of callbacks.
Subclasses must also override the [`_oauth_get_user_future`](# "tornado.auth.OAuthMixin._oauth_get_user_future") and[`_oauth_consumer_token`](# "tornado.auth.OAuthMixin._oauth_consumer_token") methods.
`authorize_redirect`(*callback_uri=None*, *extra_params=None*, *http_client=None*, *callback=None*)[[source]](#)
Redirects the user to obtain OAuth authorization for this service.
The `callback_uri` may be omitted if you have previouslyregistered a callback URI with the third-party service. Forsome services (including Friendfeed), you must use apreviously-registered callback URI and cannot specify acallback via this method.
This method sets a cookie called `_oauth_request_token` which issubsequently used (and cleared) in [`get_authenticated_user`](# "tornado.auth.OAuthMixin.get_authenticated_user") forsecurity purposes.
Note that this method is asynchronous, although it calls[`RequestHandler.finish`](# "tornado.web.RequestHandler.finish") for you so it may not be necessaryto pass a callback or use the [`Future`](# "tornado.concurrent.Future") it returns. However,if this method is called from a function decorated with[`gen.coroutine`](# "tornado.gen.coroutine"), you must call it with `yield` to keep theresponse from being closed prematurely.
Changed in version 3.1: Now returns a [`Future`](# "tornado.concurrent.Future") and takes an optional callback, forcompatibility with [`gen.coroutine`](# "tornado.gen.coroutine").
`get_authenticated_user`(*callback*, *http_client=None*)[[source]](#)
Gets the OAuth authorized user and access token.
This method should be called from the handler for yourOAuth callback URL to complete the registration process. We run thecallback with the authenticated user dictionary. This dictionarywill contain an `access_key` which can be used to make authorizedrequests to this service on behalf of the user. The dictionary willalso contain other fields such as `name`, depending on the serviceused.
`_oauth_consumer_token`()[[source]](#)
Subclasses must override this to return their OAuth consumer keys.
The return value should be a [`dict`](https://docs.python.org/3.4/library/stdtypes.html#dict "(in Python v3.4)") [https://docs.python.org/3.4/library/stdtypes.html#dict] with keys `key` and `secret`.
`_oauth_get_user_future`(*access_token*, *callback*)[[source]](#)
Subclasses must override this to get basic information about theuser.
Should return a [`Future`](# "tornado.concurrent.Future") whose result is a dictionarycontaining information about the user, which may have beenretrieved by using `access_token` to make a request to theservice.
The access token will be added to the returned dictionary to makethe result of [`get_authenticated_user`](# "tornado.auth.OAuthMixin.get_authenticated_user").
For backwards compatibility, the callback-based `_oauth_get_user`method is also supported.
`get_auth_http_client`()[[source]](#)
Returns the [`AsyncHTTPClient`](# "tornado.httpclient.AsyncHTTPClient") instance to be used for auth requests.
May be overridden by subclasses to use an HTTP client other thanthe default.
*class *`tornado.auth.``OAuth2Mixin`[[source]](#)
Abstract implementation of OAuth 2.0.
See [`FacebookGraphMixin`](# "tornado.auth.FacebookGraphMixin") or [`GoogleOAuth2Mixin`](# "tornado.auth.GoogleOAuth2Mixin") below for exampleimplementations.
Class attributes:
- `_OAUTH_AUTHORIZE_URL`: The service's authorization url.
- `_OAUTH_ACCESS_TOKEN_URL`: The service's access token url.
`authorize_redirect`(*redirect_uri=None*, *client_id=None*, *client_secret=None*, *extra_params=None*, *callback=None*, *scope=None*, *response_type='code'*)[[source]](#)
Redirects the user to obtain OAuth authorization for this service.
Some providers require that you register a redirect URL withyour application instead of passing one via this method. Youshould call this method to log the user in, and then call`get_authenticated_user` in the handler for yourredirect URL to complete the authorization process.
Changed in version 3.1: Returns a [`Future`](# "tornado.concurrent.Future") and takes an optional callback. These arenot strictly necessary as this method is synchronous,but they are supplied for consistency with[`OAuthMixin.authorize_redirect`](# "tornado.auth.OAuthMixin.authorize_redirect").
`oauth2_request`(*url*, *callback*, *access_token=None*, *post_args=None*, ***args*)[[source]](#)
Fetches the given URL auth an OAuth2 access token.
If the request is a POST, `post_args` should be provided. Querystring arguments should be given as keyword arguments.
Example usage:
..testcode:
~~~
class MainHandler(tornado.web.RequestHandler,
tornado.auth.FacebookGraphMixin):
@tornado.web.authenticated
@tornado.gen.coroutine
def get(self):
new_entry = yield self.oauth2_request(
"https://graph.facebook.com/me/feed",
post_args={"message": "I am posting from my Tornado application!"},
access_token=self.current_user["access_token"])
if not new_entry:
# Call failed; perhaps missing permission?
yield self.authorize_redirect()
return
self.finish("Posted a message!")
~~~
New in version 4.3.
`get_auth_http_client`()[[source]](#)
Returns the [`AsyncHTTPClient`](# "tornado.httpclient.AsyncHTTPClient") instance to be used for auth requests.
May be overridden by subclasses to use an HTTP client other thanthe default.
New in version 4.3.
### Google
*class *`tornado.auth.``GoogleOAuth2Mixin`[[source]](#)
Google authentication using OAuth2.
In order to use, register your application with Google and copy therelevant parameters to your application settings.
- Go to the Google Dev Console at [http://console.developers.google.com](http://console.developers.google.com)
- Select a project, or create a new one.
- In the sidebar on the left, select APIs & Auth.
- In the list of APIs, find the Google+ API service and set it to ON.
- In the sidebar on the left, select Credentials.
- In the OAuth section of the page, select Create New Client ID.
- Set the Redirect URI to point to your auth handler
- Copy the “Client secret” and “Client ID” to the application settings as{“google_oauth”: {“key”: CLIENT_ID, “secret”: CLIENT_SECRET}}
New in version 3.2.
`get_authenticated_user`(*redirect_uri*, *code*, *callback*)[[source]](#)
Handles the login for the Google user, returning an access token.
The result is a dictionary containing an `access_token` field([among others]([https://developers.google.com/identity/protocols/OAuth2WebServer#handlingtheresponse](https://developers.google.com/identity/protocols/OAuth2WebServer#handlingtheresponse))).Unlike other `get_authenticated_user` methods in this package,this method does not return any additional information about the user.The returned access token can be used with [`OAuth2Mixin.oauth2_request`](# "tornado.auth.OAuth2Mixin.oauth2_request")to request additional information (perhaps from`https://www.googleapis.com/oauth2/v2/userinfo`)
Example usage:
~~~
class GoogleOAuth2LoginHandler(tornado.web.RequestHandler,
tornado.auth.GoogleOAuth2Mixin):
@tornado.gen.coroutine
def get(self):
if self.get_argument('code', False):
access = yield self.get_authenticated_user(
redirect_uri='http://your.site.com/auth/google',
code=self.get_argument('code'))
user = yield self.oauth2_request(
"https://www.googleapis.com/oauth2/v1/userinfo",
access_token=access["access_token"])
# Save the user and access token with
# e.g. set_secure_cookie.
else:
yield self.authorize_redirect(
redirect_uri='http://your.site.com/auth/google',
client_id=self.settings['google_oauth']['key'],
scope=['profile', 'email'],
response_type='code',
extra_params={'approval_prompt': 'auto'})
~~~
### Facebook
*class *`tornado.auth.``FacebookGraphMixin`[[source]](#)
Facebook authentication using the new Graph API and OAuth2.
`get_authenticated_user`(*redirect_uri*, *client_id*, *client_secret*, *code*, *callback*, *extra_fields=None*)[[source]](#)
Handles the login for the Facebook user, returning a user object.
Example usage:
~~~
class FacebookGraphLoginHandler(tornado.web.RequestHandler,
tornado.auth.FacebookGraphMixin):
@tornado.gen.coroutine
def get(self):
if self.get_argument("code", False):
user = yield self.get_authenticated_user(
redirect_uri='/auth/facebookgraph/',
client_id=self.settings["facebook_api_key"],
client_secret=self.settings["facebook_secret"],
code=self.get_argument("code"))
# Save the user with e.g. set_secure_cookie
else:
yield self.authorize_redirect(
redirect_uri='/auth/facebookgraph/',
client_id=self.settings["facebook_api_key"],
extra_params={"scope": "read_stream,offline_access"})
~~~
`facebook_request`(*path*, *callback*, *access_token=None*, *post_args=None*, ***args*)[[source]](#)
Fetches the given relative API path, e.g., “/btaylor/picture”
If the request is a POST, `post_args` should be provided. Querystring arguments should be given as keyword arguments.
An introduction to the Facebook Graph API can be found at[http://developers.facebook.com/docs/api](http://developers.facebook.com/docs/api)
Many methods require an OAuth access token which you canobtain through [`authorize_redirect`](# "tornado.auth.OAuth2Mixin.authorize_redirect") and[`get_authenticated_user`](# "tornado.auth.FacebookGraphMixin.get_authenticated_user"). The user returned through thatprocess includes an `access_token` attribute that can beused to make authenticated requests via this method.
Example usage:
..testcode:
~~~
class MainHandler(tornado.web.RequestHandler,
tornado.auth.FacebookGraphMixin):
@tornado.web.authenticated
@tornado.gen.coroutine
def get(self):
new_entry = yield self.facebook_request(
"/me/feed",
post_args={"message": "I am posting from my Tornado application!"},
access_token=self.current_user["access_token"])
if not new_entry:
# Call failed; perhaps missing permission?
yield self.authorize_redirect()
return
self.finish("Posted a message!")
~~~
The given path is relative to `self._FACEBOOK_BASE_URL`,by default “[https://graph.facebook.com](https://graph.facebook.com)”.
This method is a wrapper around [`OAuth2Mixin.oauth2_request`](# "tornado.auth.OAuth2Mixin.oauth2_request");the only difference is that this method takes a relative path,while `oauth2_request` takes a complete url.
Changed in version 3.1: Added the ability to override `self._FACEBOOK_BASE_URL`.
### Twitter
*class *`tornado.auth.``TwitterMixin`[[source]](#)
Twitter OAuth authentication.
To authenticate with Twitter, register your application withTwitter at [http://twitter.com/apps](http://twitter.com/apps). Then copy your Consumer Keyand Consumer Secret to the application[`settings`](# "tornado.web.Application.settings")`twitter_consumer_key` and`twitter_consumer_secret`. Use this mixin on the handler for theURL you registered as your application's callback URL.
When your application is set up, you can use this mixin like thisto authenticate the user with Twitter and get access to their stream:
~~~
class TwitterLoginHandler(tornado.web.RequestHandler,
tornado.auth.TwitterMixin):
@tornado.gen.coroutine
def get(self):
if self.get_argument("oauth_token", None):
user = yield self.get_authenticated_user()
# Save the user using e.g. set_secure_cookie()
else:
yield self.authorize_redirect()
~~~
The user object returned by [`get_authenticated_user`](# "tornado.auth.OAuthMixin.get_authenticated_user")includes the attributes `username`, `name`, `access_token`,and all of the custom Twitter user attributes described at[https://dev.twitter.com/docs/api/1.1/get/users/show](https://dev.twitter.com/docs/api/1.1/get/users/show)
`authenticate_redirect`(*callback_uri=None*, *callback=None*)[[source]](#)
Just like [`authorize_redirect`](# "tornado.auth.OAuthMixin.authorize_redirect"), butauto-redirects if authorized.
This is generally the right interface to use if you are usingTwitter for single-sign on.
Changed in version 3.1: Now returns a [`Future`](# "tornado.concurrent.Future") and takes an optional callback, forcompatibility with [`gen.coroutine`](# "tornado.gen.coroutine").
`twitter_request`(*path*, *callback=None*, *access_token=None*, *post_args=None*, ***args*)[[source]](#)
Fetches the given API path, e.g., `statuses/user_timeline/btaylor`
The path should not include the format or API version number.(we automatically use JSON format and API version 1).
If the request is a POST, `post_args` should be provided. Querystring arguments should be given as keyword arguments.
All the Twitter methods are documented at [http://dev.twitter.com/](http://dev.twitter.com/)
Many methods require an OAuth access token which you canobtain through [`authorize_redirect`](# "tornado.auth.OAuthMixin.authorize_redirect") and[`get_authenticated_user`](# "tornado.auth.OAuthMixin.get_authenticated_user"). The user returned through thatprocess includes an ‘access_token' attribute that can be usedto make authenticated requests via this method. Exampleusage:
~~~
class MainHandler(tornado.web.RequestHandler,
tornado.auth.TwitterMixin):
@tornado.web.authenticated
@tornado.gen.coroutine
def get(self):
new_entry = yield self.twitter_request(
"/statuses/update",
post_args={"status": "Testing Tornado Web Server"},
access_token=self.current_user["access_token"])
if not new_entry:
# Call failed; perhaps missing permission?
yield self.authorize_redirect()
return
self.finish("Posted a message!")
~~~
© Copyright 2009-2016, The Tornado Authors. Created using [Sphinx](http://sphinx-doc.org/) 1.3.5.
- User's guide
- Introduction
- Asynchronous and non-Blocking I/O
- Coroutines
- Queue example - a concurrent web spider
- Structure of a Tornado web application
- Templates and UI
- Authentication and security
- Running and deploying
- Web framework
- tornado.web — RequestHandler and Application classes
- tornado.template — Flexible output generation
- tornado.escape — Escaping and string manipulation
- tornado.locale — Internationalization support
- tornado.websocket — Bidirectional communication to the browser
- HTTP servers and clients
- tornado.httpserver — Non-blocking HTTP server
- tornado.httpclient — Asynchronous HTTP client
- tornado.httputil — Manipulate HTTP headers and URLs
- tornado.http1connection – HTTP/1.x client/server implementation
- Asynchronous networking
- tornado.ioloop — Main event loop
- tornado.iostream — Convenient wrappers for non-blocking sockets
- tornado.netutil — Miscellaneous network utilities
- tornado.tcpclient — IOStream connection factory
- tornado.tcpserver — Basic IOStream-based TCP server
- Coroutines and concurrency
- tornado.gen — Simplify asynchronous code
- tornado.concurrent — Work with threads and futures
- tornado.locks – Synchronization primitives
- tornado.queues – Queues for coroutines
- tornado.process — Utilities for multiple processes
- Integration with other services
- tornado.auth — Third-party login with OpenID and OAuth
- tornado.wsgi — Interoperability with other Python frameworks and servers
- tornado.platform.asyncio — Bridge between asyncio and Tornado
- tornado.platform.caresresolver — Asynchronous DNS Resolver using C-Ares
- tornado.platform.twisted — Bridges between Twisted and Tornado
- Utilities
- tornado.autoreload — Automatically detect code changes in development
- tornado.log — Logging support
- tornado.options — Command-line parsing
- tornado.stack_context — Exception handling across asynchronous callbacks
- tornado.testing — Unit testing support for asynchronous code
- tornado.util — General-purpose utilities
- Frequently Asked Questions
- Release notes
- What's new in Tornado 4.3
- What's new in Tornado 4.2.1
- What's new in Tornado 4.2
- What's new in Tornado 4.1
- What's new in Tornado 4.0.2
- What's new in Tornado 4.0.1
- What's new in Tornado 4.0
- What's new in Tornado 3.2.2
- What's new in Tornado 3.2.1
- What's new in Tornado 3.2
- What's new in Tornado 3.1.1
- What's new in Tornado 3.1
- What's new in Tornado 3.0.2
- What's new in Tornado 3.0.1
- What's new in Tornado 3.0
- What's new in Tornado 2.4.1
- What's new in Tornado 2.4
- What's new in Tornado 2.3
- What's new in Tornado 2.2.1
- What's new in Tornado 2.2
- What's new in Tornado 2.1.1
- What's new in Tornado 2.1
- What's new in Tornado 2.0
- What's new in Tornado 1.2.1
- What's new in Tornado 1.2
- What's new in Tornado 1.1.1
- What's new in Tornado 1.1
- What's new in Tornado 1.0.1
- What's new in Tornado 1.0
