Skip to content
This repository was archived by the owner on Sep 29, 2023. It is now read-only.

Commit bef928d

Browse files
authored
Merge pull request #169 from AzureAD/release-1.1.0
Release 1.1.0
2 parents 139e0a7 + 6d6fbdc commit bef928d

File tree

5 files changed

+52
-21
lines changed

5 files changed

+52
-21
lines changed

adal/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727

2828
# pylint: disable=wrong-import-position
2929

30-
__version__ = '1.0.2'
30+
__version__ = '1.1.0'
3131

3232
import logging
3333

adal/authority.py

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
1-
#------------------------------------------------------------------------------
1+
#------------------------------------------------------------------------------
22
#
3-
# Copyright (c) Microsoft Corporation.
3+
# Copyright (c) Microsoft Corporation.
44
# All rights reserved.
5-
#
5+
#
66
# This code is licensed under the MIT License.
7-
#
7+
#
88
# Permission is hereby granted, free of charge, to any person obtaining a copy
99
# of this software and associated documentation files(the "Software"), to deal
1010
# in the Software without restriction, including without limitation the rights
1111
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
1212
# copies of the Software, and to permit persons to whom the Software is
1313
# furnished to do so, subject to the following conditions :
14-
#
14+
#
1515
# The above copyright notice and this permission notice shall be included in
1616
# all copies or substantial portions of the Software.
17-
#
17+
#
1818
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1919
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2020
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
@@ -62,6 +62,12 @@ def __init__(self, authority_url, validate_authority=True):
6262
def url(self):
6363
return self._url.geturl()
6464

65+
def _whitelisted(self): # testing if self._url.hostname is a dsts whitelisted domain
66+
for domain in AADConstants.WHITELISTED_DOMAINS:
67+
if self._url.hostname.endswith(domain):
68+
return True
69+
return False
70+
6571
def _validate_authority_url(self):
6672

6773
if self._url.scheme != 'https':
@@ -71,7 +77,7 @@ def _validate_authority_url(self):
7177
raise ValueError("The authority url must not have a query string.")
7278

7379
path_parts = [part for part in self._url.path.split('/') if part]
74-
if len(path_parts) > 1:
80+
if (len(path_parts) > 1) and (not self._whitelisted()): #if dsts host, path_parts will be 2
7581
raise ValueError("The authority url must be of the format https://login.microsoftonline.com/your_tenant")
7682
elif len(path_parts) == 1:
7783
self._url = urlparse(self._url.geturl().rstrip('/'))
@@ -89,6 +95,9 @@ def _perform_static_instance_discovery(self):
8995

9096
self._log.debug("Performing static instance discovery")
9197

98+
if self._whitelisted(): # testing if self._url.hostname is a dsts whitelisted domain
99+
self._log.debug("Authority validated via static instance discovery")
100+
return True
92101
try:
93102
AADConstants.WELL_KNOWN_AUTHORITY_HOSTS.index(self._url.hostname)
94103
except ValueError:
@@ -98,16 +107,16 @@ def _perform_static_instance_discovery(self):
98107
return True
99108

100109
def _create_authority_url(self):
101-
return "https://{}/{}{}".format(self._url.hostname,
102-
self._tenant,
110+
return "https://{}/{}{}".format(self._url.hostname,
111+
self._tenant,
103112
AADConstants.AUTHORIZE_ENDPOINT_PATH)
104113

105114
def _create_instance_discovery_endpoint_from_template(self, authority_host):
106115

107116
discovery_endpoint = AADConstants.INSTANCE_DISCOVERY_ENDPOINT_TEMPLATE
108117
discovery_endpoint = discovery_endpoint.replace('{authorize_host}', authority_host)
109-
discovery_endpoint = discovery_endpoint.replace('{authorize_endpoint}',
110-
quote(self._create_authority_url(),
118+
discovery_endpoint = discovery_endpoint.replace('{authorize_endpoint}',
119+
quote(self._create_authority_url(),
111120
safe='~()*!.\''))
112121
return urlparse(discovery_endpoint)
113122

@@ -132,7 +141,7 @@ def _perform_dynamic_instance_discovery(self):
132141
if resp.status_code == 429:
133142
resp.raise_for_status() # Will raise requests.exceptions.HTTPError
134143
if not util.is_http_success(resp.status_code):
135-
return_error_string = u"{} request returned http error: {}".format(operation,
144+
return_error_string = u"{} request returned http error: {}".format(operation,
136145
resp.status_code)
137146
error_response = ""
138147
if resp.text:

adal/constants.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#------------------------------------------------------------------------------
1+
#------------------------------------------------------------------------------
22
#
33
# Copyright (c) Microsoft Corporation.
44
# All rights reserved.
@@ -215,6 +215,15 @@ class AADConstants(object):
215215
'login.microsoftonline.us',
216216
'login.microsoftonline.de',
217217
]
218+
WHITELISTED_DOMAINS = [
219+
# Define dSTS domains whitelist based on its Supported Environments & National Clouds list here
220+
# https://microsoft.sharepoint.com/teams/AzureSecurityCompliance/Security/SitePages/dSTS%20Fundamentals.aspx
221+
'dsts.core.windows.net',
222+
'dsts.core.chinacloudapi.cn',
223+
'dsts.core.cloudapi.de',
224+
'dsts.core.usgovcloudapi.net',
225+
'dsts.core.azure-test.net',
226+
]
218227
INSTANCE_DISCOVERY_ENDPOINT_TEMPLATE = 'https://{authorize_host}/common/discovery/instance?authorization_endpoint={authorize_endpoint}&api-version=1.0' # pylint: disable=invalid-name
219228
AUTHORIZE_ENDPOINT_PATH = '/oauth2/authorize'
220229
TOKEN_ENDPOINT_PATH = '/oauth2/token'

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ PyJWT==1.0.0
33
#need 2.x for Python3 support
44
python-dateutil==2.1.0
55
#1.1.0 is the first that can be installed on windows
6-
cryptography==1.1.0
6+
cryptography==2.3.0
77
#for testing
88
httpretty==0.8.14
99
pylint==1.5.4

tests/test_authority.py

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
1-
#------------------------------------------------------------------------------
1+
#------------------------------------------------------------------------------
22
#
3-
# Copyright (c) Microsoft Corporation.
3+
# Copyright (c) Microsoft Corporation.
44
# All rights reserved.
5-
#
5+
#
66
# This code is licensed under the MIT License.
7-
#
7+
#
88
# Permission is hereby granted, free of charge, to any person obtaining a copy
99
# of this software and associated documentation files(the "Software"), to deal
1010
# in the Software without restriction, including without limitation the rights
1111
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
1212
# copies of the Software, and to permit persons to whom the Software is
1313
# furnished to do so, subject to the following conditions :
14-
#
14+
#
1515
# The above copyright notice and this permission notice shall be included in
1616
# all copies or substantial portions of the Software.
17-
#
17+
#
1818
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1919
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2020
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
@@ -60,6 +60,7 @@ class TestAuthority(unittest.TestCase):
6060
# discovery.
6161
nonHardCodedAuthority = 'https://login.doesntexist.com/' + cp['tenant']
6262
nonHardCodedAuthorizeEndpoint = nonHardCodedAuthority + '/oauth2/authorize'
63+
dstsTestEndpoint = 'https://test-dsts.core.azure-test.net/dstsv2/common'
6364

6465

6566
def setUp(self):
@@ -125,6 +126,11 @@ def test_success_static_instance_discovery(self):
125126
self.performStaticInstanceDiscovery('login.windows.net')
126127
self.performStaticInstanceDiscovery('login.chinacloudapi.cn')
127128
self.performStaticInstanceDiscovery('login-us.microsoftonline.com')
129+
self.performStaticInstanceDiscovery('test-dsts.dsts.core.windows.net')
130+
self.performStaticInstanceDiscovery('test-dsts.dsts.core.chinacloudapi.cn')
131+
self.performStaticInstanceDiscovery('test-dsts.dsts.core.cloudapi.de')
132+
self.performStaticInstanceDiscovery('test-dsts.dsts.core.usgovcloudapi.net')
133+
self.performStaticInstanceDiscovery('test-dsts.core.azure-test.net')
128134

129135

130136
@httpretty.activate
@@ -186,6 +192,13 @@ def test_url_extra_path_elements(self):
186192
"https://login.microsoftonline.com/your_tenant"):
187193
context = AuthenticationContext(self.nonHardCodedAuthority + '/extra/path')
188194

195+
@httpretty.activate
196+
def test_dsts_authority(self):
197+
try:
198+
context = AuthenticationContext(self.dstsTestEndpoint)
199+
except:
200+
self.fail("AuthenticationContext() rased an exception on dstsTestEndpoint")
201+
189202
@httpretty.activate
190203
def test_url_extra_slashes(self):
191204
util.setup_expected_instance_discovery_request(200,

0 commit comments

Comments
 (0)