return OpenIdMixin.get_authenticated_user(self)
+class GoogleOAuth2Mixin(OAuth2Mixin):
+ """Google authentication using OAuth2."""
+ _OAUTH_AUTHORIZE_URL = "https://accounts.google.com/o/oauth2/auth"
+ _OAUTH_ACCESS_TOKEN_URL = "https://accounts.google.com/o/oauth2/token"
+ _OAUTH_NO_CALLBACKS = False
+
+ def authorize_redirect(self, redirect_uri=None, client_id=None,
+ scope=['openid', 'email'], response_type="code", overwrites={}):
+ """Redirect the user to Google to authenticate them.
+
+ The API itself defaults some of these values that cna be overwritten by the overwrites object.
+ They are:
+ * approval_prompt = auto
+ * access_type = online
+ """
+ extra_params = {
+ "scope": ' '.join(scope),
+ "response_type": response_type,
+ }
+
+ extra_params.update(overwrites)
+
+ OAuth2Mixin.authorize_redirect(self,
+ self.request.protocol + '://' + self.request.host + (redirect_uri or self.request.uri),
+ self.settings['google_consumer_key'],
+ '', extra_params)
+
+ @_auth_return_future
+ def get_authenticated_user(self, redirect_uri, code, callback):
+ """Handles the login for the Facebook user, returning a user object.
+
+ Example usage::
+
+ class GoogleOAuth2LoginHandler(LoginHandler, tornado.auth.GoogleOAuth2Mixin):
+ @tornado.web.asynchronous
+ @tornado.gen.coroutine
+ def get(self):
+ if self.get_argument("code", False):
+ user = yield self.get_authenticated_user(
+ redirect_uri='/auth/google',
+ code=self.get_argument("code"))
+ # Save the user with e.g. set_secure_cookie
+ else:
+ yield self.authorize_redirect(
+ redirect_uri='/auth/google',
+ client_id=self.settings["google_consumer_key"],
+ scope=['openid', 'email'],
+ response_type='code',
+ extra_params={"approval_prompt": "auto"})
+ """
+ http = self.get_auth_http_client()
+ body = urllib.urlencode({
+ "redirect_uri": self.request.protocol + '://' + self.request.host + redirect_uri,
+ "code": code,
+ "client_id": self.settings['google_consumer_key'],
+ "client_secret": self.settings['google_consumer_secret'],
+ "grant_type": "authorization_code",
+ })
+
+ http.fetch(self._OAUTH_ACCESS_TOKEN_URL,
+ self.async_callback(self._on_access_token, callback),
+ method="POST", headers={'Content-Type': 'application/x-www-form-urlencoded'}, body=body)
+
+ def _on_access_token(self, future, response):
+ """Callback function for the exchange to the access token."""
+ if response.error:
+ future.set_exception(AuthError('Google auth error: %s' % str(response)))
+ return
+
+ args = json.loads(escape.native_str(response.body))
+
+ future.set_result(args)
+
+ def get_auth_http_client(self):
+ """Returns the `.AsyncHTTPClient` instance to be used for auth requests.
+
+ May be overridden by subclasses to use an HTTP client other than
+ the default.
+ """
+ return httpclient.AsyncHTTPClient()
+
+
class FacebookMixin(object):
"""Facebook Connect authentication.