Last active
September 27, 2016 18:26
-
-
Save luwes/6d54a479651fde2b68bf3e890d089689 to your computer and use it in GitHub Desktop.
Tornado Vimeo Mixin OAuth2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class BaseHandler(RequestHandler): | |
COOKIE_NAME = 'user' | |
def get_current_user(self): | |
user_json = self.get_secure_cookie(self.COOKIE_NAME) | |
if not user_json: | |
return None | |
return json_decode(user_json) | |
class LoginHandler(BaseHandler, VimeoMixin): | |
async def get(self): | |
my_url = (self.request.protocol + "://" + self.request.host + "/login") | |
api_state = self.get_secure_cookie('api_state') | |
is_valid = api_state and api_state.decode('ascii') == self.get_argument('state', None) | |
if self.get_argument('code', None) and is_valid: | |
self.clear_cookie('api_state') | |
user = await self.get_authenticated_user( | |
redirect_uri=my_url, | |
client_id=options.vimeo_client_identifier, | |
client_secret=options.vimeo_client_secrets, | |
code=self.get_argument("code"), | |
) | |
self.set_secure_cookie(self.COOKIE_NAME, json_encode(user)) | |
self.redirect(self.get_argument('next', '/')) | |
else: | |
state = base64.b64encode(os.urandom(10)).decode('ascii') | |
self.set_secure_cookie('api_state', state) | |
self.authorize_redirect( | |
redirect_uri=my_url, | |
client_id=options.vimeo_client_identifier, | |
scope=['public', 'private'], | |
extra_params={ | |
'state': state, | |
} | |
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import urllib | |
import functools | |
import base64 | |
import urllib.parse as urllib_parse | |
import tornado.ioloop | |
import tornado.web | |
import tornado.auth | |
import tornado.httpclient | |
import tornado.escape | |
import tornado.httputil | |
import logging | |
class VimeoMixin(tornado.auth.OAuth2Mixin): | |
""" Vimeo OAuth Mixin, based on FacebookGraphMixin | |
""" | |
_OAUTH_AUTHORIZE_URL = 'https://api.vimeo.com/oauth/authorize' | |
_OAUTH_ACCESS_TOKEN_URL = 'https://api.vimeo.com/oauth/access_token' | |
_OAUTH_NO_CALLBACKS = False | |
_API_URL = 'https://api.vimeo.com' | |
@tornado.auth._auth_return_future | |
def get_authenticated_user(self, redirect_uri, client_id, client_secret, | |
code, callback, extra_fields=None): | |
""" Handles the login for Vimeo, queries /user and returns a user object | |
""" | |
http = tornado.httpclient.AsyncHTTPClient() | |
body = urllib_parse.urlencode({ | |
"redirect_uri": redirect_uri, | |
"code": code, | |
"client_id": client_id, | |
"client_secret": client_secret, | |
"grant_type": "authorization_code", | |
}) | |
fields = set([ 'name', 'link', 'pictures']) | |
if extra_fields: | |
fields.update(extra_fields) | |
fn = functools.partial(self._on_access_token, redirect_uri, client_id, | |
client_secret, callback, fields) | |
http.fetch(self._OAUTH_ACCESS_TOKEN_URL, fn, method="POST", body=body) | |
def _on_access_token(self, redirect_uri, client_id, client_secret, | |
future, fields, response): | |
"""Callback function for the exchange to the access token.""" | |
if response.error: | |
future.set_exception(tornado.auth.AuthError('Vimeo auth error: %s' % str(response))) | |
return | |
body = tornado.escape.json_decode(response.body) | |
#future.set_result(args) | |
self._on_get_user_info(future, body, fields, body['user']) | |
def _on_get_user_info(self, future, session, fields, user): | |
if user is None: | |
future.set_result(None) | |
return | |
fieldmap = {} | |
for field in fields: | |
fieldmap[field] = user.get(field) | |
fieldmap.update({"access_token": session["access_token"]}) | |
future.set_result(fieldmap) | |
@tornado.auth._auth_return_future | |
def vimeo_request(self, path, callback, access_token=None, | |
post_args=None, **args): | |
url = self._API_URL + path | |
oauth_future = self.oauth2_request(url, access_token=access_token, | |
post_args=post_args, **args) | |
tornado.concurrent.chain_future(oauth_future, callback) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment