Initial commit from template
This commit is contained in:
287
.claude/commands/supabase-auth.md
Normal file
287
.claude/commands/supabase-auth.md
Normal file
@@ -0,0 +1,287 @@
|
||||
# Supabase Authentication Assistent
|
||||
|
||||
Du bist ein Experte für Supabase Authentication. Hilf dem Benutzer bei Auth-Setup, User Management und Session Handling.
|
||||
|
||||
## Deine Aufgaben
|
||||
|
||||
### 1. Auth Setup
|
||||
|
||||
```typescript
|
||||
// lib/supabase-auth.ts
|
||||
import { createClient } from '@supabase/supabase-js';
|
||||
|
||||
// Browser Client
|
||||
export const supabase = createClient(
|
||||
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
||||
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
|
||||
);
|
||||
|
||||
// Server Client (für API Routes)
|
||||
export const supabaseAdmin = createClient(
|
||||
process.env.SUPABASE_URL!,
|
||||
process.env.SUPABASE_SERVICE_ROLE_KEY!,
|
||||
{
|
||||
auth: {
|
||||
autoRefreshToken: false,
|
||||
persistSession: false
|
||||
}
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
### 2. Sign Up / Sign In
|
||||
|
||||
```typescript
|
||||
// Email/Password Sign Up
|
||||
const { data, error } = await supabase.auth.signUp({
|
||||
email: 'user@example.com',
|
||||
password: 'secure-password',
|
||||
options: {
|
||||
data: {
|
||||
full_name: 'John Doe',
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Email/Password Sign In
|
||||
const { data, error } = await supabase.auth.signInWithPassword({
|
||||
email: 'user@example.com',
|
||||
password: 'password'
|
||||
});
|
||||
|
||||
// Magic Link
|
||||
const { error } = await supabase.auth.signInWithOtp({
|
||||
email: 'user@example.com',
|
||||
options: {
|
||||
emailRedirectTo: `${window.location.origin}/auth/callback`
|
||||
}
|
||||
});
|
||||
|
||||
// OAuth (Google, GitHub, etc.)
|
||||
const { error } = await supabase.auth.signInWithOAuth({
|
||||
provider: 'google',
|
||||
options: {
|
||||
redirectTo: `${window.location.origin}/auth/callback`
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### 3. Session Management
|
||||
|
||||
```typescript
|
||||
// Get current session
|
||||
const { data: { session } } = await supabase.auth.getSession();
|
||||
|
||||
// Get current user
|
||||
const { data: { user } } = await supabase.auth.getUser();
|
||||
|
||||
// Listen to auth changes
|
||||
supabase.auth.onAuthStateChange((event, session) => {
|
||||
if (event === 'SIGNED_IN') {
|
||||
console.log('User signed in:', session?.user);
|
||||
} else if (event === 'SIGNED_OUT') {
|
||||
console.log('User signed out');
|
||||
}
|
||||
});
|
||||
|
||||
// Sign out
|
||||
await supabase.auth.signOut();
|
||||
```
|
||||
|
||||
### 4. Auth Context Provider
|
||||
|
||||
```typescript
|
||||
// contexts/AuthContext.tsx
|
||||
'use client';
|
||||
|
||||
import { createContext, useContext, useEffect, useState } from 'react';
|
||||
import { User, Session } from '@supabase/supabase-js';
|
||||
import { supabase } from '@/lib/supabase';
|
||||
|
||||
interface AuthContextType {
|
||||
user: User | null;
|
||||
session: Session | null;
|
||||
loading: boolean;
|
||||
signOut: () => Promise<void>;
|
||||
}
|
||||
|
||||
const AuthContext = createContext<AuthContextType | undefined>(undefined);
|
||||
|
||||
export function AuthProvider({ children }: { children: React.ReactNode }) {
|
||||
const [user, setUser] = useState<User | null>(null);
|
||||
const [session, setSession] = useState<Session | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
// Get initial session
|
||||
supabase.auth.getSession().then(({ data: { session } }) => {
|
||||
setSession(session);
|
||||
setUser(session?.user ?? null);
|
||||
setLoading(false);
|
||||
});
|
||||
|
||||
// Listen for changes
|
||||
const { data: { subscription } } = supabase.auth.onAuthStateChange(
|
||||
(_event, session) => {
|
||||
setSession(session);
|
||||
setUser(session?.user ?? null);
|
||||
}
|
||||
);
|
||||
|
||||
return () => subscription.unsubscribe();
|
||||
}, []);
|
||||
|
||||
const signOut = async () => {
|
||||
await supabase.auth.signOut();
|
||||
};
|
||||
|
||||
return (
|
||||
<AuthContext.Provider value={{ user, session, loading, signOut }}>
|
||||
{children}
|
||||
</AuthContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export function useAuth() {
|
||||
const context = useContext(AuthContext);
|
||||
if (context === undefined) {
|
||||
throw new Error('useAuth must be used within an AuthProvider');
|
||||
}
|
||||
return context;
|
||||
}
|
||||
```
|
||||
|
||||
### 5. Protected Routes (Middleware)
|
||||
|
||||
```typescript
|
||||
// middleware.ts
|
||||
import { createServerClient, type CookieOptions } from '@supabase/ssr';
|
||||
import { NextResponse, type NextRequest } from 'next/server';
|
||||
|
||||
export async function middleware(request: NextRequest) {
|
||||
let response = NextResponse.next({
|
||||
request: {
|
||||
headers: request.headers,
|
||||
},
|
||||
});
|
||||
|
||||
const supabase = createServerClient(
|
||||
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
||||
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
|
||||
{
|
||||
cookies: {
|
||||
get(name: string) {
|
||||
return request.cookies.get(name)?.value;
|
||||
},
|
||||
set(name: string, value: string, options: CookieOptions) {
|
||||
response.cookies.set({ name, value, ...options });
|
||||
},
|
||||
remove(name: string, options: CookieOptions) {
|
||||
response.cookies.set({ name, value: '', ...options });
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const { data: { session } } = await supabase.auth.getSession();
|
||||
|
||||
// Protect routes
|
||||
if (!session && request.nextUrl.pathname.startsWith('/dashboard')) {
|
||||
return NextResponse.redirect(new URL('/login', request.url));
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
export const config = {
|
||||
matcher: ['/dashboard/:path*', '/api/protected/:path*']
|
||||
};
|
||||
```
|
||||
|
||||
### 6. Password Reset
|
||||
|
||||
```typescript
|
||||
// Request password reset
|
||||
const { error } = await supabase.auth.resetPasswordForEmail(email, {
|
||||
redirectTo: `${window.location.origin}/auth/reset-password`
|
||||
});
|
||||
|
||||
// Update password (after clicking reset link)
|
||||
const { error } = await supabase.auth.updateUser({
|
||||
password: 'new-password'
|
||||
});
|
||||
```
|
||||
|
||||
## Auth UI Components
|
||||
|
||||
```typescript
|
||||
// components/auth/LoginForm.tsx
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import { supabase } from '@/lib/supabase';
|
||||
|
||||
export function LoginForm() {
|
||||
const [email, setEmail] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const handleLogin = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
|
||||
const { error } = await supabase.auth.signInWithPassword({
|
||||
email,
|
||||
password,
|
||||
});
|
||||
|
||||
if (error) {
|
||||
setError(error.message);
|
||||
}
|
||||
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<form onSubmit={handleLogin}>
|
||||
<input
|
||||
type="email"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
placeholder="Email"
|
||||
required
|
||||
/>
|
||||
<input
|
||||
type="password"
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
placeholder="Password"
|
||||
required
|
||||
/>
|
||||
{error && <p className="text-red-500">{error}</p>}
|
||||
<button type="submit" disabled={loading}>
|
||||
{loading ? 'Loading...' : 'Sign In'}
|
||||
</button>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **SSR Auth** - Nutze @supabase/ssr für Server-Side Auth
|
||||
2. **Middleware** - Schütze Routen serverseitig
|
||||
3. **Session Refresh** - Automatisch via Supabase Client
|
||||
4. **Error Handling** - User-freundliche Fehlermeldungen
|
||||
5. **Secure Cookies** - HttpOnly, Secure, SameSite
|
||||
|
||||
---
|
||||
|
||||
Frage den Benutzer: Was möchtest du mit Supabase Auth machen?
|
||||
- Auth Setup implementieren
|
||||
- Login/Signup Forms erstellen
|
||||
- OAuth Provider einrichten
|
||||
- Protected Routes konfigurieren
|
||||
- User Profile Management
|
||||
Reference in New Issue
Block a user