Skip to content

Commit 7198d9e

Browse files
committed
Validate in SAMLResponse the Audience
1 parent eabe609 commit 7198d9e

File tree

2 files changed

+39
-23
lines changed

2 files changed

+39
-23
lines changed

example.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ def do_POST(self):
7979
res = Response(
8080
query['SAMLResponse'].pop(),
8181
self.settings['idp_cert_fingerprint'],
82+
issuer=self.settings['issuer']
8283
)
8384
valid = res.is_valid()
8485
name_id = res.name_id

onelogin/saml/Response.py

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,8 @@ def __init__(self, msg):
3838
def __str__(self):
3939
return '%s: %s' % (self.__doc__, self._msg)
4040

41-
4241
class Response(object):
43-
def __init__(self, response, signature, _base64=None, _etree=None):
42+
def __init__(self, response, signature, _base64=None, _etree=None, issuer=None):
4443
"""
4544
Extract information from an samlp:Response
4645
Arguments:
@@ -55,6 +54,7 @@ def __init__(self, response, signature, _base64=None, _etree=None):
5554
decoded_response = _base64.b64decode(response)
5655
self._document = _etree.fromstring(decoded_response)
5756
self._signature = signature
57+
self._issuer = issuer
5858

5959
def _parse_datetime(self, dt):
6060
try:
@@ -110,29 +110,44 @@ def is_valid(self, _clock=None, _verifier=None):
110110

111111
now = _clock()
112112

113-
not_before = None
114-
not_on_or_after = None
113+
foundCondition = False
114+
fountConditionAndAudience = False
115+
115116
for condition in conditions:
116-
not_on_or_after = condition.attrib.get('NotOnOrAfter', None)
117+
117118
not_before = condition.attrib.get('NotBefore', None)
118-
119-
if not_before is None:
120-
#notbefore condition is not mandatory. If it is not specified, use yesterday as not_before condition
121-
not_before = (now - timedelta(1, 0, 0)).strftime('%Y-%m-%dT%H:%M:%SZ')
122-
if not_on_or_after is None:
123-
raise ResponseConditionError('Did not find NotOnOrAfter condition')
124-
125-
not_before = self._parse_datetime(not_before)
126-
not_on_or_after = self._parse_datetime(not_on_or_after)
127-
128-
if now < not_before:
129-
raise ResponseValidationError(
130-
'Current time is earlier than NotBefore condition'
131-
)
132-
if now >= not_on_or_after:
133-
raise ResponseValidationError(
134-
'Current time is on or after NotOnOrAfter condition'
135-
)
119+
not_on_or_after = condition.attrib.get('NotOnOrAfter', None)
120+
121+
if not_before is None:
122+
#notbefore condition is not mandatory. If it is not specified, use yesterday as not_before condition
123+
not_before = (now - timedelta(0, 5, 0)).strftime('%Y-%m-%dT%H:%M:%SZ')
124+
if not_on_or_after is None:
125+
continue
126+
127+
not_before = self._parse_datetime(not_before)
128+
not_on_or_after = self._parse_datetime(not_on_or_after)
129+
130+
if now < not_before:
131+
continue
132+
if now >= not_on_or_after:
133+
continue
134+
foundCondition = True
135+
136+
if self._issuer:
137+
audiences = condition.xpath(
138+
'/samlp:Response/saml:Assertion/saml:Conditions/saml:AudienceRestriction/saml:Audience',
139+
namespaces=namespaces,
140+
)
141+
audienceValues = []
142+
for audience in audiences:
143+
audienceValues.append(audience.text)
144+
if self._issuer in audienceValues:
145+
fountConditionAndAudience = True
146+
147+
if not foundCondition:
148+
raise ResponseConditionError('Timmig issue')
149+
if foundCondition and not fountConditionAndAudience:
150+
raise ResponseConditionError('Not valid Audience')
136151

137152
return _verifier(
138153
self._document,

0 commit comments

Comments
 (0)