Skip to content
Snippets Groups Projects
Commit e0507277b57d authored by Florent Aide's avatar Florent Aide
Browse files

implement real attribute matching instead of using subject.nameId.content for everything

parent 9b47f2baccae
No related branches found
Tags TAG_3.2
No related merge requests found
...@@ -29,6 +29,15 @@ ...@@ -29,6 +29,15 @@
) )
return lasso.Login(server) return lasso.Login(server)
def _get_matching_attr_for_provider(
self, cr, uid, provider_id, context=None
):
"""internal helper to fetch the matching attribute for this SAML
provider. Returns a unicode object.
"""
provider = self.browse(cr, uid, provider_id, context=context)
return provider.matching_attribute
def _get_auth_request(self, cr, uid, id_, state, context=None): def _get_auth_request(self, cr, uid, id_, state, context=None):
"""build an authentication request and give it back to our client """build an authentication request and give it back to our client
WARNING: this method cannot be used for multiple ids WARNING: this method cannot be used for multiple ids
...@@ -55,6 +64,7 @@ ...@@ -55,6 +64,7 @@
'sp_pkey': fields.text( 'sp_pkey': fields.text(
'Private key of our service provider (this openerpserver)' 'Private key of our service provider (this openerpserver)'
), ),
'matching_attribute': fields.text('Matching Attribute', required=True),
'enabled': fields.boolean('Enabled'), 'enabled': fields.boolean('Enabled'),
'css_class': fields.char('CSS class'), 'css_class': fields.char('CSS class'),
'body': fields.char( 'body': fields.char(
...@@ -66,6 +76,7 @@ ...@@ -66,6 +76,7 @@
_defaults = { _defaults = {
'enabled': False, 'enabled': False,
'matching_attribute': "subject.nameId",
'css_class': 'zocial saml', 'css_class': 'zocial saml',
'body': 'Authentic', 'body': 'Authentic',
} }
...@@ -63,8 +63,9 @@ ...@@ -63,8 +63,9 @@
p = self.pool.get('auth.saml.provider') p = self.pool.get('auth.saml.provider')
login = p._get_lasso_for_provider(cr, uid, provider, context=context) login = p._get_lasso_for_provider(cr, uid, provider, context=context)
matching_attribute = p._get_matching_attr_for_provider(cr, uid, provider, context=context)
try: try:
login.processAuthnResponseMsg(token) login.processAuthnResponseMsg(token)
except (lasso.DsError, lasso.ProfileCannotVerifySignatureError): except (lasso.DsError, lasso.ProfileCannotVerifySignatureError):
raise Exception('Lasso Profile cannot verify signature') raise Exception('Lasso Profile cannot verify signature')
...@@ -66,10 +67,10 @@ ...@@ -66,10 +67,10 @@
try: try:
login.processAuthnResponseMsg(token) login.processAuthnResponseMsg(token)
except (lasso.DsError, lasso.ProfileCannotVerifySignatureError): except (lasso.DsError, lasso.ProfileCannotVerifySignatureError):
raise Exception('Lasso Profile cannot verify signature') raise Exception('Lasso Profile cannot verify signature')
except lasso.Error, e: except lasso.Error as e:
raise Exception(repr(e)) raise Exception(repr(e))
try: try:
login.acceptSso() login.acceptSso()
...@@ -72,7 +73,9 @@ ...@@ -72,7 +73,9 @@
raise Exception(repr(e)) raise Exception(repr(e))
try: try:
login.acceptSso() login.acceptSso()
except lasso.Error: except lasso.Error as error:
raise Exception('Invalid assertion') raise Exception(
'Invalid assertion : %s' % lasso.strError(error[0])
)
...@@ -78,5 +81,3 @@ ...@@ -78,5 +81,3 @@
# TODO use a real token validation from LASSO attrs = {}
# TODO push into the validation result a real UPN
validation = {'user_id': login.assertion.subject.nameId.content}
...@@ -82,7 +83,40 @@ ...@@ -82,7 +83,40 @@
""" for att_statement in login.assertion.attributeStatement:
if p.data_endpoint: for attribute in att_statement.attribute:
data = self._auth_oauth_rpc(cr, uid, p.data_endpoint, access_token) name = None
validation.update(data) 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)))
...@@ -88,4 +122,22 @@ ...@@ -88,4 +122,22 @@
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 return validation
def _auth_saml_signin( def _auth_saml_signin(
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
<field name="name" /> <field name="name" />
<field name="enabled" /> <field name="enabled" />
<field name="body" /> <field name="body" />
<field name="matching_attribute" />
</group> </group>
<group> <group>
<field name="idp_metadata" /> <field name="idp_metadata" />
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment