/** * Kintinery Auth Module * Wraps amazon-cognito-identity-js for sign-up, confirm, sign-in, sign-out, and session management. */ const KintineryAuth = (() => { // These come from the global amazon-cognito-identity-js library loaded via CDN const getCognitoClasses = () => ({ CognitoUserPool: AmazonCognitoIdentity.CognitoUserPool, CognitoUser: AmazonCognitoIdentity.CognitoUser, AuthenticationDetails: AmazonCognitoIdentity.AuthenticationDetails, CognitoUserAttribute: AmazonCognitoIdentity.CognitoUserAttribute, }); const getUserPool = () => { const { CognitoUserPool } = getCognitoClasses(); return new CognitoUserPool({ UserPoolId: KintineryConfig.USER_POOL_ID, ClientId: KintineryConfig.CLIENT_ID, }); }; /** * Sign up a new user with email and password. * @returns {Promise<{userSub: string}>} */ function signUp(email, password, displayName) { return new Promise((resolve, reject) => { const { CognitoUserAttribute } = getCognitoClasses(); const pool = getUserPool(); const attributes = [ new CognitoUserAttribute({ Name: 'email', Value: email }), ]; if (displayName) { attributes.push(new CognitoUserAttribute({ Name: 'name', Value: displayName })); } pool.signUp(email, password, attributes, null, (err, result) => { if (err) return reject(err); resolve({ userSub: result.userSub, userConfirmed: result.userConfirmed }); }); }); } /** * Confirm sign-up with the 6-digit verification code sent via email. */ function confirmSignUp(email, code) { return new Promise((resolve, reject) => { const { CognitoUser } = getCognitoClasses(); const user = new CognitoUser({ Username: email, Pool: getUserPool() }); user.confirmRegistration(code, true, (err, result) => { if (err) return reject(err); resolve(result); }); }); } /** * Resend the confirmation code. */ function resendConfirmationCode(email) { return new Promise((resolve, reject) => { const { CognitoUser } = getCognitoClasses(); const user = new CognitoUser({ Username: email, Pool: getUserPool() }); user.resendConfirmationCode((err, result) => { if (err) return reject(err); resolve(result); }); }); } /** * Sign in with email and password. * @returns {Promise<{idToken: string, accessToken: string, refreshToken: string}>} */ function signIn(email, password) { return new Promise((resolve, reject) => { const { CognitoUser, AuthenticationDetails } = getCognitoClasses(); const user = new CognitoUser({ Username: email, Pool: getUserPool() }); const authDetails = new AuthenticationDetails({ Username: email, Password: password }); user.authenticateUser(authDetails, { onSuccess: (session) => { resolve({ idToken: session.getIdToken().getJwtToken(), accessToken: session.getAccessToken().getJwtToken(), refreshToken: session.getRefreshToken().getToken(), }); }, onFailure: (err) => reject(err), }); }); } /** * Get the current session (if the user is logged in with valid tokens). * Automatically refreshes expired tokens using the refresh token. * @returns {Promise<{idToken: string, email: string, userId: string, name: string}|null>} */ function getSession() { return new Promise((resolve) => { const pool = getUserPool(); const user = pool.getCurrentUser(); if (!user) return resolve(null); user.getSession((err, session) => { if (err || !session || !session.isValid()) return resolve(null); const idToken = session.getIdToken(); resolve({ idToken: idToken.getJwtToken(), email: idToken.payload.email, userId: idToken.payload.sub, name: idToken.payload.name || idToken.payload.email, }); }); }); } /** * Sign out the current user (clears local tokens). */ function signOut() { const pool = getUserPool(); const user = pool.getCurrentUser(); if (user) user.signOut(); } /** * Initiate forgot-password flow. */ function forgotPassword(email) { return new Promise((resolve, reject) => { const { CognitoUser } = getCognitoClasses(); const user = new CognitoUser({ Username: email, Pool: getUserPool() }); user.forgotPassword({ onSuccess: (data) => resolve(data), onFailure: (err) => reject(err), }); }); } /** * Confirm new password with the reset code. */ function confirmPassword(email, code, newPassword) { return new Promise((resolve, reject) => { const { CognitoUser } = getCognitoClasses(); const user = new CognitoUser({ Username: email, Pool: getUserPool() }); user.confirmPassword(code, newPassword, { onSuccess: () => resolve(), onFailure: (err) => reject(err), }); }); } /** * Check if user is currently authenticated. * @returns {Promise} */ async function isAuthenticated() { const session = await getSession(); return session !== null; } /** * Require auth — redirects to login page if not authenticated. * Call this at the top of protected pages. * @returns {Promise<{idToken, email, userId, name}>} */ async function requireAuth() { const session = await getSession(); if (!session) { window.location.href = 'login.html'; throw new Error('Not authenticated'); } return session; } return { signUp, confirmSignUp, resendConfirmationCode, signIn, getSession, signOut, forgotPassword, confirmPassword, isAuthenticated, requireAuth, }; })();