Skip to content

Commit d1bfaeb

Browse files
Issue #364: Some urls come with 403 response (#366)
* Issue #364: Some urls come with 403 response python3-saml urllib dependency responds with 403 status to urls with default Python user-agent
1 parent 888c8bc commit d1bfaeb

File tree

2 files changed

+23
-4
lines changed

2 files changed

+23
-4
lines changed

src/onelogin/saml2/idp_metadata_parser.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class OneLogin_Saml2_IdPMetadataParser(object):
2727
"""
2828

2929
@classmethod
30-
def get_metadata(cls, url, validate_cert=True, timeout=None):
30+
def get_metadata(cls, url, validate_cert=True, timeout=None, headers=None):
3131
"""
3232
Gets the metadata XML from the provided URL
3333
:param url: Url where the XML of the Identity Provider Metadata is published.
@@ -38,19 +38,23 @@ def get_metadata(cls, url, validate_cert=True, timeout=None):
3838
3939
:param timeout: Timeout in seconds to wait for metadata response
4040
:type timeout: int
41+
:param headers: Extra headers to send in the request
42+
:type headers: dict
4143
4244
:returns: metadata XML
4345
:rtype: string
4446
"""
4547
valid = False
4648

49+
request = urllib2.Request(url, headers=headers or {})
50+
4751
if validate_cert:
48-
response = urllib2.urlopen(url, timeout=timeout)
52+
response = urllib2.urlopen(request, timeout=timeout)
4953
else:
5054
ctx = ssl.create_default_context()
5155
ctx.check_hostname = False
5256
ctx.verify_mode = ssl.CERT_NONE
53-
response = urllib2.urlopen(url, context=ctx, timeout=timeout)
57+
response = urllib2.urlopen(request, context=ctx, timeout=timeout)
5458
xml = response.read()
5559

5660
if xml:
@@ -87,7 +91,7 @@ def parse_remote(cls, url, validate_cert=True, entity_id=None, timeout=None, **k
8791
:returns: settings dict with extracted data
8892
:rtype: dict
8993
"""
90-
idp_metadata = cls.get_metadata(url, validate_cert, timeout)
94+
idp_metadata = cls.get_metadata(url, validate_cert, timeout, headers=kwargs.pop('headers', None))
9195
return cls.parse(idp_metadata, entity_id=entity_id, **kwargs)
9296

9397
@classmethod

tests/src/OneLogin/saml2_tests/idp_metadata_parser_test.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ def testGetMetadata(self):
5454
except URLError:
5555
pass
5656

57+
def testGetMetadataWithHeaders(self):
58+
data = OneLogin_Saml2_IdPMetadataParser.get_metadata('https://samltest.id/saml/providers',
59+
headers={'User-Agent': 'Mozilla/5.0'})
60+
self.assertIsNotNone(data)
61+
self.assertIn(b'entityID=', data)
62+
5763
def testParseRemote(self):
5864
"""
5965
Tests the parse_remote method of the OneLogin_Saml2_IdPMetadataParser
@@ -86,6 +92,15 @@ def testParseRemote(self):
8692
expected_settings = json.loads(expected_settings_json)
8793
self.assertEqual(expected_settings, data)
8894

95+
def testParseRemoteWithHeaders(self):
96+
"""
97+
Tests the parse_remote method passing headers of the OneLogin_Saml2_IdPMetadataParser
98+
"""
99+
data = OneLogin_Saml2_IdPMetadataParser.parse_remote('https://samltest.id/saml/providers')
100+
self.assertEqual(data['idp']['entityId'], 'https://samltest.id/saml/idp')
101+
self.assertIsNotNone(data['idp']['singleSignOnService']['url'])
102+
self.assertIsNotNone(data['idp']['x509certMulti'])
103+
89104
def testParse(self):
90105
"""
91106
Tests the parse method of the OneLogin_Saml2_IdPMetadataParser

0 commit comments

Comments
 (0)