Skip to content

Commit

Permalink
Improve get_metadata method from Parser, allowing to set timeouts and…
Browse files Browse the repository at this point in the history
… headers
  • Loading branch information
pitbulk committed Oct 9, 2023
1 parent ffc4f0b commit 6663bef
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 8 deletions.
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,7 @@ The method above requires a little extra work to manually specify attributes abo

There's an easier method -- use a metadata exchange. Metadata is just an XML file that defines the capabilities of both the IdP and the SP application. It also contains the X.509 public key certificates which add to the trusted relationship. The IdP administrator can also configure custom settings for an SP based on the metadata.

Using ````parse_remote```` IdP metadata can be obtained and added to the settings withouth further ado.
Using ````parse_remote```` IdP metadata can be obtained and added to the settings without further ado.

But take in mind that the OneLogin_Saml2_IdPMetadataParser class does not validate in any way the URL that is introduced in order to be parsed.

Expand All @@ -598,9 +598,15 @@ Usually the same administrator that handles the Service Provider also sets the U
But there are other scenarios, like a SAAS app where the administrator of the app delegates this functionality to other users. In this case, extra precaution should be taken in order to validate such URL inputs and avoid attacks like SSRF.


``
```
idp_data = OneLogin_Saml2_IdPMetadataParser.parse_remote('https://example.com/auth/saml2/idp/metadata')
``
```

You can specify a timeout in seconds for metadata retrieval, if not it is not guaranteed that the request will complete

```
idp_data = OneLogin_Saml2_IdPMetadataParser.parse_remote('https://example.com/auth/saml2/idp/metadata', timeout=5)
```

If the Metadata contains several entities, the relevant ``EntityDescriptor`` can be specified when retrieving the settings from the ``IdpMetadataParser`` by its ``EntityId`` value:
```
Expand Down
22 changes: 17 additions & 5 deletions src/onelogin/saml2/idp_metadata_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class OneLogin_Saml2_IdPMetadataParser(object):
"""

@staticmethod
def get_metadata(url, validate_cert=True):
def get_metadata(url, validate_cert=True, timeout=None, headers=None):
"""
Gets the metadata XML from the provided URL
Expand All @@ -37,17 +37,26 @@ def get_metadata(url, validate_cert=True):
:param validate_cert: If the url uses https schema, that flag enables or not the verification of the associated certificate.
:type validate_cert: bool
:param timeout: Timeout in seconds to wait for metadata response
:type timeout: int
:param headers: Extra headers to send in the request
:type headers: dict
:returns: metadata XML
:rtype: string
"""
valid = False

request = urllib2.Request(url, headers=headers or {})

if validate_cert:
response = urllib2.urlopen(url)
response = urllib2.urlopen(request, timeout=timeout)
else:
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
response = urllib2.urlopen(url, context=ctx)
response = urllib2.urlopen(request, context=ctx, timeout=timeout)
xml = response.read()

if xml:
Expand All @@ -65,7 +74,7 @@ def get_metadata(url, validate_cert=True):
return xml

@staticmethod
def parse_remote(url, validate_cert=True, entity_id=None, **kwargs):
def parse_remote(url, validate_cert=True, entity_id=None, timeout=None, **kwargs):
"""
Gets the metadata XML from the provided URL and parse it, returning a dict with extracted data
Expand All @@ -79,10 +88,13 @@ def parse_remote(url, validate_cert=True, entity_id=None, **kwargs):
that contains multiple EntityDescriptor.
:type entity_id: string
:param timeout: Timeout in seconds to wait for metadata response
:type timeout: int
:returns: settings dict with extracted data
:rtype: dict
"""
idp_metadata = OneLogin_Saml2_IdPMetadataParser.get_metadata(url, validate_cert)
idp_metadata = OneLogin_Saml2_IdPMetadataParser.get_metadata(url, validate_cert, timeout, headers=kwargs.pop('headers', None))
return OneLogin_Saml2_IdPMetadataParser.parse(idp_metadata, entity_id=entity_id, **kwargs)

@staticmethod
Expand Down

0 comments on commit 6663bef

Please sign in to comment.