Skip to content

Commit 78033d9

Browse files
✨ [#403] Fetch IDP metadata using requests
Using requests allows us to easily customize the CA_BUNDLE to use when verifying the server certificate, instead of having to disable SSL certificate verification alltogether.
1 parent fd02e44 commit 78033d9

File tree

3 files changed

+18
-25
lines changed

3 files changed

+18
-25
lines changed

pyproject.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ dependencies = [
3535
"lxml>=4.6.5,!=4.7.0",
3636
"xmlsec>=1.3.9",
3737
"isodate>=0.6.1",
38+
"requests",
3839
]
3940
requires-python = ">=3.7"
4041

@@ -119,4 +120,4 @@ ignore_errors = true
119120

120121

121122
[tool.coverage.html]
122-
directory = "coverage_html_report"
123+
directory = "coverage_html_report"

src/onelogin/saml2/idp_metadata_parser.py

+11-14
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,7 @@
77

88
from copy import deepcopy
99

10-
try:
11-
import urllib.request as urllib2
12-
except ImportError:
13-
import urllib2
10+
import requests
1411

1512
import ssl
1613

@@ -30,6 +27,13 @@ class OneLogin_Saml2_IdPMetadataParser(object):
3027
def get_metadata(cls, url, validate_cert=True, timeout=None, headers=None):
3128
"""
3229
Gets the metadata XML from the provided URL
30+
31+
The metadata is retrieved with the ``requests`` library. If you need to support
32+
server certificates that are not readily available in the trust store, use the
33+
``REQUESTS_CA_BUNDLE`` environment variable. See the
34+
`advanced documentation <https://requests.readthedocs.io/en/latest/user/advanced/>`_
35+
for more information.
36+
3337
:param url: Url where the XML of the Identity Provider Metadata is published.
3438
:type url: string
3539
@@ -46,16 +50,9 @@ def get_metadata(cls, url, validate_cert=True, timeout=None, headers=None):
4650
"""
4751
valid = False
4852

49-
request = urllib2.Request(url, headers=headers or {})
50-
51-
if validate_cert:
52-
response = urllib2.urlopen(request, timeout=timeout)
53-
else:
54-
ctx = ssl.create_default_context()
55-
ctx.check_hostname = False
56-
ctx.verify_mode = ssl.CERT_NONE
57-
response = urllib2.urlopen(request, context=ctx, timeout=timeout)
58-
xml = response.read()
53+
response = requests.get(url, headers=headers, verify=validate_cert, timeout=timeout)
54+
response.raise_for_status()
55+
xml = response.content
5956

6057
if xml:
6158
try:

tests/src/OneLogin/saml2_tests/idp_metadata_parser_test.py

+5-10
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,10 @@
11
# -*- coding: utf-8 -*-
22

3-
4-
try:
5-
from urllib.error import URLError
6-
except ImportError:
7-
from urllib2 import URLError
8-
93
from copy import deepcopy
104
import json
115
from os.path import dirname, join, exists
126
from lxml.etree import XMLSyntaxError
7+
from requests import RequestException
138
import unittest
149

1510
from onelogin.saml2.idp_metadata_parser import OneLogin_Saml2_IdPMetadataParser
@@ -51,7 +46,7 @@ def testGetMetadata(self):
5146
try:
5247
data = OneLogin_Saml2_IdPMetadataParser.get_metadata("https://raw.githubusercontent.com/SAML-Toolkits/python3-saml/master/tests/data/metadata/testshib-providers.xml", validate_cert=False)
5348
self.assertTrue(data is not None and data is not {})
54-
except URLError:
49+
except RequestException:
5550
pass
5651

5752
def testGetMetadataWithHeaders(self):
@@ -70,7 +65,7 @@ def testParseRemote(self):
7065

7166
try:
7267
data = OneLogin_Saml2_IdPMetadataParser.parse_remote("https://raw.githubusercontent.com/SAML-Toolkits/python3-saml/master/tests/data/metadata/testshib-providers.xml", validate_cert=False)
73-
except URLError:
68+
except RequestException:
7469
xml = self.file_contents(join(self.data_path, "metadata", "testshib-providers.xml"))
7570
data = OneLogin_Saml2_IdPMetadataParser.parse(xml)
7671

@@ -162,7 +157,7 @@ def test_parse_testshib_required_binding_sso_redirect(self):
162157
"""
163158
try:
164159
xmldoc = OneLogin_Saml2_IdPMetadataParser.get_metadata("https://idp.testshib.org/idp/shibboleth")
165-
except URLError:
160+
except RequestException:
166161
xmldoc = self.file_contents(join(self.data_path, "metadata", "testshib-providers.xml"))
167162

168163
# Parse, require SSO REDIRECT binding, implicitly.
@@ -196,7 +191,7 @@ def test_parse_testshib_required_binding_sso_post(self):
196191
"""
197192
try:
198193
xmldoc = OneLogin_Saml2_IdPMetadataParser.get_metadata("https://idp.testshib.org/idp/shibboleth")
199-
except URLError:
194+
except RequestException:
200195
xmldoc = self.file_contents(join(self.data_path, "metadata", "testshib-providers.xml"))
201196

202197
# Parse, require POST binding.

0 commit comments

Comments
 (0)