This commit is contained in:
2025-12-22 09:57:49 +01:00
parent 87865e2c6d
commit e00c47a56f
4 changed files with 236 additions and 78 deletions
+29 -17
View File
@@ -24,10 +24,15 @@ class GraphAuthenticator:
self.credential: Optional[InteractiveBrowserCredential] = None
self.client: Optional[GraphServiceClient] = None
async def authenticate(self) -> bool:
async def authenticate(self, tenant_id: str = None, credential: InteractiveBrowserCredential = None, skip_validation: bool = False) -> bool:
"""
Authenticate to Microsoft Graph using interactive browser login.
Args:
tenant_id: Optional specific tenant ID (recommended to avoid double auth)
credential: Optional credential to reuse (avoids creating new credential)
skip_validation: Skip the me.get() validation call (use when reusing credential to avoid extra auth)
Returns:
bool: True if authentication succeeded, False otherwise
@@ -35,14 +40,19 @@ class GraphAuthenticator:
Exception: If authentication fails
"""
try:
# Create interactive browser credential
# Using "organizations" allows login with any organizational account
# additionally_allowed_tenants="*" allows acquiring tokens for any tenant (needed for Key Vault access)
self.credential = InteractiveBrowserCredential(
tenant_id="organizations",
client_id=self.client_id,
additionally_allowed_tenants=["*"]
)
if credential:
# Reuse provided credential (recommended to avoid multiple auth prompts)
self.credential = credential
else:
# Use specific tenant if provided, otherwise fall back to "organizations"
auth_tenant = tenant_id if tenant_id else "organizations"
# Create interactive browser credential
self.credential = InteractiveBrowserCredential(
tenant_id=auth_tenant,
client_id=self.client_id,
additionally_allowed_tenants=["*"]
)
# Define scopes for Microsoft Graph
scopes = ['https://graph.microsoft.com/.default']
@@ -53,17 +63,19 @@ class GraphAuthenticator:
scopes=scopes
)
# Authenticate to Graph API FIRST
# This triggers the initial browser auth for Graph scope
# Then Management API will use SSO (single sign-on) from this auth
me = await self.client.me.get()
# Validate authentication (unless skip_validation is True)
if not skip_validation:
me = await self.client.me.get()
if me:
print(f"Successfully authenticated as: {me.display_name} ({me.user_principal_name})")
if me:
print(f"Successfully authenticated as: {me.display_name} ({me.user_principal_name})")
return True
return False
else:
print("Skipping Graph validation (using cached authentication)")
return True
return False
except Exception as e:
raise Exception(f"Graph authentication failed: {str(e)}")