Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 17 additions & 7 deletions msal/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import sys
import warnings
from threading import Lock
from typing import Optional # Needed in Python 3.7 & 3.8
import os

from .oauth2cli import Client, JwtAssertionCreator
Expand Down Expand Up @@ -225,6 +226,7 @@ class ClientApplication(object):
REMOVE_ACCOUNT_ID = "903"

ATTEMPT_REGION_DISCOVERY = True # "TryAutoDetect"
DISABLE_MSAL_FORCE_REGION = False # Used in azure_region to disable MSAL_FORCE_REGION behavior
_TOKEN_SOURCE = "token_source"
_TOKEN_SOURCE_IDP = "identity_provider"
_TOKEN_SOURCE_CACHE = "cache"
Expand Down Expand Up @@ -448,11 +450,14 @@ def __init__(
Instructs MSAL to use the Entra regional token service. This legacy feature is only available to
first-party applications. Only ``acquire_token_for_client()`` is supported.

Supports 3 values:
Supports 4 values:

``azure_region=None`` - meaning no region is used. This is the default value.
``azure_region="some_region"`` - meaning the specified region is used.
``azure_region=True`` - meaning MSAL will try to auto-detect the region. This is not recommended.
1. ``azure_region=None`` - This default value means no region is configured.
MSAL will use the region defined in env var ``MSAL_FORCE_REGION``.
2. ``azure_region="some_region"`` - meaning the specified region is used.
3. ``azure_region=True`` - meaning
MSAL will try to auto-detect the region. This is not recommended.
4. ``azure_region=False`` - meaning MSAL will use no region.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not as per spec. Let's please keep it as per spec.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per offline discussion, an alias DISABLE_MSAL_FORCE_REFRESH is now added here.


.. note::
Region auto-discovery has been tested on VMs and on Azure Functions. It is unreliable.
Expand Down Expand Up @@ -630,7 +635,10 @@ def __init__(
except ValueError: # Those are explicit authority validation errors
raise
except Exception: # The rest are typically connection errors
if validate_authority and azure_region and not oidc_authority:
if validate_authority and not oidc_authority and (
azure_region # Opted in to use region
or (azure_region is None and os.getenv("MSAL_FORCE_REGION")) # Will use region
):
# Since caller opts in to use region, here we tolerate connection
# errors happened during authority validation at non-region endpoint
self.authority = Authority(
Expand Down Expand Up @@ -724,9 +732,11 @@ def _build_telemetry_context(
self._telemetry_buffer, self._telemetry_lock, api_id,
correlation_id=correlation_id, refresh_reason=refresh_reason)

def _get_regional_authority(self, central_authority):
if not self._region_configured: # User did not opt-in to ESTS-R
def _get_regional_authority(self, central_authority) -> Optional[Authority]:
if self._region_configured is False: # User opts out of ESTS-R
return None # Short circuit to completely bypass region detection
if self._region_configured is None: # User did not make an ESTS-R choice
self._region_configured = os.getenv("MSAL_FORCE_REGION") or None
self._region_detected = self._region_detected or _detect_region(
self.http_client if self._region_configured is not None else None)
if (self._region_configured != self.ATTEMPT_REGION_DISCOVERY
Expand Down
14 changes: 13 additions & 1 deletion tests/test_e2e.py
Original file line number Diff line number Diff line change
Expand Up @@ -1130,11 +1130,23 @@ def _test_acquire_token_for_client(self, configured_region, expected_region):
def test_acquire_token_for_client_should_hit_global_endpoint_by_default(self):
self._test_acquire_token_for_client(None, None)

def test_acquire_token_for_client_should_ignore_env_var_by_default(self):
def test_acquire_token_for_client_should_ignore_env_var_region_name_by_default(self):
os.environ["REGION_NAME"] = "eastus"
self._test_acquire_token_for_client(None, None)
del os.environ["REGION_NAME"]

@patch.dict(os.environ, {"MSAL_FORCE_REGION": "eastus"})
def test_acquire_token_for_client_should_use_env_var_msal_force_region_by_default(self):
self._test_acquire_token_for_client(None, "eastus")

@patch.dict(os.environ, {"MSAL_FORCE_REGION": "eastus"})
def test_acquire_token_for_client_should_prefer_the_explicit_region(self):
self._test_acquire_token_for_client("westus", "westus")

@patch.dict(os.environ, {"MSAL_FORCE_REGION": "eastus"})
def test_acquire_token_for_client_should_allow_opt_out_env_var_msal_force_region(self):
self._test_acquire_token_for_client(False, None)

def test_acquire_token_for_client_should_use_a_specified_region(self):
self._test_acquire_token_for_client("westus", "westus")

Expand Down