UNPKG

svelte-guardian

Version:

Batteries included authentication for SvelteKit applications.

160 lines (159 loc) 5.31 kB
import { goto } from '$app/navigation'; // Utility function for API calls async function apiCall(endpoint, method = 'POST', data) { try { const response = await fetch(`/auth/${endpoint}`, { method, headers: { 'Content-Type': 'application/json' }, body: data ? JSON.stringify(data) : undefined }); if (!response.ok) { const errorData = await response.json(); throw new Error(errorData.error || 'Request failed'); } return await response.json(); } catch (error) { return { success: false, error: error.message || 'An error occurred' }; } } // Email Verification Functions export const emailVerification = { // Request OTP verification async requestOTP(email) { return await apiCall('verify-email/send-otp', 'POST', { email }); }, // Request link async requestLink(email) { return await apiCall('verify-email/send-link', 'POST', { email }); }, // Initiate email verification async initiate(email) { return await apiCall('verify-email/initiate', 'POST', { email }); }, // Verify OTP async verifyOTP(email, otp) { return await apiCall('verify-email/verify-otp', 'POST', { email, otp }); }, // Verify link token async verifyToken(email, token) { return await apiCall('verify-email/verify-token', 'POST', { email, token }); }, // Utility function to handle email verification flow async handleEmailVerification(email, method) { if (method === 'otp') { const result = await this.requestOTP(email); if (result.success) { // Show OTP input form return { success: true, data: { verificationId: result.data?.verificationId } }; } return result; } else { return await this.requestLink(email); } } }; // Password Reset Functions export const passwordReset = { // Request password reset async requestReset(email) { return await apiCall('reset-password/initiate-reset', 'POST', { email }); }, // Validate reset token async validateToken(token) { return await apiCall('reset-password/validate-token', 'POST', { token }); }, // Reset password async resetPassword(email, token, newPassword, confirmPassword) { if (newPassword !== confirmPassword) { return { success: false, error: 'Passwords do not match' }; } return await apiCall('reset-password/reset', 'POST', { email, token, newPassword }); }, // Password validation validatePassword(password, options = {}) { const errors = []; if (password.length < (options.minimumPasswordLength || 8)) { errors.push(`Password must be at least ${options.minimumPasswordLength || 8} characters long`); } if (options.requireSpecialChar && !/[!@#$%^&*(),.?":{}|<>]/.test(password)) { errors.push('Password must contain at least one special character'); } if (options.requireNumber && !/\d/.test(password)) { errors.push('Password must contain at least one number'); } if (options.requireUppercase && !/[A-Z]/.test(password)) { errors.push('Password must contain at least one uppercase letter'); } return { valid: errors.length === 0, errors }; }, // Complete password reset flow async handlePasswordReset(email) { const result = await this.requestReset(email); if (result.success) { // Redirect to check email page await goto('/auth/check-email'); } return result; } }; // Two-Factor Authentication Functions export const twoFactorAuth = { // Setup 2FA async setup(method) { return await apiCall('two-factor/setup', 'POST', { method }); }, // Generate QR code for TOTP async generateQRCode(secret) { const qrcode = await import('qrcode'); const otpauth = `otpauth://totp/${window.location.hostname}?secret=${secret}`; return await qrcode.toDataURL(otpauth); }, // Verify 2FA token async verifyToken(token) { return await apiCall('two-factor/verify', 'POST', { token }); }, // Verify backup code async verifyBackupCode(code) { return await apiCall('two-factor/verify-backup', 'POST', { code }); }, // Disable 2FA async disable() { return await apiCall('two-factor/disable', 'POST'); }, // Handle complete 2FA setup flow async handleSetup(method) { const result = await this.setup(method); if (result.success && method === '2fa-totp') { const qrCode = await this.generateQRCode(result.data.secret); return { ...result, data: { ...result.data, qrCode } }; } return result; } }; export * from '@auth/sveltekit/client';