From 2c42972230d9a999f97a1da7c12b64e54c8d7c0d Mon Sep 17 00:00:00 2001 From: Ozzieisaacs Date: Thu, 16 Apr 2020 17:58:42 +0200 Subject: [PATCH] Fix for #1307 (Oauth login not working) - Changed blueprint reference in Backend from name to id, users can now again be found - Depending on version of flask-dance the resultcode of authorized is set different to prevent redirect loop with newer versions(>1.3) - Redirect to login page in case no user is linked to current oauth account - Flash messages upon successfull login, successsfull linked account --- cps/oauth.py | 4 +++- cps/oauth_bb.py | 40 ++++++++++++++++++++++-------------- cps/templates/user_edit.html | 2 +- 3 files changed, 29 insertions(+), 17 deletions(-) diff --git a/cps/oauth.py b/cps/oauth.py index 7846a47b..e5c5fb5f 100644 --- a/cps/oauth.py +++ b/cps/oauth.py @@ -23,12 +23,14 @@ from flask import session try: from flask_dance.consumer.backend.sqla import SQLAlchemyBackend, first, _get_real_user from sqlalchemy.orm.exc import NoResultFound + backend_resultcode = False # prevent storing values with this resultcode except ImportError: # fails on flask-dance >1.3, due to renaming try: from flask_dance.consumer.storage.sqla import SQLAlchemyStorage as SQLAlchemyBackend from flask_dance.consumer.storage.sqla import first, _get_real_user from sqlalchemy.orm.exc import NoResultFound + backend_resultcode = True # prevent storing values with this resultcode except ImportError: pass @@ -48,7 +50,7 @@ try: def get(self, blueprint, user=None, user_id=None): if self.provider_id + '_oauth_token' in session and session[self.provider_id + '_oauth_token'] != '': - return session[blueprint.name + '_oauth_token'] + return session[self.provider_id + '_oauth_token'] # check cache cache_key = self.make_cache_key(blueprint=blueprint, user=user, user_id=user_id) token = self.cache.get(cache_key) diff --git a/cps/oauth_bb.py b/cps/oauth_bb.py index 2dbcc875..d98ec50a 100644 --- a/cps/oauth_bb.py +++ b/cps/oauth_bb.py @@ -35,7 +35,7 @@ from sqlalchemy.orm.exc import NoResultFound from . import constants, logger, config, app, ub from .web import login_required -from .oauth import OAuthBackend +from .oauth import OAuthBackend, backend_resultcode oauth_check = {} @@ -141,9 +141,9 @@ if ub.oauth_support: scope=element['scope'] ) element['blueprint'] = blueprint - app.register_blueprint(blueprint, url_prefix="/login") element['blueprint'].backend = OAuthBackend(ub.OAuth, ub.session, str(element['id']), user=current_user, user_required=True) + app.register_blueprint(blueprint, url_prefix="/login") if element['active']: register_oauth_blueprint(element['id'], element['provider_name']) @@ -207,19 +207,23 @@ if ub.oauth_support: ub.session.rollback() # Disable Flask-Dance's default behavior for saving the OAuth token - return False + # Value differrs depending on flask-dance version + return backend_resultcode - def bind_oauth_or_register(provider_id, provider_user_id, redirect_url): + def bind_oauth_or_register(provider_id, provider_user_id, redirect_url, provider_name): query = ub.session.query(ub.OAuth).filter_by( provider=provider_id, provider_user_id=provider_user_id, ) try: - oauth_entry = query.one() + oauth_entry = query.first() # already bind with user, just login if oauth_entry.user: login_user(oauth_entry.user) + log.debug(u"You are now logged in as: '%s'", oauth_entry.user.nickname) + flash(_(u"you are now logged in as: '%(nickname)s'", nickname= oauth_entry.user.nickname), + category="success") return redirect(url_for('web.index')) else: # bind to current user @@ -228,16 +232,22 @@ if ub.oauth_support: try: ub.session.add(oauth_entry) ub.session.commit() + flash(_(u"Link to %(oauth)s Succeeded", oauth=provider_name), category="success") + return redirect(url_for('web.profile')) except Exception as e: log.exception(e) ub.session.rollback() - return redirect(url_for('web.login')) + else: + flash(_(u"Login failed, No User Linked With OAuth Account"), category="error") + log.info('Login failed, No User Linked With OAuth Account') + return redirect(url_for('web.login')) + # return redirect(url_for('web.login')) # if config.config_public_reg: # return redirect(url_for('web.register')) # else: # flash(_(u"Public registration is not enabled"), category="error") # return redirect(url_for(redirect_url)) - except NoResultFound: + except (NoResultFound, AttributeError): return redirect(url_for(redirect_url)) @@ -270,14 +280,14 @@ if ub.oauth_support: ub.session.delete(oauth_entry) ub.session.commit() logout_oauth_user() - flash(_(u"Unlink to %(oauth)s success.", oauth=oauth_check[provider]), category="success") + flash(_(u"Unlink to %(oauth)s Succeeded", oauth=oauth_check[provider]), category="success") except Exception as e: log.exception(e) ub.session.rollback() - flash(_(u"Unlink to %(oauth)s failed.", oauth=oauth_check[provider]), category="error") + flash(_(u"Unlink to %(oauth)s Failed", oauth=oauth_check[provider]), category="error") except NoResultFound: - log.warning("oauth %s for user %d not fount", provider, current_user.id) - flash(_(u"Not linked to %(oauth)s.", oauth=oauth_check[provider]), category="error") + log.warning("oauth %s for user %d not found", provider, current_user.id) + flash(_(u"Not Linked to %(oauth)s.", oauth=oauth_check[provider]), category="error") return redirect(url_for('web.profile')) @@ -296,7 +306,7 @@ if ub.oauth_support: flash(msg, category="error") - @oauth.route('/github') + @oauth.route('/link/github') @oauth_required def github_login(): if not github.authorized: @@ -304,7 +314,7 @@ if ub.oauth_support: account_info = github.get('/user') if account_info.ok: account_info_json = account_info.json() - return bind_oauth_or_register(oauthblueprints[0]['id'], account_info_json['id'], 'github.login') + return bind_oauth_or_register(oauthblueprints[0]['id'], account_info_json['id'], 'github.login', 'github') flash(_(u"GitHub Oauth error, please retry later."), category="error") return redirect(url_for('web.login')) @@ -315,7 +325,7 @@ if ub.oauth_support: return unlink_oauth(oauthblueprints[0]['id']) - @oauth.route('/login/google') + @oauth.route('/link/google') @oauth_required def google_login(): if not google.authorized: @@ -323,7 +333,7 @@ if ub.oauth_support: resp = google.get("/oauth2/v2/userinfo") if resp.ok: account_info_json = resp.json() - return bind_oauth_or_register(oauthblueprints[1]['id'], account_info_json['id'], 'google.login') + return bind_oauth_or_register(oauthblueprints[1]['id'], account_info_json['id'], 'google.login', 'google') flash(_(u"Google Oauth error, please retry later."), category="error") return redirect(url_for('web.login')) diff --git a/cps/templates/user_edit.html b/cps/templates/user_edit.html index d3b80a55..cb473f38 100644 --- a/cps/templates/user_edit.html +++ b/cps/templates/user_edit.html @@ -46,7 +46,7 @@ {% endfor %} - {% if registered_oauth.keys()| length > 0 %} + {% if registered_oauth.keys()| length > 0 and not new_user %} {% for id, name in registered_oauth.items() %}