diff --git a/msal/application.py b/msal/application.py index 5d1406af..a06df303 100644 --- a/msal/application.py +++ b/msal/application.py @@ -11,8 +11,6 @@ from threading import Lock import os -import requests - from .oauth2cli import Client, JwtAssertionCreator from .oauth2cli.oidc import decode_part from .authority import Authority @@ -425,6 +423,8 @@ def __init__( if http_client: self.http_client = http_client else: + import requests # Lazy load + self.http_client = requests.Session() self.http_client.verify = verify self.http_client.proxies = proxies diff --git a/msal/authority.py b/msal/authority.py index 145ce3d9..ecf6b777 100644 --- a/msal/authority.py +++ b/msal/authority.py @@ -5,11 +5,6 @@ from urlparse import urlparse import logging -# Historically some customers patched this module-wide requests instance. -# We keep it here for now. They will be removed in next major release. -import requests -import requests as _requests - from .exceptions import MsalServiceError @@ -59,9 +54,10 @@ class Authority(object): _domains_without_user_realm_discovery = set([]) @property - def http_client(self): # Obsolete. We will remove this in next major release. - # A workaround: if module-wide requests is patched, we honor it. - return self._http_client if requests is _requests else requests + def http_client(self): # Obsolete. We will remove this eventually + warnings.warn( + "authority.http_client might be removed in MSAL Python 1.21+", DeprecationWarning) + return self._http_client def __init__(self, authority_url, http_client, validate_authority=True): """Creates an authority instance, and also validates it. @@ -84,7 +80,7 @@ def __init__(self, authority_url, http_client, validate_authority=True): payload = instance_discovery( "https://{}{}/oauth2/v2.0/authorize".format( self.instance, authority.path), - self.http_client) + self._http_client) if payload.get("error") == "invalid_instance": raise ValueError( "invalid_instance: " @@ -104,7 +100,7 @@ def __init__(self, authority_url, http_client, validate_authority=True): try: openid_config = tenant_discovery( tenant_discovery_endpoint, - self.http_client) + self._http_client) except ValueError: raise ValueError( "Unable to get authority configuration for {}. " @@ -124,7 +120,7 @@ def user_realm_discovery(self, username, correlation_id=None, response=None): # "federation_protocol", "cloud_audience_urn", # "federation_metadata_url", "federation_active_auth_url", etc. if self.instance not in self.__class__._domains_without_user_realm_discovery: - resp = response or self.http_client.get( + resp = response or self._http_client.get( "https://{netloc}/common/userrealm/{username}?api-version=1.0".format( netloc=self.instance, username=username), headers={'Accept': 'application/json', diff --git a/msal/oauth2cli/assertion.py b/msal/oauth2cli/assertion.py index 0cf58799..855bd16b 100644 --- a/msal/oauth2cli/assertion.py +++ b/msal/oauth2cli/assertion.py @@ -4,8 +4,6 @@ import uuid import logging -import jwt - logger = logging.getLogger(__name__) @@ -99,6 +97,7 @@ def create_normal_assertion( Parameters are defined in https://tools.ietf.org/html/rfc7523#section-3 Key-value pairs in additional_claims will be added into payload as-is. """ + import jwt # Lazy loading now = time.time() payload = { 'aud': audience, diff --git a/msal/oauth2cli/oauth2.py b/msal/oauth2cli/oauth2.py index e092b3dd..54708004 100644 --- a/msal/oauth2cli/oauth2.py +++ b/msal/oauth2cli/oauth2.py @@ -17,8 +17,6 @@ import string import hashlib -import requests - from .authcode import AuthCodeReceiver as _AuthCodeReceiver try: @@ -159,6 +157,8 @@ def __init__( "when http_client is in use") self._http_client = http_client else: + import requests # Lazy loading + self._http_client = requests.Session() self._http_client.verify = True if verify is None else verify self._http_client.proxies = proxies diff --git a/tests/test_authority_patch.py b/tests/test_authority_patch.py deleted file mode 100644 index 1feca62d..00000000 --- a/tests/test_authority_patch.py +++ /dev/null @@ -1,32 +0,0 @@ -import unittest - -import msal -from tests.http_client import MinimalHttpClient - - -class DummyHttpClient(object): - def get(self, url, **kwargs): - raise RuntimeError("just for testing purpose") - - -class TestAuthorityHonorsPatchedRequests(unittest.TestCase): - """This is only a workaround for an undocumented behavior.""" - def test_authority_honors_a_patched_requests(self): - # First, we test that the original, unmodified authority is working - a = msal.authority.Authority( - "https://login.microsoftonline.com/common", MinimalHttpClient()) - self.assertEqual( - a.authorization_endpoint, - 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize') - - original = msal.authority.requests - try: - # Now we mimic a (discouraged) practice of patching authority.requests - msal.authority.requests = DummyHttpClient() - # msal.authority is expected to honor that patch. - with self.assertRaises(RuntimeError): - a = msal.authority.Authority( - "https://login.microsoftonline.com/common", MinimalHttpClient()) - finally: # Tricky: - # Unpatch is necessary otherwise other test cases would be affected - msal.authority.requests = original