diff --git a/controllers/main.py b/controllers/main.py index aed15c7e0451fcac62e7042c6d2a66e8244ac496_Y29udHJvbGxlcnMvbWFpbi5weQ==..6d2087dae38a0fa73b3b9872272353e2bd5e1951_Y29udHJvbGxlcnMvbWFpbi5weQ== 100644 --- a/controllers/main.py +++ b/controllers/main.py @@ -124,11 +124,10 @@ state = self.get_state(provider_id) try: - with request.registry.cursor() as cr: - auth_request = provider_osv._get_auth_request( - cr, SUPERUSER_ID, provider_id, state=state - ) + auth_request = provider_osv._get_auth_request( + request.cr, SUPERUSER_ID, provider_id, state + ) except Exception, e: _logger.exception("SAML2: %s" % str(e)) @@ -131,7 +130,9 @@ except Exception, e: _logger.exception("SAML2: %s" % str(e)) + # TODO: handle case when auth_request comes back as None + # store a RelayState on the request to our IDP so that the IDP # can send us back this info alongside the obtained token params = { diff --git a/model/auth_saml.py b/model/auth_saml.py index aed15c7e0451fcac62e7042c6d2a66e8244ac496_bW9kZWwvYXV0aF9zYW1sLnB5..6d2087dae38a0fa73b3b9872272353e2bd5e1951_bW9kZWwvYXV0aF9zYW1sLnB5 100644 --- a/model/auth_saml.py +++ b/model/auth_saml.py @@ -1,4 +1,5 @@ -from openerp.osv import fields -from openerp.osv import osv +from openerp import models +from openerp import api +from openerp import fields import lasso import simplejson @@ -3,5 +4,4 @@ import lasso import simplejson -from openerp import SUPERUSER_ID @@ -6,9 +6,9 @@ -class auth_saml_provider(osv.osv): +class auth_saml_provider(models.Model): """Class defining the configuration values of an Saml2 provider""" _name = 'auth.saml.provider' _description = 'SAML2 provider' _order = 'name' @@ -9,8 +9,9 @@ """Class defining the configuration values of an Saml2 provider""" _name = 'auth.saml.provider' _description = 'SAML2 provider' _order = 'name' - def _get_lasso_for_provider(self, cr, uid, pid, context=None): + @api.multi + def _get_lasso_for_provider(self): # user is not connected yet... so use SUPERUSER_ID @@ -16,6 +17,5 @@ # user is not connected yet... so use SUPERUSER_ID - provider = self.browse(cr, SUPERUSER_ID, pid, context=context) # TODO: we should cache those results somewhere because it is # really costy to always recreate a login variable from buffers server = lasso.Server.newFromBuffers( @@ -18,9 +18,9 @@ # TODO: we should cache those results somewhere because it is # really costy to always recreate a login variable from buffers server = lasso.Server.newFromBuffers( - provider.sp_metadata, - provider.sp_pkey + self.sp_metadata, + self.sp_pkey ) server.addProviderFromBuffer( lasso.PROVIDER_ROLE_IDP, @@ -24,7 +24,7 @@ ) server.addProviderFromBuffer( lasso.PROVIDER_ROLE_IDP, - provider.idp_metadata + self.idp_metadata ) return lasso.Login(server) @@ -28,7 +28,8 @@ ) return lasso.Login(server) - def _get_auth_request(self, cr, uid, pid, state, context=None): + @api.multi + def _get_auth_request(self, state): """build an authentication request and give it back to our client WARNING: this method cannot be used for multiple ids """ @@ -32,7 +33,7 @@ """build an authentication request and give it back to our client WARNING: this method cannot be used for multiple ids """ - login = self._get_lasso_for_provider(cr, uid, pid, context=context) + login = self._get_lasso_for_provider() # ! -- this is the part that MUST be performed on each call and # cannot be cached @@ -46,25 +47,14 @@ # obtained after the buildAuthnRequestMsg() call return login.msgUrl - _columns = { - # Name of the OAuth2 entity, authentic, xcg... - 'name': fields.char('Provider name'), - 'idp_metadata': fields.text('IDP Configuration'), - 'sp_metadata': fields.text('SP Configuration'), - 'sp_pkey': fields.text( - 'Private key of our service provider (this openerpserver)' - ), - 'enabled': fields.boolean('Enabled'), - 'css_class': fields.char('CSS class'), - 'body': fields.char( - 'Body', - required=True, - ), - 'sequence': fields.integer(), - } - - _defaults = { - 'enabled': False, - 'css_class': 'zocial saml', - 'body': 'Authentic', - } + # Name of the OAuth2 entity, authentic, xcg... + name = fields.Char('Provider name') + idp_metadata = fields.Text('IDP Configuration') + sp_metadata = fields.Text('SP Configuration') + sp_pkey = fields.Text( + 'Private key of our service provider (this openerpserver)' + ) + enabled = fields.Boolean('Enabled', default=False) + sequence = fields.Integer('Sequence') + css_class = fields.Char('CSS Class') + body = fields.Char('Body') diff --git a/model/res_users.py b/model/res_users.py index aed15c7e0451fcac62e7042c6d2a66e8244ac496_bW9kZWwvcmVzX3VzZXJzLnB5..6d2087dae38a0fa73b3b9872272353e2bd5e1951_bW9kZWwvcmVzX3VzZXJzLnB5 100644 --- a/model/res_users.py +++ b/model/res_users.py @@ -6,5 +6,7 @@ import passlib import openerp -from openerp.osv import osv, fields +from openerp import api +from openerp import models +from openerp import fields from openerp import SUPERUSER_ID @@ -10,5 +12,6 @@ from openerp import SUPERUSER_ID +from openerp.addons.base.res.res_users import res_users as baseuser _logger = logging.getLogger(__name__) @@ -11,7 +14,7 @@ _logger = logging.getLogger(__name__) -class res_users(osv.Model): +class res_users(models.Model): _inherit = 'res.users' @@ -16,13 +19,11 @@ _inherit = 'res.users' - _columns = { - 'saml_provider_id': fields.many2one( - 'auth.saml.provider', - string='SAML Provider', - ), - 'saml_uid': fields.char( - 'SAML User ID', - help="SAML Provider user_id", - ), - } + saml_provider_id = fields.Many2one( + 'auth.saml.provider', + string='SAML Provider', + ) + saml_uid = fields.Char( + 'SAML User ID', + help="SAML Provider user_id", + ) @@ -28,6 +29,7 @@ - def _no_password_with_saml(self, cr, uid, ids, context=None): + @api.multi + def _no_password_with_saml(self): """Ensure no Odoo user posesses both an SAML user ID and an Odoo password. """ @@ -30,8 +32,8 @@ """Ensure no Odoo user posesses both an SAML user ID and an Odoo password. """ - if self._allow_saml_uid_and_internal_password(cr, uid, context): + if self._allow_saml_uid_and_internal_password(): # The constraint is a no-op in this case. return True @@ -35,8 +37,7 @@ # The constraint is a no-op in this case. return True - users = self.browse(cr, uid, ids, context=context) - for user in users: + for user in self: if user.password and user.saml_uid: return False @@ -61,6 +62,7 @@ ), ] - def _auth_saml_validate(self, cr, uid, provider_id, token, context=None): + @api.multi + def _auth_saml_validate(self, provider_id, token): """ return the validation data corresponding to the access token """ @@ -65,5 +67,7 @@ """ return the validation data corresponding to the access token """ - p = self.pool.get('auth.saml.provider') + pobj = self.env['auth.saml.provider'] + p = pobj.browse(provider_id) + # we are not yet logged in, so the userid cannot have access to the # fields we need yet @@ -68,8 +72,6 @@ # we are not yet logged in, so the userid cannot have access to the # fields we need yet - login = p._get_lasso_for_provider( - cr, SUPERUSER_ID, provider_id, context=context - ) + login = p.sudo()._get_lasso_for_provider() try: login.processAuthnResponseMsg(token) @@ -87,5 +89,5 @@ # TODO use a real token validation from LASSO # TODO push into the validation result a real UPN - validation = {'user_id': login.assertion.subject.nameId.content} + return {'user_id': login.assertion.subject.nameId.content} @@ -91,15 +93,6 @@ - """ - if p.data_endpoint: - data = self._auth_oauth_rpc(cr, uid, p.data_endpoint, access_token) - validation.update(data) - """ - - return validation - - def _auth_saml_signin( - self, cr, uid, provider, validation, saml_response, context=None - ): + @api.multi + def _auth_saml_signin(self, provider, validation, saml_response): """ retrieve and sign into openerp the user corresponding to provider and validated access token @@ -111,7 +104,7 @@ This method can be overridden to add alternative signin methods. """ - token_osv = self.pool.get('auth_saml.token') + token_osv = self.env['auth_saml.token'] saml_uid = validation['user_id'] user_ids = self.search( @@ -115,7 +108,6 @@ saml_uid = validation['user_id'] user_ids = self.search( - cr, uid, [ ("saml_uid", "=", saml_uid), ('saml_provider_id', '=', provider), @@ -128,11 +120,7 @@ # TODO replace assert by proper raise... asserts do not execute in # production code... assert len(user_ids) == 1 - - # browse the user because we'll need this in the response - user = self.browse(cr, uid, user_ids[0], context=context) - - user_id = user.id + user = user_ids[0] # now find if a token for this user/provider already exists token_ids = token_osv.search( @@ -136,6 +124,5 @@ # now find if a token for this user/provider already exists token_ids = token_osv.search( - cr, uid, [ ('saml_provider_id', '=', provider), @@ -140,5 +127,5 @@ [ ('saml_provider_id', '=', provider), - ('user_id', '=', user_id), + ('user_id', '=', user.id), ] ) @@ -143,3 +130,4 @@ ] ) + if token_ids: @@ -145,4 +133,3 @@ if token_ids: - token_osv.write( - cr, uid, token_ids, + token_ids.write( {'saml_access_token': saml_response}, @@ -148,5 +135,4 @@ {'saml_access_token': saml_response}, - context=context ) else: token_osv.create( @@ -150,7 +136,6 @@ ) else: token_osv.create( - cr, uid, { 'saml_access_token': saml_response, 'saml_provider_id': provider, @@ -154,5 +139,5 @@ { 'saml_access_token': saml_response, 'saml_provider_id': provider, - 'user_id': user_id, + 'user_id': user.id, }, @@ -158,6 +143,5 @@ }, - context=context ) return user.login @@ -160,6 +144,7 @@ ) return user.login - def auth_saml(self, cr, uid, provider, saml_response, context=None): + @api.model + def auth_saml(self, provider, saml_response): @@ -165,10 +150,8 @@ - validation = self._auth_saml_validate( - cr, uid, provider, saml_response - ) + validation = self._auth_saml_validate(provider, saml_response) # required check if not validation.get('user_id'): raise openerp.exceptions.AccessDenied() # retrieve and sign in user @@ -169,14 +152,12 @@ # required check if not validation.get('user_id'): raise openerp.exceptions.AccessDenied() # retrieve and sign in user - login = self._auth_saml_signin( - cr, uid, provider, validation, saml_response, context=context - ) + login = self._auth_saml_signin(provider, validation, saml_response) if not login: raise openerp.exceptions.AccessDenied() # return user credentials @@ -178,9 +159,9 @@ if not login: raise openerp.exceptions.AccessDenied() # return user credentials - return cr.dbname, login, saml_response + return self.env.cr.dbname, login, saml_response def check_credentials(self, cr, uid, token): """token can be a password if the user has used the normal form... @@ -188,4 +169,5 @@ and the interesting code is inside the except clause """ token_osv = self.pool.get('auth_saml.token') + try: @@ -191,5 +173,10 @@ try: - super(res_users, self).check_credentials(cr, uid, token) + baseuser.check_credentials( + self, + cr, + uid, + token + ) except (openerp.exceptions.AccessDenied, passlib.exc.PasswordSizeError): # since normal auth did not succeed we now try to find if the user