@@ -148,7 +148,6 @@ def __init__(self, scopes: list[str] = []) -> None:
148148 "Missing KEEP_AZUREAD_TENANT_ID or KEEP_AZUREAD_CLIENT_ID environment variable"
149149 )
150150
151- self .issuer = f"https://sts.windows.net/{ self .tenant_id } /"
152151 self .group_mapper = AzureADGroupMapper ()
153152 # Keep track of hashed tokens so we won't update the user on the same token
154153 self .saw_tokens = set ()
@@ -179,23 +178,33 @@ def _verify_bearer_token(
179178 "verify_iat" : True ,
180179 "verify_exp" : True ,
181180 "verify_nbf" : True ,
182- "verify_iss" : True ,
181+ # we will validate manually since we need to support both
182+ # v1 (sts.windows.net) and v2 (https://login.microsoftonline.com)
183+ "verify_iss" : False ,
183184 # "require" the standard claims but NOT "appid"
184185 "require" : ["exp" , "iat" , "nbf" , "iss" , "sub" ],
185186 }
186187
187188 try :
189+
188190 payload = jwt .decode (
189191 token ,
190192 key = signing_key ,
191193 algorithms = ["RS256" ],
192- issuer = self .issuer ,
193194 options = options ,
194195 )
195196
196- # In v1.0 tokens, client_id => 'appid'
197- # In v2.0 tokens, client_id => 'azp'
198- # We consider either one valid, so long as it matches self.client_id
197+ # ---- MANUAL ISSUER CHECK ----
198+ # Allowed issuers for v1 vs. v2 in the same tenant:
199+ allowed_issuers = [
200+ f"https://sts.windows.net/{ self .tenant_id } /" , # v1 tokens
201+ f"https://login.microsoftonline.com/{ self .tenant_id } /v2.0" , # v2 tokens
202+ ]
203+ issuer_in_token = payload .get ("iss" )
204+ if issuer_in_token not in allowed_issuers :
205+ raise HTTPException (status_code = 401 , detail = "Invalid token issuer" )
206+
207+ # Check client ID: v1 -> 'appid', v2 -> 'azp'
199208 client_id_in_token = payload .get ("appid" ) or payload .get ("azp" )
200209
201210 if not client_id_in_token :
0 commit comments