#!/usr/bin/env python3 """Microsoft Graph OAuth authentication (device code flow).""" import msal import json import os TOKEN_FILE = os.path.expanduser("~/.config/microsoft-graph-tokens.json") CLIENT_ID = "14d82eec-204b-4c2f-b7e8-296a70dab67e" SCOPES = [ "https://graph.microsoft.com/Mail.Read", "https://graph.microsoft.com/Mail.ReadWrite", "https://graph.microsoft.com/Mail.Send", "https://graph.microsoft.com/Files.Read", "https://graph.microsoft.com/Files.ReadWrite", "https://graph.microsoft.com/User.Read" ] def main(): app = msal.PublicClientApplication(CLIENT_ID, authority="https://login.microsoftonline.com/consumers") flow = app.initiate_device_flow(scopes=SCOPES) if "user_code" not in flow: print(f"āŒ Failed to create device flow: {flow}") return print("\nšŸ” Microsoft Sign-In Required\n") print(f"1. Go to: {flow['verification_uri']}") print(f"2. Enter code: {flow['user_code']}") print("3. Sign in with your Microsoft account\n") print("Waiting for authorization...") result = app.acquire_token_by_device_flow(flow) if "access_token" in result: tokens = { "access_token": result["access_token"], "refresh_token": result.get("refresh_token"), "id_token": result.get("id_token"), "expires_in": result.get("expires_in"), "client_id": CLIENT_ID, "scopes": SCOPES, "account": result.get("id_token_claims", {}).get("preferred_username", "unknown") } os.makedirs(os.path.dirname(TOKEN_FILE), exist_ok=True) with open(TOKEN_FILE, "w") as f: json.dump(tokens, f, indent=2) print(f"\nāœ… Authorization successful!") print(f"Account: {tokens['account']}") print(f"Token saved to: {TOKEN_FILE}") else: print(f"\nāŒ Error: {result.get('error')}") print(f"Description: {result.get('error_description')}") if __name__ == "__main__": main()