# HG changeset patch # User Florent Aide <florent.aide@gmail.com> # Date 1455123438 -3600 # Wed Feb 10 17:57:18 2016 +0100 # Branch odoo8 # Node ID d67d84c6ebc084d85a777e17a4431b1c1a3b78ec # Parent 010cf843cdd99a559a100571396c36af096541af implement real attribute matching instead of using subject.nameId.content for everything diff --git a/model/auth_saml.py b/model/auth_saml.py --- a/model/auth_saml.py +++ b/model/auth_saml.py @@ -33,6 +33,16 @@ return lasso.Login(server) @api.multi + def _get_matching_attr_for_provider(self): + """internal helper to fetch the matching attribute for this SAML + provider. Returns a unicode object. + """ + + self.ensure_one() + + return self.matching_attribute + + @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 @@ -58,6 +68,11 @@ sp_pkey = fields.Text( 'Private key of our service provider (this openerpserver)' ) + matching_attribute = fields.Text( + string='Matching Attribute', + default='subject.nameId', + required=True, + ), enabled = fields.Boolean('Enabled', default=False) sequence = fields.Integer('Sequence') css_class = fields.Char('CSS Class') diff --git a/model/res_users.py b/model/res_users.py --- a/model/res_users.py +++ b/model/res_users.py @@ -72,6 +72,7 @@ # we are not yet logged in, so the userid cannot have access to the # fields we need yet login = p.sudo()._get_lasso_for_provider() + matching_attribute = p._get_matching_attr_for_provider() try: login.processAuthnResponseMsg(token) @@ -79,17 +80,76 @@ raise Exception('Lasso Profile cannot verify signature') except lasso.ProfileStatusNotSuccessError: raise Exception('Profile Status Not Success Error') - except lasso.Error, e: + except lasso.Error as e: raise Exception(repr(e)) try: login.acceptSso() - except lasso.Error: - raise Exception('Invalid assertion') + except lasso.Error as error: + raise Exception( + 'Invalid assertion : %s' % lasso.strError(error[0]) + ) + + attrs = {} - # TODO use a real token validation from LASSO - # TODO push into the validation result a real UPN - return {'user_id': login.assertion.subject.nameId.content} + for att_statement in login.assertion.attributeStatement: + for attribute in att_statement.attribute: + name = None + lformat = lasso.SAML2_ATTRIBUTE_NAME_FORMAT_BASIC + nickname = None + try: + name = attribute.name.decode('ascii') + except Exception as e: + _logger.warning('sso_after_response: error decoding name of \ + attribute %s' % attribute.dump()) + else: + try: + if attribute.nameFormat: + lformat = attribute.nameFormat.decode('ascii') + if attribute.friendlyName: + nickname = attribute.friendlyName + except Exception as e: + message = 'sso_after_response: name or format of an \ + attribute failed to decode as ascii: %s due to %s' + _logger.warning(message % (attribute.dump(), str(e))) + try: + if name: + if lformat: + if nickname: + key = (name, lformat, nickname) + else: + key = (name, lformat) + else: + key = name + attrs[key] = list() + for value in attribute.attributeValue: + content = [a.exportToXml() for a in value.any] + content = ''.join(content) + attrs[key].append(content.decode('utf8')) + except Exception as e: + message = 'sso_after_response: value of an \ + attribute failed to decode as ascii: %s due to %s' + _logger.warning(message % (attribute.dump(), str(e))) + + matching_value = None + for k in attrs: + if isinstance(k, tuple) and k[0] == matching_attribute: + matching_value = attrs[k][0] + break + + if not matching_value and matching_attribute == "subject.nameId": + matching_value = login.assertion.subject.nameId.content + + elif not matching_value and matching_attribute != "subject.nameId": + raise Exception( + "Matching attribute %s not found in user attrs: %s" % ( + matching_attribute, + attrs, + ) + ) + + validation = {'user_id': matching_value} + return validation @api.multi def _auth_saml_signin(self, provider, validation, saml_response): diff --git a/views/auth_saml.xml b/views/auth_saml.xml --- a/views/auth_saml.xml +++ b/views/auth_saml.xml @@ -43,6 +43,7 @@ <field name="name" /> <field name="enabled" /> <field name="body" /> + <field name="matching_attribute" /> </group> <group> <field name="idp_metadata" />