Remove Flask-OAuthlib and oauth_blender_id from Pillar

We switch completely to a rauth-based approach, allowing multiple providers for authentication.
This commit is contained in:
Francesco Siddi 2017-08-18 18:34:10 +02:00
parent 6e9a539d61
commit 6b3e523036
6 changed files with 34 additions and 64 deletions

View File

@ -115,7 +115,6 @@ class PillarServer(Eve):
# Configure authentication
self.login_manager = auth.config_login_manager(self)
self.oauth_blender_id = auth.config_oauth_login(self)
self._config_caching()

View File

@ -9,7 +9,8 @@ import logging
import requests
from bson import tz_util
from flask import Blueprint, request, current_app, jsonify
from rauth import OAuth2Session
from flask import Blueprint, request, current_app, jsonify, session
from requests.adapters import HTTPAdapter
from pillar.api.utils import authentication
@ -175,23 +176,26 @@ def fetch_blenderid_user() -> dict:
bid_url = '%s/api/user' % blender_id_endpoint()
log.debug('Fetching user info from %s', bid_url)
try:
bid_resp = current_app.oauth_blender_id.get(bid_url)
client_id = current_app.config['OAUTH_CREDENTIALS']['blender-id']['id']
client_secret = current_app.config['OAUTH_CREDENTIALS']['blender-id']['secret']
oauth_session = OAuth2Session(
client_id, client_secret, access_token=session['blender_id_oauth_token'])
bid_resp = oauth_session.get(bid_url)
except httplib2.HttpLib2Error:
log.exception('Error getting %s from BlenderID', bid_url)
return {}
if bid_resp.status != 200:
log.warning('Error %i from BlenderID %s: %s', bid_resp.status, bid_url, bid_resp.data)
if bid_resp.status_code != 200:
log.warning('Error %i from BlenderID %s: %s', bid_resp.status_code, bid_url, bid_resp.data)
return {}
if not bid_resp.data:
if not bid_resp.json():
log.warning('Empty data returned from BlenderID %s', bid_url)
return {}
log.debug('BlenderID returned %s', bid_resp.data)
return bid_resp.data
log.debug('BlenderID returned %s', bid_resp.json())
return bid_resp.json()
def setup_app(app, url_prefix):

View File

@ -6,7 +6,6 @@ import typing
from flask import session, g
import flask_login
import flask_oauthlib.client
from werkzeug.local import LocalProxy
from pillar import current_app
@ -222,35 +221,6 @@ def get_blender_id_oauth_token():
return None
def config_oauth_login(app):
config = app.config
if not config.get('SOCIAL_BLENDER_ID'):
log.info('OAuth Blender-ID login not set up, no app config SOCIAL_BLENDER_ID.')
return None
if not config.get('BLENDER_ID_OAUTH_URL'):
log.error('Unable to use Blender ID, missing configuration BLENDER_ID_OAUTH_URL.')
return None
oauth = flask_oauthlib.client.OAuth(app)
social_blender_id = config.get('SOCIAL_BLENDER_ID')
oauth_blender_id = oauth.remote_app(
'blender_id',
consumer_key=social_blender_id['app_id'],
consumer_secret=social_blender_id['app_secret'],
request_token_params={'scope': 'email'},
base_url=config['BLENDER_ID_OAUTH_URL'],
request_token_url=None,
access_token_url=config['BLENDER_ID_BASE_ACCESS_TOKEN_URL'],
authorize_url=config['BLENDER_ID_AUTHORIZE_URL']
)
oauth_blender_id.tokengetter(get_blender_id_oauth_token)
log.info('OAuth Blender-ID login setup as %s', social_blender_id['app_id'])
return oauth_blender_id
def _get_current_user() -> UserClass:
"""Returns the current user as a UserClass instance.

View File

@ -1,10 +1,10 @@
import json
from rauth import OAuth2Service
from flask import current_app, url_for, request, redirect
from flask import current_app, url_for, request, redirect, session
class OAuthSignIn(object):
class OAuthSignIn:
providers = None
def __init__(self, provider_name):
@ -27,6 +27,7 @@ class OAuthSignIn(object):
def get_provider(cls, provider_name):
if cls.providers is None:
cls.providers = {}
# TODO convert to the new __init_subclass__
for provider_class in cls.__subclasses__():
provider = provider_class()
cls.providers[provider.provider_name] = provider
@ -35,7 +36,7 @@ class OAuthSignIn(object):
class BlenderIdSignIn(OAuthSignIn):
def __init__(self):
super(BlenderIdSignIn, self).__init__('blender-id')
super().__init__('blender-id')
base_url = current_app.config['OAUTH_CREDENTIALS']['blender-id'].get(
'base_url', 'https://www.blender.org/id/')
@ -73,6 +74,7 @@ class BlenderIdSignIn(OAuthSignIn):
me = oauth_session.get('user').json()
# TODO handle case when user chooses not to disclose en email
session['blender_id_oauth_token'] = oauth_session.access_token
return (
me['id'],
me.get('email'),
@ -82,7 +84,7 @@ class BlenderIdSignIn(OAuthSignIn):
class FacebookSignIn(OAuthSignIn):
def __init__(self):
super(FacebookSignIn, self).__init__('facebook')
super().__init__('facebook')
self.service = OAuth2Service(
name='facebook',
client_id=self.consumer_id,
@ -122,7 +124,7 @@ class FacebookSignIn(OAuthSignIn):
class GoogleSignIn(OAuthSignIn):
def __init__(self):
super(GoogleSignIn, self).__init__('google')
super().__init__('google')
self.service = OAuth2Service(
name='google',
client_id=self.consumer_id,

View File

@ -1,12 +1,10 @@
import json
import logging
import requests
from werkzeug import exceptions as wz_exceptions
from flask import abort, Blueprint, current_app, flash, redirect, render_template, request, session,\
url_for
from flask_login import login_required, logout_user, current_user
from flask_oauthlib.client import OAuthException
from pillarsdk import exceptions as sdk_exceptions
from pillarsdk.users import User
@ -16,6 +14,7 @@ import pillar.auth
from pillar.web import system_util
from pillar.api.local_auth import generate_and_store_token, get_local_user
from pillar.api.utils.authentication import find_user_in_db, upsert_user
from pillar.api.blender_cloud.subscription import update_subscription
from pillar.auth.oauth import OAuthSignIn
from . import forms
@ -45,24 +44,20 @@ def oauth_callback(provider):
if social_id is None:
log.debug('Authentication failed for user with {}'.format(provider))
return redirect(url_for('main.homepage'))
# If login from Blender ID we use the token to create the user
if provider == 'blender-id':
session['blender_id_oauth_token'] = (access_token, '')
pillar.auth.login_user(access_token)
if current_user is not None:
# Check with the store for user roles. If the user has an active
# subscription, we apply the 'subscriber' role
api = system_util.pillar_api(token=access_token)
api.get('bcloud/update-subscription')
else:
# Find or create user
user_info = {'id': social_id, 'email': email, 'full_name': ''}
db_user = find_user_in_db(user_info, provider=provider)
db_id, status = upsert_user(db_user)
token = generate_and_store_token(db_id)
# Login user
pillar.auth.login_user(token['token'])
# Find or create user
user_info = {'id': social_id, 'email': email, 'full_name': ''}
db_user = find_user_in_db(user_info, provider=provider)
db_id, status = upsert_user(db_user)
token = generate_and_store_token(db_id)
# Login user
pillar.auth.login_user(token['token'], load_from_db=True)
if provider == 'blender-id' and current_user is not None:
# Check with the store for user roles. If the user has an active subscription, we apply
# the 'subscriber' role
update_subscription()
next_after_login = session.pop('next_after_login', None)
if next_after_login:

View File

@ -14,7 +14,6 @@ Flask==0.12.2
Flask-Cache==0.13.1
Flask-Script==2.0.5
Flask-Login==0.3.2
Flask-OAuthlib==0.9.3
Flask-WTF==0.12
gcloud==0.12.0
google-apitools==0.4.11
@ -24,6 +23,7 @@ ndg-httpsclient==0.4.0
Pillow==4.1.1
pycrypto==2.6.1
python-dateutil==2.5.3
rauth==0.7.3
redis==2.10.5
WebOb==1.5.0
wheel==0.29.0