/** * Authentication service for token management and user info extraction. */ import { IPublicClientApplication, InteractionRequiredAuthError } from '@azure/msal-browser'; import { apiTokenRequest } from './authConfig'; /** * Acquires an access token silently, or via popup if interaction required. * Use this before making authenticated API calls. */ export const getAccessToken = async (msalInstance: IPublicClientApplication): Promise => { console.log('[MSAL Auth] getAccessToken called'); const account = msalInstance.getActiveAccount(); if (!account) { console.error('[MSAL Auth] No active account found'); return null; } console.log('[MSAL Auth] Active account:', account.username); try { // Try silent token acquisition first console.log('[MSAL Auth] Attempting silent token acquisition...'); const response = await msalInstance.acquireTokenSilent({ ...apiTokenRequest, account, }); console.log('[MSAL Auth] Silent token acquisition successful, expires:', response.expiresOn); return response.accessToken; } catch (error) { if (error instanceof InteractionRequiredAuthError) { // Fallback to popup if silent fails (e.g., token expired, new consent required) console.log('[MSAL Auth] Silent acquisition failed, trying popup...'); try { const response = await msalInstance.acquireTokenPopup(apiTokenRequest); console.log('[MSAL Auth] Popup token acquisition successful'); return response.accessToken; } catch (popupError) { console.error('[MSAL Auth] Failed to acquire token via popup:', popupError); return null; } } console.error('[MSAL Auth] Failed to acquire token:', error); return null; } }; /** * User info interface matching Azure AD claims */ export interface UserInfo { name: string; email: string; firstName: string; lastName: string; accountType: string; } /** * Extract user information from the active account */ export const getUserInfo = (msalInstance: IPublicClientApplication): UserInfo | null => { const account = msalInstance.getActiveAccount(); if (!account) return null; const idTokenClaims = account.idTokenClaims as Record; return { name: account.name || 'Unknown User', email: account.username || '', firstName: (idTokenClaims?.given_name as string) || account.name?.split(' ')[0] || '', lastName: (idTokenClaims?.family_name as string) || account.name?.split(' ').slice(1).join(' ') || '', accountType: 'Enterprise User', // Single tenant = enterprise users }; };