You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

73 lines
1.9 KiB

// server/api/auth/login.post.ts
/**
* POST /api/auth/login
*
* Initiates OAuth2 Authorization Code Flow with PKCE
*
* Request body:
* {
* "email": "user@example.com"
* }
*
* Response:
* {
* "redirectUrl": "https://experimenta.cidaas.de/authz-srv/authz?..."
* }
*
* Client should redirect user to redirectUrl
*/
import { z } from 'zod'
const loginSchema = z.object({
email: z.string().email('Invalid email address'),
})
export default defineEventHandler(async (event) => {
// 1. Validate request body
const body = await readBody(event)
const { email } = loginSchema.parse(body)
// 2. Generate PKCE challenge
const { verifier, challenge } = await generatePKCE()
// 3. Generate state for CSRF protection
const state = generateState(32)
// 4. Store PKCE verifier in encrypted cookie (5 min TTL)
setCookie(event, 'pkce_verifier', verifier, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'lax',
maxAge: 300, // 5 minutes
path: '/',
})
// 5. Store state in cookie for validation
setCookie(event, 'oauth_state', state, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'lax',
maxAge: 300, // 5 minutes
path: '/',
})
// 6. Build Cidaas authorization URL
const config = useRuntimeConfig()
const authUrl = new URL(config.cidaas.authorizeUrl)
authUrl.searchParams.set('client_id', config.cidaas.clientId)
authUrl.searchParams.set('redirect_uri', config.cidaas.redirectUri)
authUrl.searchParams.set('response_type', 'code')
authUrl.searchParams.set('scope', 'openid profile email')
authUrl.searchParams.set('state', state)
authUrl.searchParams.set('code_challenge', challenge)
authUrl.searchParams.set('code_challenge_method', 'S256')
authUrl.searchParams.set('login_hint', email) // Pre-fill email in Cidaas form
// 7. Return redirect URL to client
return {
redirectUrl: authUrl.toString(),
}
})