From 053769cf71268afc24353ddac487a4ea693c46c4 Mon Sep 17 00:00:00 2001 From: edicristofaro Date: Tue, 11 Apr 2017 15:53:41 -0400 Subject: [PATCH] microblog/app/oauth.py --- app/oauth.py.txt | 137 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 app/oauth.py.txt diff --git a/app/oauth.py.txt b/app/oauth.py.txt new file mode 100644 index 0000000..318a7f0 --- /dev/null +++ b/app/oauth.py.txt @@ -0,0 +1,137 @@ +from rauth import OAuth1Service, OAuth2Service +from flask import flash, current_app, url_for, request, redirect, session, jsonify +import json, urllib2 + +class OAuthSignIn(object): + providers = None + + def __init__(self, provider_name): + self.provider_name = provider_name + credentials = current_app.config['OAUTH_CREDENTIALS'][provider_name] + self.consumer_id = credentials['id'] + self.consumer_secret = credentials['secret'] + + def authorize(self): + pass + + def callback(self): + pass + + def get_callback_url(self): + return url_for('oauth_callback', provider=self.provider_name, + _external=True) + + @classmethod + def get_provider(self, provider_name): + if self.providers is None: + self.providers = {} + for provider_class in self.__subclasses__(): + provider = provider_class() + self.providers[provider.provider_name] = provider + return self.providers[provider_name] + +class FacebookSignIn(OAuthSignIn): + def __init__(self): + super(FacebookSignIn, self).__init__('facebook') + self.service = OAuth2Service( + name='facebook', + client_id=self.consumer_id, + client_secret=self.consumer_secret, + authorize_url='https://graph.facebook.com/oauth/authorize', + access_token_url='https://graph.facebook.com/oauth/access_token', + base_url='https://graph.facebook.com/' + ) + def authorize(self): + return redirect(self.service.get_authorize_url( + scope='email', + response_type='code', + redirect_uri=self.get_callback_url()) + ) + def callback(self): + if 'code' not in request.args: + return None, None, None + oauth_session = self.service.get_auth_session( + data={'code': request.args['code'], + 'grant_type': 'authorization_code', + 'redirect_uri': self.get_callback_url()} + ) + me = oauth_session.get('me').json() + return ( + 'facebook$' + me['id'], + me.get('email').split('@')[0], # Facebook does not provide + # username, so the email's user + # is used instead + me.get('email') + ) + +class TwitterSignIn(OAuthSignIn): + def __init__(self): + super(TwitterSignIn, self).__init__('twitter') + self.service = OAuth1Service( + name='twitter', + consumer_key=self.consumer_id, + consumer_secret=self.consumer_secret, + request_token_url='https://api.twitter.com/oauth/request_token', + authorize_url='https://api.twitter.com/oauth/authorize', + access_token_url='https://api.twitter.com/oauth/access_token', + base_url='https://api.twitter.com/1.1/' + ) + def authorize(self): + request_token = self.service.get_request_token( + params={'oauth_callback': self.get_callback_url()} + ) + session['request_token'] = request_token + return redirect(self.service.get_authorize_url(request_token[0])) + def callback(self): + request_token = session.pop('request_token') + if 'oauth_verifier' not in request.args: + return None, None, None + oauth_session = self.service.get_auth_session( + request_token[0], + request_token[1], + data={'oauth_verifier': request.args['oauth_verifier']} + ) + me = oauth_session.get('account/verify_credentials.json').json() + social_id = 'twitter$' + str(me.get('id')) + username = me.get('screen_name') + return social_id, username, None # Twitter does not provide email + +class GoogleSignIn(OAuthSignIn): + def __init__(self): + super(GoogleSignIn, self).__init__('google') + googleinfo = urllib2.urlopen('https://accounts.google.com/.well-known/openid-configuration') + google_params = json.load(googleinfo) + self.service = OAuth2Service( + name='google', + client_id=self.consumer_id, + client_secret=self.consumer_secret, + authorize_url=google_params.get('authorization_endpoint'), + base_url=google_params.get('userinfo_endpoint'), + access_token_url=google_params.get('token_endpoint') + ) + + def authorize(self): + return redirect(self.service.get_authorize_url( + scope='email', + response_type='code', + redirect_uri=self.get_callback_url()) + ) + + def callback(self): + if 'code' not in request.args: + return None, None, None + oauth_session = self.service.get_auth_session( + data={'code': request.args['code'], + 'grant_type': 'authorization_code', + 'redirect_uri': self.get_callback_url() + }, + decoder = json.loads + ) + me = oauth_session.get('').json() + return ( + 'google$' + me['sub'], # Google provides a unique per-user value in the "sub" + # claim of its ID Token + # https://developers.google.com/identity/protocols/OpenIDConnect + me.get('email').split('@')[0], + me.get('email') + )