// shortlist/js/auth.js — Shared Cognito auth for all Shortlist pages // ───────────────────────────────────────────────────────────────────────────── // Fill in COGNITO_USER_POOL_ID and COGNITO_CLIENT_ID after deploying // OrionShortlistStack (values appear in CDK outputs as UserPoolId / UserPoolClientId). // ───────────────────────────────────────────────────────────────────────────── const COGNITO_REGION = 'us-east-1'; const COGNITO_USER_POOL_ID = 'us-east-1_NsjykEmfF'; const COGNITO_CLIENT_ID = '7mdbic2paketj5eul0951in6mh'; // ── Internal helpers ────────────────────────────────────────────────────────── function _getPool() { return new AmazonCognitoIdentity.CognitoUserPool({ UserPoolId: COGNITO_USER_POOL_ID, ClientId: COGNITO_CLIENT_ID, }); } function _decodeJwt(token) { try { const payload = token.split('.')[1]; return JSON.parse(atob(payload.replace(/-/g, '+').replace(/_/g, '/'))); } catch { return null; } } function _getStoredSession() { const pool = _getPool(); const user = pool.getCurrentUser(); if (!user) return Promise.resolve(null); return new Promise(resolve => { user.getSession((err, session) => { resolve((!err && session && session.isValid()) ? session : null); }); }); } // ── Public API ──────────────────────────────────────────────────────────────── window.ShortlistAuth = { /** * Admin pages: verifies session + admins group membership. * Redirects to login page if invalid; resolves with session if ok. */ async checkAdminAuth() { const session = await _getStoredSession(); if (!session) { window.location.href = '/shortlist/pages/admin/login.html'; return null; } const claims = _decodeJwt(session.getIdToken().getJwtToken()); const groups = claims?.['cognito:groups'] || []; if (!groups.includes('admins')) { window.location.href = '/shortlist/pages/admin/login.html?error=unauthorized'; return null; } return session; }, /** * Returns the current valid session, or null if not authenticated. * Used by candidate/employer pages to check login state. */ async getSession() { return _getStoredSession(); }, /** * Decode and return claims from the stored ID token. */ async getClaims() { const session = await _getStoredSession(); if (!session) return null; return _decodeJwt(session.getIdToken().getJwtToken()); }, /** * Returns the email of the currently signed-in user, or null. */ async getCurrentEmail() { const claims = await this.getClaims(); return claims?.email || null; }, /** * Sign in with email + password (SRP). * Returns the Cognito session on success; rejects on failure. */ signIn(email, password) { return new Promise((resolve, reject) => { const pool = _getPool(); const user = new AmazonCognitoIdentity.CognitoUser({ Username: email, Pool: pool }); const auth = new AmazonCognitoIdentity.AuthenticationDetails({ Username: email, Password: password }); user.authenticateUser(auth, { onSuccess: resolve, onFailure: reject, newPasswordRequired: () => reject(Object.assign(new Error('NEW_PASSWORD_REQUIRED'), { code: 'NewPasswordRequired' })), }); }); }, /** * Register a new user (email + password). * Cognito sends a verification code to the email. */ signUp(email, password) { return new Promise((resolve, reject) => { const pool = _getPool(); const emailAttr = new AmazonCognitoIdentity.CognitoUserAttribute({ Name: 'email', Value: email }); pool.signUp(email, password, [emailAttr], null, (err, result) => { if (err) reject(err); else resolve(result); }); }); }, /** * Confirm sign-up with the code emailed by Cognito. */ confirmSignUp(email, code) { return new Promise((resolve, reject) => { const user = new AmazonCognitoIdentity.CognitoUser({ Username: email, Pool: _getPool() }); user.confirmRegistration(code, true, (err, result) => { if (err) reject(err); else resolve(result); }); }); }, /** * Resend the confirmation code (e.g. if it expired). */ resendCode(email) { return new Promise((resolve, reject) => { const user = new AmazonCognitoIdentity.CognitoUser({ Username: email, Pool: _getPool() }); user.resendConfirmationCode((err, result) => { if (err) reject(err); else resolve(result); }); }); }, /** * Sign out the current user globally (clears localStorage tokens). */ signOut() { const user = _getPool().getCurrentUser(); if (user) user.signOut(); }, };