import { byuAuthConfig } from '@server/utils/auth.ts' import { getQuery, getCookie, deleteCookie, setCookie, createError, sendRedirect } from 'h3' export default defineEventHandler(async (event) => { const config = useRuntimeConfig() const query = getQuery(event) const code = query.code as string const state = query.state as string // Verify state const savedState = getCookie(event, 'oauth_state') if (state !== savedState) { throw createError({ statusCode: 401, message: 'Invalid state parameter' }) } // Get code verifier const codeVerifier = getCookie(event, 'code_verifier') if (!codeVerifier) { throw createError({ statusCode: 401, message: 'Missing code verifier' }) } try { // Exchange code for token with PKCE const tokenResponse = await $fetch(byuAuthConfig.tokenUrl, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: new URLSearchParams({ grant_type: 'authorization_code', code, redirect_uri: byuAuthConfig.redirectUri, client_id: byuAuthConfig.clientId, code_verifier: codeVerifier, }).toString() }) // Get user info const userInfo = await $fetch(byuAuthConfig.userInfoUrl, { headers: { Authorization: `Bearer ${tokenResponse.access_token}` } }) // Create session object const session = { user: { id: userInfo.net_id, netId: userInfo.net_id, firstName: userInfo.preferred_first_name, lastName: userInfo.surname, byuId: userInfo.byu_id, name: `${userInfo.preferred_first_name} ${userInfo.surname}`, expiresAt: userInfo.exp, }, accessToken: tokenResponse.access_token, tokenType: tokenResponse.token_type, expiresIn: tokenResponse.expires_in, } // Store session in secure cookie setCookie(event, 'session', JSON.stringify(session), { httpOnly: true, secure: config.baseUrl !== 'http://localhost:3000', maxAge: 60 * 60, // 1 hour sameSite: 'lax' }) // Clean up temporary cookies deleteCookie(event, 'oauth_state') deleteCookie(event, 'code_verifier') // Read redirect URL from cookie, fallback to home page const redirectUrl = getCookie(event, 'redirect_after_login') || '/' // Clear redirect cookie deleteCookie(event, 'redirect_after_login') // Redirect user back to the intended page return sendRedirect(event, redirectUrl) } catch (error: any) { console.error('!!! AUTH CALLBACK ERROR !!!') console.error('Error:', error) console.error('Error data:', error.data) throw createError({ statusCode: 500, message: 'Authentication failed', data: error.data }) } })