diff --git a/src/layouts/Layout.astro b/src/layouts/Layout.astro index b5b1963..5cf3f33 100644 --- a/src/layouts/Layout.astro +++ b/src/layouts/Layout.astro @@ -40,9 +40,7 @@ import CookieConsent from '../components/CookieConsent.astro'; })(); - - - +
@@ -110,4 +108,5 @@ import CookieConsent from '../components/CookieConsent.astro'; \ No newline at end of file diff --git a/src/layouts/LoginLayout.astro b/src/layouts/LoginLayout.astro index 720cac0..51dbed7 100644 --- a/src/layouts/LoginLayout.astro +++ b/src/layouts/LoginLayout.astro @@ -50,9 +50,7 @@ import CookieConsent from '../components/CookieConsent.astro'; })(); - - - + @@ -99,4 +97,5 @@ import CookieConsent from '../components/CookieConsent.astro'; \ No newline at end of file diff --git a/src/lib/auth-unified.ts b/src/lib/auth-unified.ts new file mode 100644 index 0000000..b59d4ad --- /dev/null +++ b/src/lib/auth-unified.ts @@ -0,0 +1,383 @@ +/** + * Unified Authentication Module + * This is the SINGLE source of truth for all authentication in the application. + * All auth-related functions should be imported from this file. + */ + +import { createSupabaseServerClient, createSupabaseServerClientFromRequest } from './supabase-ssr'; +import { logSecurityEvent, logUserActivity } from './logger'; +import type { AstroCookies } from 'astro'; +import type { User, Session } from '@supabase/supabase-js'; + +// Custom error class for auth-related errors +export class AuthError extends Error { + constructor( + message: string, + public code: 'NO_SESSION' | 'INVALID_TOKEN' | 'NO_PERMISSION' | 'EXPIRED' | 'NO_ORGANIZATION', + public statusCode: number = 401 + ) { + super(message); + this.name = 'AuthError'; + } +} + +// Auth context interface +export interface AuthContext { + user: User; + session: Session; + isAdmin: boolean; + isSuperAdmin: boolean; + organizationId: string | null; +} + +// Type guard for authentication +export function isAuthenticated(auth: AuthContext | null): auth is AuthContext { + return auth !== null; +} + +/** + * Universal auth verification function + * Works with both Request objects (API routes) and AstroCookies (Astro pages) + */ +export async function verifyAuth(requestOrCookies: Request | AstroCookies): PromiseUser ID: {auth.user.id}
Email: {auth.user.email}
Is Admin: {auth.isAdmin ? 'Yes' : 'No'}
+Is Super Admin: {auth.isSuperAdmin ? 'Yes' : 'No'}
+Organization ID: {auth.organizationId || 'None'}
Token Type: {auth.session.token_type}
+Expires At: {new Date((auth.session.expires_at || 0) * 1000).toLocaleString()}
+Access Token: {auth.session.access_token.substring(0, 20)}...
You are not logged in or your session has expired.
+ {authError && ( +Error: {authError}
{cookies}
+ {JSON.stringify(headers, null, 2)}
+
+// In Astro pages
+import { verifyAuth, requireAuth } from '../lib/auth-unified';
+
+// Check auth (returns null if not authenticated)
+const auth = await verifyAuth(Astro.request);
+
+// Require auth (throws if not authenticated)
+const auth = await requireAuth(Astro.request);
+
+// Require admin
+const auth = await requireAdmin(Astro.request);
+
+