microblog/app/oauth.py
This commit is contained in:
parent
dd4a0375c2
commit
053769cf71
|
@ -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')
|
||||||
|
)
|
Loading…
Reference in New Issue