Skip to content

Commit 518f112

Browse files
authored
Merge pull request #17 from AzureAD/full-support-for-verify-and-proxies
Full support for verify and proxies
2 parents 43999a6 + b4e482b commit 518f112

File tree

3 files changed

+39
-18
lines changed

3 files changed

+39
-18
lines changed

msal/application.py

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -92,14 +92,14 @@ def __init__(
9292
"""
9393
self.client_id = client_id
9494
self.client_credential = client_credential
95+
self.verify = verify
96+
self.proxies = proxies
97+
self.timeout = timeout
9598
self.authority = Authority(
9699
authority or "https://login.microsoftonline.com/common/",
97-
validate_authority)
100+
validate_authority, verify=verify, proxies=proxies, timeout=timeout)
98101
# Here the self.authority is not the same type as authority in input
99102
self.token_cache = token_cache or TokenCache()
100-
self.verify = verify
101-
self.proxies = proxies
102-
self.timeout = timeout
103103
self.client = self._build_client(client_credential, self.authority)
104104

105105
def _build_client(self, client_credential, authority):
@@ -166,7 +166,10 @@ def get_authorization_request_url(
166166
(Under the hood, we simply merge scope and additional_scope before
167167
sending them on the wire.)
168168
"""
169-
the_authority = Authority(authority) if authority else self.authority
169+
the_authority = Authority(
170+
authority,
171+
verify=self.verify, proxies=self.proxies, timeout=self.timeout,
172+
) if authority else self.authority
170173
client = Client(
171174
{"authorization_endpoint": the_authority.authorization_endpoint},
172175
self.client_id)
@@ -272,7 +275,10 @@ def acquire_token_silent(
272275
- None when cache lookup does not yield anything.
273276
"""
274277
assert isinstance(scopes, list), "Invalid parameter type"
275-
the_authority = Authority(authority) if authority else self.authority
278+
the_authority = Authority(
279+
authority,
280+
verify=self.verify, proxies=self.proxies, timeout=self.timeout,
281+
) if authority else self.authority
276282

277283
if not force_refresh:
278284
matches = self.token_cache.find(
@@ -383,17 +389,20 @@ def acquire_token_by_username_password(
383389

384390
def _acquire_token_by_username_password_federated(
385391
self, user_realm_result, username, password, scopes=None, **kwargs):
392+
verify = kwargs.pop("verify", self.verify)
393+
proxies = kwargs.pop("proxies", self.proxies)
386394
wstrust_endpoint = {}
387395
if user_realm_result.get("federation_metadata_url"):
388396
wstrust_endpoint = mex_send_request(
389-
user_realm_result["federation_metadata_url"])
397+
user_realm_result["federation_metadata_url"],
398+
verify=verify, proxies=proxies)
390399
logger.debug("wstrust_endpoint = %s", wstrust_endpoint)
391400
wstrust_result = wst_send_request(
392401
username, password, user_realm_result.get("cloud_audience_urn"),
393402
wstrust_endpoint.get("address",
394403
# Fallback to an AAD supplied endpoint
395404
user_realm_result.get("federation_active_auth_url")),
396-
wstrust_endpoint.get("action"), **kwargs)
405+
wstrust_endpoint.get("action"), verify=verify, proxies=proxies)
397406
if not ("token" in wstrust_result and "type" in wstrust_result):
398407
raise RuntimeError("Unsuccessful RSTR. %s" % wstrust_result)
399408
grant_type = {

msal/authority.py

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ class Authority(object):
2121
Once constructed, it contains members named "*_endpoint" for this instance.
2222
TODO: It will also cache the previously-validated authority instances.
2323
"""
24-
def __init__(self, authority_url, validate_authority=True):
24+
def __init__(self, authority_url, validate_authority=True,
25+
verify=True, proxies=None, timeout=None,
26+
):
2527
"""Creates an authority instance, and also validates it.
2628
2729
:param validate_authority:
@@ -30,24 +32,31 @@ def __init__(self, authority_url, validate_authority=True):
3032
This parameter only controls whether an instance discovery will be
3133
performed.
3234
"""
35+
self.verify = verify
36+
self.proxies = proxies
37+
self.timeout = timeout
3338
canonicalized, self.instance, tenant = canonicalize(authority_url)
3439
tenant_discovery_endpoint = ( # Hard code a V2 pattern as default value
3540
'https://{}/{}/v2.0/.well-known/openid-configuration'
3641
.format(WORLD_WIDE, tenant))
3742
if validate_authority and self.instance not in WELL_KNOWN_AUTHORITY_HOSTS:
3843
tenant_discovery_endpoint = instance_discovery(
39-
canonicalized + "/oauth2/v2.0/authorize")
40-
openid_config = tenant_discovery(tenant_discovery_endpoint)
44+
canonicalized + "/oauth2/v2.0/authorize",
45+
verify=verify, proxies=proxies, timeout=timeout)
46+
openid_config = tenant_discovery(
47+
tenant_discovery_endpoint,
48+
verify=verify, proxies=proxies, timeout=timeout)
4149
self.authorization_endpoint = openid_config['authorization_endpoint']
4250
self.token_endpoint = openid_config['token_endpoint']
4351
_, _, self.tenant = canonicalize(self.token_endpoint) # Usually a GUID
4452
self.is_adfs = self.tenant.lower() == 'adfs'
4553

46-
def user_realm_discovery(self, username, **kwargs):
54+
def user_realm_discovery(self, username):
4755
resp = requests.get(
4856
"https://{netloc}/common/userrealm/{username}?api-version=1.0".format(
4957
netloc=self.instance, username=username),
50-
headers={'Accept':'application/json'}, **kwargs)
58+
headers={'Accept':'application/json'},
59+
verify=self.verify, proxies=self.proxies, timeout=self.timeout)
5160
resp.raise_for_status()
5261
return resp.json()
5362
# It will typically contain "ver", "account_type",
@@ -64,17 +73,20 @@ def canonicalize(url):
6473
"https://login.microsoftonline.com/<tenant_name>" % url)
6574
return match_object.group(0), match_object.group(1), match_object.group(2)
6675

67-
def instance_discovery(url, response=None): # Returns tenant discovery endpoint
76+
def instance_discovery(url, response=None, **kwargs):
77+
# Returns tenant discovery endpoint
6878
resp = requests.get( # Note: This URL seemingly returns V1 endpoint only
6979
'https://{}/common/discovery/instance'.format(WORLD_WIDE),
70-
params={'authorization_endpoint': url, 'api-version': '1.0'})
80+
params={'authorization_endpoint': url, 'api-version': '1.0'},
81+
**kwargs)
7182
payload = response or resp.json()
7283
if 'tenant_discovery_endpoint' not in payload:
7384
raise MsalServiceError(status_code=resp.status_code, **payload)
7485
return payload['tenant_discovery_endpoint']
7586

76-
def tenant_discovery(tenant_discovery_endpoint): # Returns Openid Configuration
77-
resp = requests.get(tenant_discovery_endpoint)
87+
def tenant_discovery(tenant_discovery_endpoint, **kwargs):
88+
# Returns Openid Configuration
89+
resp = requests.get(tenant_discovery_endpoint, **kwargs)
7890
payload = resp.json()
7991
if 'authorization_endpoint' in payload and 'token_endpoint' in payload:
8092
return payload

tests/test_authority.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,6 @@ def test_instance_discovery_with_unknown_instance(self):
9494
def test_instance_discovery_with_mocked_response(self):
9595
mock_response = {'tenant_discovery_endpoint': 'http://a.com/t/openid'}
9696
endpoint = instance_discovery(
97-
"https://login.microsoftonline.in/tenant.com", mock_response)
97+
"https://login.microsoftonline.in/tenant.com", response=mock_response)
9898
self.assertEqual(endpoint, mock_response['tenant_discovery_endpoint'])
9999

0 commit comments

Comments
 (0)