This module contains implementations of various third-party authentication schemes.
All the classes in this file are class mixins designed to be used with
the tornado.web.RequestHandler
class. They are used in two ways:
- On a login handler, use methods such as
authenticate_redirect()
,authorize_redirect()
, andget_authenticated_user()
to establish the user’s identity and store authentication tokens to your database and/or cookies. - In non-login handlers, use methods such as
facebook_request()
ortwitter_request()
to use the authentication tokens to make requests to the respective services.
They all take slightly different arguments due to the fact all these services 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 guaranteed
to run their callback with an argument of None
on error.
Previously some functions would do this while others would simply
terminate the request on their own. This change also ensures that
errors are more consistently reported through the Future
interfaces.
Common protocols
These classes implement the OpenID and OAuth standards. They will generally need to be subclassed to use them with any particular site. The degree of customization required will vary, but in most cases overriding the class attributes (which are named beginning with underscores 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 given
callback URI with additional parameters including openid.mode
.
We request the given attributes for the authenticated user by default (name, email, language, and username). If you don’t need all those attributes for your app, you can request fewer with the ax_attrs keyword argument.
Changed in version 3.1: Returns a Future
and takes an optional callback. These are
not strictly necessary as this method is synchronous,
but they are supplied for consistency with
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 the
redirect from the authenticate_redirect()
method (which is
often the same as the one that calls it; in that case you would
call get_authenticated_user
if the openid.mode
parameter
is present and 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
instance to be used for auth requests.
May be overridden by subclasses to use an HTTP client other than the default.
class tornado.auth.OAuthMixin[source]
Abstract implementation of OAuth 1.0 and 1.0a.
See 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 requires advance registration of callbacks.
Subclasses must also override the _oauth_get_user_future
and
_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 previously
registered a callback URI with the third-party service. For
some services (including Friendfeed), you must use a
previously-registered callback URI and cannot specify a
callback via this method.
This method sets a cookie called _oauth_request_token
which is
subsequently used (and cleared) in get_authenticated_user
for
security purposes.
Note that this method is asynchronous, although it calls
RequestHandler.finish
for you so it may not be necessary
to pass a callback or use the Future
it returns. However,
if this method is called from a function decorated with
gen.coroutine
, you must call it with yield
to keep the
response from being closed prematurely.
Changed in version 3.1: Now returns a Future
and takes an optional callback, for
compatibility with 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 your
OAuth callback URL to complete the registration process. We run the
callback with the authenticated user dictionary. This dictionary
will contain an access_key
which can be used to make authorized
requests to this service on behalf of the user. The dictionary will
also contain other fields such as name
, depending on the service
used.
_oauth_consumer_token()[source]
Subclasses must override this to return their OAuth consumer keys.
The return value should be a dict
with keys key
and secret
.
_oauth_get_user_future(access_token, callback)[source]
Subclasses must override this to get basic information about the user.
Should return a Future
whose result is a dictionary
containing information about the user, which may have been
retrieved by using access_token
to make a request to the
service.
The access token will be added to the returned dictionary to make
the result of get_authenticated_user
.
For backwards compatibility, the callback-based _oauth_get_user
method is also supported.
get_auth_http_client()[source]
Returns the AsyncHTTPClient
instance to be used for auth requests.
May be overridden by subclasses to use an HTTP client other than the default.
class tornado.auth.OAuth2Mixin[source]
Abstract implementation of OAuth 2.0.
See FacebookGraphMixin
or GoogleOAuth2Mixin
below for example
implementations.
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 with
your application instead of passing one via this method. You
should call this method to log the user in, and then call
get_authenticated_user
in the handler for your
redirect URL to complete the authorization process.
Changed in version 3.1: Returns a Future
and takes an optional callback. These are
not strictly necessary as this method is synchronous,
but they are supplied for consistency with
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. Query
string 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
instance to be used for auth requests.
May be overridden by subclasses to use an HTTP client other than the default.
New in version 4.3.
class tornado.auth.GoogleOAuth2Mixin[source]
Google authentication using OAuth2.
In order to use, register your application with Google and copy the relevant parameters to your application settings.
- Go to the Google Dev Console at 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)).
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
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'})
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"})
This method returns a dictionary which may contain the following fields:
access_token
, a string which may be passed tofacebook_request
session_expires
, an integer encoded as a string representing the time until the access token expires in seconds. This field should be used likeint(user['session_expires'])
; in a future version of Tornado it will change from a string to an integer.id
,name
,first_name
,last_name
,locale
,picture
,link
, plus any fields named in theextra_fields
argument. These fields are copied from the Facebook graph API user object
Changed in version 4.5: The session_expires
field was updated to support changes made to the
Facebook API in March 2017.
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. Query
string arguments should be given as keyword arguments.
An introduction to the Facebook Graph API can be found at http://developers.facebook.com/docs/api
Many methods require an OAuth access token which you can
obtain through authorize_redirect
and
get_authenticated_user
. The user returned through that
process includes an access_token
attribute that can be
used 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”.
This method is a wrapper around 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
.
class tornado.auth.TwitterMixin[source]
Twitter OAuth authentication.
To authenticate with Twitter, register your application with
Twitter at http://twitter.com/apps. Then copy your Consumer Key
and Consumer Secret to the application
settings
twitter_consumer_key
and
twitter_consumer_secret
. Use this mixin on the handler for the
URL you registered as your application’s callback URL.
When your application is set up, you can use this mixin like this to 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
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
authenticate_redirect(callback_uri=None, callback=None)[source]
Just like authorize_redirect
, but
auto-redirects if authorized.
This is generally the right interface to use if you are using Twitter for single-sign on.
Changed in version 3.1: Now returns a Future
and takes an optional callback, for
compatibility with 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. Query
string arguments should be given as keyword arguments.
All the Twitter methods are documented at http://dev.twitter.com/
Many methods require an OAuth access token which you can
obtain through authorize_redirect
and
get_authenticated_user
. The user returned through that
process includes an ‘access_token’ attribute that can be used
to make authenticated requests via this method. Example
usage:
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!")