From 1455afbda3cfa6ce917a68e2ced27ea7798ab836 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Mon, 26 Nov 2012 09:53:34 +0100 Subject: [PATCH 1/8] [IMP] auth_oauth: refactor js method on_oauth_sign_in() to enable overriding of the oauth state definition bzr revid: rco@openerp.com-20121126085334-df4xhhcwvwe40xgj --- addons/auth_oauth/static/src/js/auth_oauth.js | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/addons/auth_oauth/static/src/js/auth_oauth.js b/addons/auth_oauth/static/src/js/auth_oauth.js index 2aa66877d42..2c3aa86880c 100644 --- a/addons/auth_oauth/static/src/js/auth_oauth.js +++ b/addons/auth_oauth/static/src/js/auth_oauth.js @@ -35,27 +35,30 @@ openerp.auth_oauth = function(instance) { on_oauth_sign_in: function(ev) { ev.preventDefault(); var index = $(ev.target).data('index'); - var p = this.oauth_providers[index]; - var ret = _.str.sprintf('%s//%s/auth_oauth/signin', location.protocol, location.host); + var provider = this.oauth_providers[index]; + var return_url = _.str.sprintf('%s//%s/auth_oauth/signin', location.protocol, location.host); if (instance.session.debug) { - ret += '?debug'; + return_url += '?debug'; } - var dbname = self.$("form [name=db]").val(); - var state_object = { - d: dbname, - p: p.id - }; - var state = JSON.stringify(state_object); + var state = self._oauth_state(); var params = { response_type: 'token', - client_id: p.client_id, - redirect_uri: ret, - scope: p.scope, - state: state, + client_id: provider.client_id, + redirect_uri: return_url, + scope: provider.scope, + state: JSON.stringify(state), }; - var url = p.auth_endpoint + '?' + $.param(params); + var url = provider.auth_endpoint + '?' + $.param(params); window.location = url; }, + _oauth_state: function(provider) { + // return the state object sent back with the redirected uri + var dbname = self.$("form [name=db]").val(); + return { + d: dbname, + p: provider.id, + }; + }, }); }; From c15ca7dbe9f4aee9e52b2e78d3caf34fc5e48e64 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Mon, 26 Nov 2012 10:46:26 +0100 Subject: [PATCH 2/8] [IMP] auth_oauth: refactor method auth_oauth to ease the addition of signin methods bzr revid: rco@openerp.com-20121126094626-88rfueeeycy66wsi --- addons/auth_oauth/res_users.py | 58 +++++++++++++++------------------- 1 file changed, 26 insertions(+), 32 deletions(-) diff --git a/addons/auth_oauth/res_users.py b/addons/auth_oauth/res_users.py index 7e7b3753a4e..028aa3b99db 100644 --- a/addons/auth_oauth/res_users.py +++ b/addons/auth_oauth/res_users.py @@ -45,6 +45,24 @@ class res_users(osv.Model): validation.update(data) return validation + def _auth_oauth_signin(self, cr, uid, provider, validation, params, context=None): + """ retrieve and sign in the user corresponding to provider and validated access token + :param provider: oauth provider id + :param validation: result of validation of access token (dict) + :param params: oauth parameters (dict) + :return: login or None + + This method can be overridden to add alternative signin methods. + """ + oauth_uid = validation['user_id'] + user_ids = self.search(cr, uid, [("oauth_uid", "=", oauth_uid), ('oauth_provider_id', '=', provider)]) + if user_ids: + assert len(user_ids) == 1 + user = self.browse(cr, uid, user_ids[0], context=context) + user.write({'oauth_access_token': access_token}) + return user.login + return None + def auth_oauth(self, cr, uid, provider, params, context=None): # Advice by Google (to avoid Confused Deputy Problem) # if validation.audience != OUR_CLIENT_ID: @@ -53,39 +71,15 @@ class res_users(osv.Model): # continue with the process access_token = params.get('access_token') validation = self._auth_oauth_validate(cr, uid, provider, access_token) - # required - oauth_uid = validation['user_id'] - if not oauth_uid: + # required check + if not validation.get('user_id'): raise openerp.exceptions.AccessDenied() - email = validation.get('email', 'provider_%d_user_%d' % (provider, oauth_uid)) - login = email - # optional - name = validation.get('name', email) - res = self.search(cr, uid, [("oauth_uid", "=", oauth_uid), ('oauth_provider_id', '=', provider)]) - if res: - assert len(res) == 1 - user = self.browse(cr, uid, res[0], context=context) - login = user.login - user.write({'oauth_access_token': access_token}) - else: - # New user if signup module available - if not hasattr(self, '_signup_create_user'): - raise openerp.exceptions.AccessDenied() - - new_user = { - 'name': name, - 'login': login, - 'user_email': email, - 'oauth_provider_id': provider, - 'oauth_uid': oauth_uid, - 'oauth_access_token': access_token, - 'active': True, - } - # TODO pass signup token to allow attach new user to right partner - self._signup_create_user(cr, uid, new_user) - - credentials = (cr.dbname, login, access_token) - return credentials + # retrieve and sign in user + login = self._auth_oauth_signin(cr, uid, provider, validation, params, context=context) + if not login: + raise openerp.exceptions.AccessDenied() + # return user credentials + return (cr.dbname, login, access_token) def check_credentials(self, cr, uid, password): try: From 867a84c3f86e5ee47bb99bf4409f3987a31d5f42 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Mon, 26 Nov 2012 11:42:51 +0100 Subject: [PATCH 3/8] [FIX] auth_oauth: improve method _auth_oauth_signin bzr revid: rco@openerp.com-20121126104251-j6355zk91f468y5y --- addons/auth_oauth/res_users.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/addons/auth_oauth/res_users.py b/addons/auth_oauth/res_users.py index 028aa3b99db..762559d8b81 100644 --- a/addons/auth_oauth/res_users.py +++ b/addons/auth_oauth/res_users.py @@ -47,21 +47,21 @@ class res_users(osv.Model): def _auth_oauth_signin(self, cr, uid, provider, validation, params, context=None): """ retrieve and sign in the user corresponding to provider and validated access token - :param provider: oauth provider id + :param provider: oauth provider id (int) :param validation: result of validation of access token (dict) :param params: oauth parameters (dict) - :return: login or None + :return: user login (str) This method can be overridden to add alternative signin methods. """ oauth_uid = validation['user_id'] user_ids = self.search(cr, uid, [("oauth_uid", "=", oauth_uid), ('oauth_provider_id', '=', provider)]) - if user_ids: - assert len(user_ids) == 1 - user = self.browse(cr, uid, user_ids[0], context=context) - user.write({'oauth_access_token': access_token}) - return user.login - return None + if not user_ids: + raise openerp.exceptions.AccessDenied() + assert len(user_ids) == 1 + user = self.browse(cr, uid, user_ids[0], context=context) + user.write({'oauth_access_token': params['access_token']}) + return user.login def auth_oauth(self, cr, uid, provider, params, context=None): # Advice by Google (to avoid Confused Deputy Problem) From 1299315111f1b398efe13e46ce5346f67964b610 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Mon, 26 Nov 2012 11:52:42 +0100 Subject: [PATCH 4/8] [ADD] auth_oauth_signup: link module to make auth_oauth work with auth_signup bzr revid: rco@openerp.com-20121126105242-4a1urt7lwnkvchgm --- addons/auth_oauth_signup/__init__.py | 22 +++++++ addons/auth_oauth_signup/__openerp__.py | 39 ++++++++++++ addons/auth_oauth_signup/res_users.py | 60 +++++++++++++++++++ .../static/src/js/auth_oauth_signup.js | 14 +++++ 4 files changed, 135 insertions(+) create mode 100644 addons/auth_oauth_signup/__init__.py create mode 100644 addons/auth_oauth_signup/__openerp__.py create mode 100644 addons/auth_oauth_signup/res_users.py create mode 100644 addons/auth_oauth_signup/static/src/js/auth_oauth_signup.js diff --git a/addons/auth_oauth_signup/__init__.py b/addons/auth_oauth_signup/__init__.py new file mode 100644 index 00000000000..bc40c87d118 --- /dev/null +++ b/addons/auth_oauth_signup/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2012-today OpenERP SA () +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see +# +############################################################################## + +import res_users diff --git a/addons/auth_oauth_signup/__openerp__.py b/addons/auth_oauth_signup/__openerp__.py new file mode 100644 index 00000000000..1e5767065a4 --- /dev/null +++ b/addons/auth_oauth_signup/__openerp__.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2010-2012 OpenERP SA (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +{ + 'name': 'Signup with OAuth2 Authentication', + 'version': '1.0', + 'category': 'Hidden', + 'description': """ +Allow users to sign up through OAuth2 Provider. +=============================================== +""", + 'author': 'OpenERP SA', + 'website': 'http://www.openerp.com', + 'depends': ['auth_oauth', 'auth_signup'], + 'data': [], + 'js': ['static/src/js/auth_oauth_signup.js'], + 'css': [], + 'qweb': [], + 'installable': True, + 'auto_install': True, +} diff --git a/addons/auth_oauth_signup/res_users.py b/addons/auth_oauth_signup/res_users.py new file mode 100644 index 00000000000..8b56585d04d --- /dev/null +++ b/addons/auth_oauth_signup/res_users.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2010-2012 OpenERP SA (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +import logging + +import urllib +import urlparse +import urllib2 +import simplejson + +import openerp +from openerp.osv import osv, fields +from openerp import SUPERUSER_ID + +_logger = logging.getLogger(__name__) + +class res_users(osv.Model): + _inherit = 'res.users' + + def _auth_oauth_signin(self, cr, uid, provider, validation, params, context=None): + # overridden to use signup method if regular oauth signin fails + try: + login = super(res_users, self)._auth_oauth_signin(cr, uid, provider, validation, params, context=context) + + except openerp.exceptions.AccessDenied: + state = simplejson.loads(params['state']) + token = state.get('t') + oauth_uid = validation['user_id'] + email = validation.get('email', 'provider_%d_user_%d' % (provider, oauth_uid)) + name = validation.get('name', email) + values = { + 'name': name, + 'login': email, + 'email': email, + 'oauth_provider_id': provider, + 'oauth_uid': oauth_uid, + 'oauth_access_token': params['access_token'], + 'active': True, + } + _, login, _ = self.signup(cr, uid, values, token, context=context) + + return login diff --git a/addons/auth_oauth_signup/static/src/js/auth_oauth_signup.js b/addons/auth_oauth_signup/static/src/js/auth_oauth_signup.js new file mode 100644 index 00000000000..6715943af9b --- /dev/null +++ b/addons/auth_oauth_signup/static/src/js/auth_oauth_signup.js @@ -0,0 +1,14 @@ +openerp.auth_oauth_signup = function(instance) { + + // override Login._oauth_state to add the signup token in the state + instance.web.Login.include({ + _oauth_state: function(provider) { + var state = this._super.apply(this, arguments); + if (this.params.token) { + state.t = this.params.token; + } + return state; + }, + }); + +}; From ff4e9c7e2ccbf36f3cd676d0588cf90c736a1e16 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Mon, 26 Nov 2012 12:03:01 +0100 Subject: [PATCH 5/8] [IMP] auth_oauth_signup: remove useless imports from code bzr revid: rco@openerp.com-20121126110301-pcwta72vkdfhb6wk --- addons/auth_oauth_signup/res_users.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/addons/auth_oauth_signup/res_users.py b/addons/auth_oauth_signup/res_users.py index 8b56585d04d..83400f7c008 100644 --- a/addons/auth_oauth_signup/res_users.py +++ b/addons/auth_oauth_signup/res_users.py @@ -20,15 +20,10 @@ ############################################################################## import logging - -import urllib -import urlparse -import urllib2 import simplejson import openerp from openerp.osv import osv, fields -from openerp import SUPERUSER_ID _logger = logging.getLogger(__name__) From a50bc125f83956841782fd2e17798f01cdf0f911 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Tue, 27 Nov 2012 11:06:35 +0100 Subject: [PATCH 6/8] [IMP] auth_oauth: doc improvement bzr revid: rco@openerp.com-20121127100635-vzbuw6a73286t2t2 --- addons/auth_oauth/res_users.py | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/auth_oauth/res_users.py b/addons/auth_oauth/res_users.py index 762559d8b81..b1c7e214f12 100644 --- a/addons/auth_oauth/res_users.py +++ b/addons/auth_oauth/res_users.py @@ -51,6 +51,7 @@ class res_users(osv.Model): :param validation: result of validation of access token (dict) :param params: oauth parameters (dict) :return: user login (str) + :raise: openerp.exceptions.AccessDenied if signin failed This method can be overridden to add alternative signin methods. """ From 22f30bc8dc037aa1590ec3e497eca2c9677f4fa5 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Tue, 27 Nov 2012 16:30:40 +0100 Subject: [PATCH 7/8] [FIX] auth_oauth: stupid mistake, using 'self' instead of 'this'... bzr revid: rco@openerp.com-20121127153040-aol52i523ysabah8 --- addons/auth_oauth/static/src/js/auth_oauth.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/auth_oauth/static/src/js/auth_oauth.js b/addons/auth_oauth/static/src/js/auth_oauth.js index 2c3aa86880c..c3a6aeb15ca 100644 --- a/addons/auth_oauth/static/src/js/auth_oauth.js +++ b/addons/auth_oauth/static/src/js/auth_oauth.js @@ -40,7 +40,7 @@ openerp.auth_oauth = function(instance) { if (instance.session.debug) { return_url += '?debug'; } - var state = self._oauth_state(); + var state = this._oauth_state(); var params = { response_type: 'token', client_id: provider.client_id, @@ -53,7 +53,7 @@ openerp.auth_oauth = function(instance) { }, _oauth_state: function(provider) { // return the state object sent back with the redirected uri - var dbname = self.$("form [name=db]").val(); + var dbname = this.$("form [name=db]").val(); return { d: dbname, p: provider.id, From 7c61b7142df3c599b02db791cab7f7c56a141b76 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Tue, 27 Nov 2012 16:35:32 +0100 Subject: [PATCH 8/8] [FIX] auth_oauth: add missing parameter in method call... bzr revid: rco@openerp.com-20121127153532-5jw6sm8ltcmoewrq --- addons/auth_oauth/static/src/js/auth_oauth.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/auth_oauth/static/src/js/auth_oauth.js b/addons/auth_oauth/static/src/js/auth_oauth.js index c3a6aeb15ca..fdf7baf607c 100644 --- a/addons/auth_oauth/static/src/js/auth_oauth.js +++ b/addons/auth_oauth/static/src/js/auth_oauth.js @@ -40,7 +40,7 @@ openerp.auth_oauth = function(instance) { if (instance.session.debug) { return_url += '?debug'; } - var state = this._oauth_state(); + var state = this._oauth_state(provider); var params = { response_type: 'token', client_id: provider.client_id,