@@ -56,6 +56,7 @@ def __init__(
5656 self , authority_url , http_client ,
5757 validate_authority = True ,
5858 instance_discovery = None ,
59+ oidc_authority_url = None ,
5960 ):
6061 """Creates an authority instance, and also validates it.
6162
@@ -65,12 +66,56 @@ def __init__(
6566 This parameter only controls whether an instance discovery will be
6667 performed.
6768 """
69+ self ._http_client = http_client
70+ if oidc_authority_url :
71+ logger .info ("Initializing with OIDC authority: %s" , oidc_authority_url )
72+ tenant_discovery_endpoint = self ._initialize_oidc_authority (
73+ oidc_authority_url )
74+ else :
75+ logger .info ("Initializing with Entra authority: %s" , authority_url )
76+ tenant_discovery_endpoint = self ._initialize_entra_authority (
77+ authority_url , validate_authority , instance_discovery )
78+ try :
79+ openid_config = tenant_discovery (
80+ tenant_discovery_endpoint ,
81+ self ._http_client )
82+ except ValueError :
83+ error_message = (
84+ "Unable to get OIDC authority configuration for {url} "
85+ "because its OIDC Discovery endpoint is unavailable at "
86+ "{url}/.well-known/openid-configuration " .format (url = oidc_authority_url )
87+ if oidc_authority_url else
88+ "Unable to get authority configuration for {}. "
89+ "Authority would typically be in a format of "
90+ "https://login.microsoftonline.com/your_tenant "
91+ "or https://tenant_name.ciamlogin.com "
92+ "or https://tenant_name.b2clogin.com/tenant.onmicrosoft.com/policy. "
93+ .format (authority_url )
94+ ) + " Also please double check your tenant name or GUID is correct."
95+ raise ValueError (error_message )
96+ logger .debug (
97+ 'openid_config("%s") = %s' , tenant_discovery_endpoint , openid_config )
98+ self .authorization_endpoint = openid_config ['authorization_endpoint' ]
99+ self .token_endpoint = openid_config ['token_endpoint' ]
100+ self .device_authorization_endpoint = openid_config .get ('device_authorization_endpoint' )
101+ _ , _ , self .tenant = canonicalize (self .token_endpoint ) # Usually a GUID
102+
103+ def _initialize_oidc_authority (self , oidc_authority_url ):
104+ authority , self .instance , tenant = canonicalize (oidc_authority_url )
105+ self .is_adfs = tenant .lower () == 'adfs' # As a convention
106+ self ._is_b2c = True # Not exactly true, but
107+ # OIDC Authority was designed for CIAM which is the next gen of B2C.
108+ # Besides, application.py uses this to bypass broker.
109+ self ._is_known_to_developer = True # Not really relevant, but application.py uses this to bypass authority validation
110+ return oidc_authority_url + "/.well-known/openid-configuration"
111+
112+ def _initialize_entra_authority (
113+ self , authority_url , validate_authority , instance_discovery ):
68114 # :param instance_discovery:
69115 # By default, the known-to-Microsoft validation will use an
70116 # instance discovery endpoint located at ``login.microsoftonline.com``.
71117 # You can customize the endpoint by providing a url as a string.
72118 # Or you can turn this behavior off by passing in a False here.
73- self ._http_client = http_client
74119 if isinstance (authority_url , AuthorityBuilder ):
75120 authority_url = str (authority_url )
76121 authority , self .instance , tenant = canonicalize (authority_url )
@@ -111,24 +156,7 @@ def __init__(
111156 version = "" if self .is_adfs else "/v2.0" ,
112157 )
113158 ).geturl () # Keeping original port and query. Query is useful for test.
114- try :
115- openid_config = tenant_discovery (
116- tenant_discovery_endpoint ,
117- self ._http_client )
118- except ValueError :
119- raise ValueError (
120- "Unable to get authority configuration for {}. "
121- "Authority would typically be in a format of "
122- "https://login.microsoftonline.com/your_tenant "
123- "or https://tenant_name.ciamlogin.com "
124- "or https://tenant_name.b2clogin.com/tenant.onmicrosoft.com/policy. "
125- "Also please double check your tenant name or GUID is correct." .format (
126- authority_url ))
127- logger .debug ("openid_config = %s" , openid_config )
128- self .authorization_endpoint = openid_config ['authorization_endpoint' ]
129- self .token_endpoint = openid_config ['token_endpoint' ]
130- self .device_authorization_endpoint = openid_config .get ('device_authorization_endpoint' )
131- _ , _ , self .tenant = canonicalize (self .token_endpoint ) # Usually a GUID
159+ return tenant_discovery_endpoint
132160
133161 def user_realm_discovery (self , username , correlation_id = None , response = None ):
134162 # It will typically return a dict containing "ver", "account_type",
0 commit comments