diff --git a/addons/auth_oauth/controllers/main.py b/addons/auth_oauth/controllers/main.py index b1393997ff3..9cfe7ad137c 100644 --- a/addons/auth_oauth/controllers/main.py +++ b/addons/auth_oauth/controllers/main.py @@ -123,51 +123,53 @@ class OAuthController(http.Controller): @fragment_to_query_string def signin(self, **kw): state = json.loads(kw['state']) + + # make sure request.session.db and state['d'] are the same, + # update the session and retry the request otherwise dbname = state['d'] if not http.db_filter([dbname]): return BadRequest() + ensure_db(db=dbname) + provider = state['p'] - context = clean_context(state.get('c', {})) - registry = registry_get(dbname) - with registry.cursor() as cr: - try: - env = api.Environment(cr, SUPERUSER_ID, context) - db, login, key = env['res.users'].sudo().auth_oauth(provider, kw) - cr.commit() - action = state.get('a') - menu = state.get('m') - redirect = werkzeug.urls.url_unquote_plus(state['r']) if state.get('r') else False - url = '/web' - if redirect: - url = redirect - elif action: - url = '/web#action=%s' % action - elif menu: - url = '/web#menu_id=%s' % menu + request.update_context(**clean_context(state.get('c', {}))) + try: + # auth_oauth may create a new user, the commit makes it + # visible to authenticate()'s own transaction below + _, login, key = request.env['res.users'].with_user(SUPERUSER_ID).auth_oauth(provider, kw) + request.env.cr.commit() - pre_uid = request.session.authenticate(db, login, key) - resp = request.redirect(_get_login_redirect_url(pre_uid, url), 303) - resp.autocorrect_location_header = False + action = state.get('a') + menu = state.get('m') + redirect = werkzeug.urls.url_unquote_plus(state['r']) if state.get('r') else False + url = '/web' + if redirect: + url = redirect + elif action: + url = '/web#action=%s' % action + elif menu: + url = '/web#menu_id=%s' % menu - # Since /web is hardcoded, verify user has right to land on it - if werkzeug.urls.url_parse(resp.location).path == '/web' and not request.env.user._is_internal(): - resp.location = '/' - return resp - except AttributeError: - # auth_signup is not installed - _logger.error("auth_signup not installed on database %s: oauth sign up cancelled." % (dbname,)) - url = "/web/login?oauth_error=1" - except AccessDenied: - # oauth credentials not valid, user could be on a temporary session - _logger.info('OAuth2: access denied, redirect to main page in case a valid session exists, without setting cookies') - url = "/web/login?oauth_error=3" - redirect = request.redirect(url, 303) - redirect.autocorrect_location_header = False - return redirect - except Exception as e: - # signup error - _logger.exception("OAuth2: %s" % str(e)) - url = "/web/login?oauth_error=2" + pre_uid = request.session.authenticate(dbname, login, key) + resp = request.redirect(_get_login_redirect_url(pre_uid, url), 303) + resp.autocorrect_location_header = False + + # Since /web is hardcoded, verify user has right to land on it + if werkzeug.urls.url_parse(resp.location).path == '/web' and not request.env.user._is_internal(): + resp.location = '/' + return resp + except AttributeError: # TODO juc master: useless since ensure_db() + # auth_signup is not installed + _logger.error("auth_signup not installed on database %s: oauth sign up cancelled.", dbname) + url = "/web/login?oauth_error=1" + except AccessDenied: + # oauth credentials not valid, user could be on a temporary session + _logger.info('OAuth2: access denied, redirect to main page in case a valid session exists, without setting cookies') + url = "/web/login?oauth_error=3" + except Exception: + # signup error + _logger.exception("Exception during request handling") + url = "/web/login?oauth_error=2" redirect = request.redirect(url, 303) redirect.autocorrect_location_header = False diff --git a/addons/web/controllers/utils.py b/addons/web/controllers/utils.py index f14141d16dd..f1baae5997f 100644 --- a/addons/web/controllers/utils.py +++ b/addons/web/controllers/utils.py @@ -52,7 +52,7 @@ def clean_action(action, env): return cleaned_action -def ensure_db(redirect='/web/database/selector'): +def ensure_db(redirect='/web/database/selector', db=None): # This helper should be used in web client auth="none" routes # if those routes needs a db to work with. # If the heuristics does not find any database, then the users will be @@ -60,7 +60,8 @@ def ensure_db(redirect='/web/database/selector'): # If the db is taken out of a query parameter, it will be checked against # `http.db_filter()` in order to ensure it's legit and thus avoid db # forgering that could lead to xss attacks. - db = request.params.get('db') and request.params.get('db').strip() + if db is None: + db = request.params.get('db') and request.params.get('db').strip() # Ensure db is legit if db and db not in http.db_filter([db]): diff --git a/odoo/http.py b/odoo/http.py index 2d6afc1b927..0156a8558c3 100644 --- a/odoo/http.py +++ b/odoo/http.py @@ -1017,6 +1017,7 @@ class Session(collections.abc.MutableMapping): self.should_rotate = True self.update({ + 'db': env.registry.db_name, 'login': login, 'uid': uid, 'context': user_context,