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

Commit

Permalink
Merge pull request #169 from AzureAD/release-1.1.0
Browse files Browse the repository at this point in the history
Release 1.1.0
  • Loading branch information
rayluo authored Aug 30, 2018
2 parents 139e0a7 + 6d6fbdc commit bef928d
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 21 deletions.
2 changes: 1 addition & 1 deletion adal/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

# pylint: disable=wrong-import-position

__version__ = '1.0.2'
__version__ = '1.1.0'

import logging

Expand Down
33 changes: 21 additions & 12 deletions adal/authority.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
#
# Copyright (c) Microsoft Corporation.
# Copyright (c) Microsoft Corporation.
# All rights reserved.
#
#
# This code is licensed under the MIT License.
#
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files(the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
#
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
Expand Down Expand Up @@ -62,6 +62,12 @@ def __init__(self, authority_url, validate_authority=True):
def url(self):
return self._url.geturl()

def _whitelisted(self): # testing if self._url.hostname is a dsts whitelisted domain
for domain in AADConstants.WHITELISTED_DOMAINS:
if self._url.hostname.endswith(domain):
return True
return False

def _validate_authority_url(self):

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

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

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

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

def _create_authority_url(self):
return "https://{}/{}{}".format(self._url.hostname,
self._tenant,
return "https://{}/{}{}".format(self._url.hostname,
self._tenant,
AADConstants.AUTHORIZE_ENDPOINT_PATH)

def _create_instance_discovery_endpoint_from_template(self, authority_host):

discovery_endpoint = AADConstants.INSTANCE_DISCOVERY_ENDPOINT_TEMPLATE
discovery_endpoint = discovery_endpoint.replace('{authorize_host}', authority_host)
discovery_endpoint = discovery_endpoint.replace('{authorize_endpoint}',
quote(self._create_authority_url(),
discovery_endpoint = discovery_endpoint.replace('{authorize_endpoint}',
quote(self._create_authority_url(),
safe='~()*!.\''))
return urlparse(discovery_endpoint)

Expand All @@ -132,7 +141,7 @@ def _perform_dynamic_instance_discovery(self):
if resp.status_code == 429:
resp.raise_for_status() # Will raise requests.exceptions.HTTPError
if not util.is_http_success(resp.status_code):
return_error_string = u"{} request returned http error: {}".format(operation,
return_error_string = u"{} request returned http error: {}".format(operation,
resp.status_code)
error_response = ""
if resp.text:
Expand Down
11 changes: 10 additions & 1 deletion adal/constants.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
#
# Copyright (c) Microsoft Corporation.
# All rights reserved.
Expand Down Expand Up @@ -215,6 +215,15 @@ class AADConstants(object):
'login.microsoftonline.us',
'login.microsoftonline.de',
]
WHITELISTED_DOMAINS = [
# Define dSTS domains whitelist based on its Supported Environments & National Clouds list here
# https://microsoft.sharepoint.com/teams/AzureSecurityCompliance/Security/SitePages/dSTS%20Fundamentals.aspx
'dsts.core.windows.net',
'dsts.core.chinacloudapi.cn',
'dsts.core.cloudapi.de',
'dsts.core.usgovcloudapi.net',
'dsts.core.azure-test.net',
]
INSTANCE_DISCOVERY_ENDPOINT_TEMPLATE = 'https://{authorize_host}/common/discovery/instance?authorization_endpoint={authorize_endpoint}&api-version=1.0' # pylint: disable=invalid-name
AUTHORIZE_ENDPOINT_PATH = '/oauth2/authorize'
TOKEN_ENDPOINT_PATH = '/oauth2/token'
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ PyJWT==1.0.0
#need 2.x for Python3 support
python-dateutil==2.1.0
#1.1.0 is the first that can be installed on windows
cryptography==1.1.0
cryptography==2.3.0
#for testing
httpretty==0.8.14
pylint==1.5.4
25 changes: 19 additions & 6 deletions tests/test_authority.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
#
# Copyright (c) Microsoft Corporation.
# Copyright (c) Microsoft Corporation.
# All rights reserved.
#
#
# This code is licensed under the MIT License.
#
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files(the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
#
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
Expand Down Expand Up @@ -60,6 +60,7 @@ class TestAuthority(unittest.TestCase):
# discovery.
nonHardCodedAuthority = 'https://login.doesntexist.com/' + cp['tenant']
nonHardCodedAuthorizeEndpoint = nonHardCodedAuthority + '/oauth2/authorize'
dstsTestEndpoint = 'https://test-dsts.core.azure-test.net/dstsv2/common'


def setUp(self):
Expand Down Expand Up @@ -125,6 +126,11 @@ def test_success_static_instance_discovery(self):
self.performStaticInstanceDiscovery('login.windows.net')
self.performStaticInstanceDiscovery('login.chinacloudapi.cn')
self.performStaticInstanceDiscovery('login-us.microsoftonline.com')
self.performStaticInstanceDiscovery('test-dsts.dsts.core.windows.net')
self.performStaticInstanceDiscovery('test-dsts.dsts.core.chinacloudapi.cn')
self.performStaticInstanceDiscovery('test-dsts.dsts.core.cloudapi.de')
self.performStaticInstanceDiscovery('test-dsts.dsts.core.usgovcloudapi.net')
self.performStaticInstanceDiscovery('test-dsts.core.azure-test.net')


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

@httpretty.activate
def test_dsts_authority(self):
try:
context = AuthenticationContext(self.dstsTestEndpoint)
except:
self.fail("AuthenticationContext() rased an exception on dstsTestEndpoint")

@httpretty.activate
def test_url_extra_slashes(self):
util.setup_expected_instance_discovery_request(200,
Expand Down

0 comments on commit bef928d

Please sign in to comment.