Skip to content

Commit

Permalink
Validate in SAMLResponse the Audience
Browse files Browse the repository at this point in the history
  • Loading branch information
pitbulk committed Jun 26, 2014
1 parent eabe609 commit 7198d9e
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 23 deletions.
1 change: 1 addition & 0 deletions example.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ def do_POST(self):
res = Response(
query['SAMLResponse'].pop(),
self.settings['idp_cert_fingerprint'],
issuer=self.settings['issuer']
)
valid = res.is_valid()
name_id = res.name_id
Expand Down
61 changes: 38 additions & 23 deletions onelogin/saml/Response.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,8 @@ def __init__(self, msg):
def __str__(self):
return '%s: %s' % (self.__doc__, self._msg)


class Response(object):
def __init__(self, response, signature, _base64=None, _etree=None):
def __init__(self, response, signature, _base64=None, _etree=None, issuer=None):
"""
Extract information from an samlp:Response
Arguments:
Expand All @@ -55,6 +54,7 @@ def __init__(self, response, signature, _base64=None, _etree=None):
decoded_response = _base64.b64decode(response)
self._document = _etree.fromstring(decoded_response)
self._signature = signature
self._issuer = issuer

def _parse_datetime(self, dt):
try:
Expand Down Expand Up @@ -110,29 +110,44 @@ def is_valid(self, _clock=None, _verifier=None):

now = _clock()

not_before = None
not_on_or_after = None
foundCondition = False
fountConditionAndAudience = False

for condition in conditions:
not_on_or_after = condition.attrib.get('NotOnOrAfter', None)

not_before = condition.attrib.get('NotBefore', None)

if not_before is None:
#notbefore condition is not mandatory. If it is not specified, use yesterday as not_before condition
not_before = (now - timedelta(1, 0, 0)).strftime('%Y-%m-%dT%H:%M:%SZ')
if not_on_or_after is None:
raise ResponseConditionError('Did not find NotOnOrAfter condition')

not_before = self._parse_datetime(not_before)
not_on_or_after = self._parse_datetime(not_on_or_after)

if now < not_before:
raise ResponseValidationError(
'Current time is earlier than NotBefore condition'
)
if now >= not_on_or_after:
raise ResponseValidationError(
'Current time is on or after NotOnOrAfter condition'
)
not_on_or_after = condition.attrib.get('NotOnOrAfter', None)

if not_before is None:
#notbefore condition is not mandatory. If it is not specified, use yesterday as not_before condition
not_before = (now - timedelta(0, 5, 0)).strftime('%Y-%m-%dT%H:%M:%SZ')
if not_on_or_after is None:
continue

not_before = self._parse_datetime(not_before)
not_on_or_after = self._parse_datetime(not_on_or_after)

if now < not_before:
continue
if now >= not_on_or_after:
continue
foundCondition = True

if self._issuer:
audiences = condition.xpath(
'/samlp:Response/saml:Assertion/saml:Conditions/saml:AudienceRestriction/saml:Audience',
namespaces=namespaces,
)
audienceValues = []
for audience in audiences:
audienceValues.append(audience.text)
if self._issuer in audienceValues:
fountConditionAndAudience = True

if not foundCondition:
raise ResponseConditionError('Timmig issue')
if foundCondition and not fountConditionAndAudience:
raise ResponseConditionError('Not valid Audience')

return _verifier(
self._document,
Expand Down

0 comments on commit 7198d9e

Please sign in to comment.