loreal-video-optimizer/frontend/auth.js
2025-12-05 20:21:47 +05:30

171 lines
4.4 KiB
JavaScript

/**
* Microsoft Authentication Library (MSAL) wrapper for SSO authentication
* Provides authentication functions for the video optimizer application
*/
let msalInstance = null;
let msalConfig = null;
const loginRequest = {
scopes: ["User.Read"]
};
/**
* Initialize MSAL with configuration from backend
* @param {Object} config - Azure AD configuration from /api/config
*/
async function initAuth(config) {
if (!config || !config.AZURE_CLIENT_ID || !config.AZURE_TENANT_ID) {
throw new Error('Invalid Azure AD configuration');
}
msalConfig = {
auth: {
clientId: config.AZURE_CLIENT_ID,
authority: `https://login.microsoftonline.com/${config.AZURE_TENANT_ID}`,
redirectUri: config.REDIRECT_URI || window.location.origin
},
cache: {
cacheLocation: "sessionStorage", // Re-login required after browser close
storeAuthStateInCookie: false
}
};
// Initialize MSAL instance
msalInstance = new msal.PublicClientApplication(msalConfig);
// Initialize the MSAL instance (required in MSAL v3.x)
await msalInstance.initialize();
// Handle redirect promise
try {
const response = await msalInstance.handleRedirectPromise();
if (response) {
console.log('Authentication successful:', response);
}
} catch (error) {
console.error('Authentication error:', error);
// Check if it's an unauthorized user error (not in tenant)
if (error.errorCode === 'user_cancelled' ||
error.errorCode === 'access_denied' ||
error.errorMessage?.includes('AADSTS50020')) {
throw new Error('Unauthorized: You are not authorized to access this application. Please contact your administrator.');
}
throw error;
}
}
/**
* Check if user is authenticated
* @returns {boolean}
*/
function isAuthenticated() {
if (!msalInstance) {
return false;
}
const accounts = msalInstance.getAllAccounts();
return accounts.length > 0;
}
/**
* Get the current user account
* @returns {Object|null}
*/
function getAccount() {
if (!msalInstance) {
return null;
}
const accounts = msalInstance.getAllAccounts();
return accounts.length > 0 ? accounts[0] : null;
}
/**
* Get user email
* @returns {string|null}
*/
function getUserEmail() {
const account = getAccount();
return account ? (account.username || account.email || '') : null;
}
/**
* Get user display name
* @returns {string|null}
*/
function getUserName() {
const account = getAccount();
return account ? (account.name || account.username || '') : null;
}
/**
* Login with redirect
*/
async function login() {
if (!msalInstance) {
throw new Error('MSAL not initialized. Call initAuth() first.');
}
try {
await msalInstance.loginRedirect(loginRequest);
} catch (error) {
console.error('Login failed:', error);
throw error;
}
}
/**
* Logout with redirect
*/
async function logout() {
if (!msalInstance) {
throw new Error('MSAL not initialized. Call initAuth() first.');
}
try {
await msalInstance.logoutRedirect({
postLogoutRedirectUri: window.location.origin
});
} catch (error) {
console.error('Logout failed:', error);
throw error;
}
}
/**
* Get access token (if needed for API calls)
* @returns {Promise<string>}
*/
async function getAccessToken() {
if (!msalInstance) {
throw new Error('MSAL not initialized. Call initAuth() first.');
}
const account = getAccount();
if (!account) {
throw new Error('No authenticated user found');
}
try {
const response = await msalInstance.acquireTokenSilent({
...loginRequest,
account: account
});
return response.accessToken;
} catch (error) {
console.error('Token acquisition failed:', error);
// If silent token acquisition fails, redirect to login
await msalInstance.acquireTokenRedirect(loginRequest);
}
}
// Export functions to window object for global access
window.initAuth = initAuth;
window.isAuthenticated = isAuthenticated;
window.getAccount = getAccount;
window.getUserEmail = getUserEmail;
window.getUserName = getUserName;
window.login = login;
window.logout = logout;
window.getAccessToken = getAccessToken;