Supabase Authentication
Use Supabase Auth for managed authentication with social providers, email/password, and more.
Backend Setup
Environment Variables
BOARDS_AUTH_PROVIDER=supabase
SUPABASE_URL=https://your-project-id.supabase.co
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key
Or configure via JSON:
BOARDS_AUTH_PROVIDER=supabase
BOARDS_AUTH_CONFIG='{"url": "https://your-project.supabase.co", "service_role_key": "your-key"}'
Supabase Project Setup
- Create a new project at supabase.com
- Go to Settings > API to get your URL and keys
- Configure authentication providers in Auth > Providers
- Set up redirect URLs in Auth > URL Configuration
Frontend Setup
Installation
npm install @weirdfingers/boards @supabase/supabase-js
Provider Configuration
import { SupabaseAuthProvider, AuthProvider } from "@weirdfingers/boards";
const authProvider = new SupabaseAuthProvider({
url: process.env.NEXT_PUBLIC_SUPABASE_URL!,
anonKey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
tenantId: "my-company", // optional
});
function App() {
return <AuthProvider provider={authProvider}>{/* Your app */}</AuthProvider>;
}
Configuration Options
| Option | Default | Description |
|---|---|---|
url | Required | Supabase project URL |
anonKey | Required | Supabase anonymous/public key |
tenantId | undefined | Tenant ID for multi-tenant apps |
Usage
Email/Password Sign Up
import { useAuth } from "@weirdfingers/boards";
function SignUpForm() {
const { signIn } = useAuth();
const handleSubmit = async (e: FormEvent) => {
e.preventDefault();
const formData = new FormData(e.target as HTMLFormElement);
try {
await signIn({
type: "signup",
email: formData.get("email") as string,
password: formData.get("password") as string,
options: {
data: {
display_name: formData.get("name") as string,
},
},
});
} catch (error) {
console.error("Sign up failed:", error);
}
};
return (
<form onSubmit={handleSubmit}>
<input name="name" placeholder="Full Name" required />
<input name="email" type="email" placeholder="Email" required />
<input name="password" type="password" placeholder="Password" required />
<button type="submit">Sign Up</button>
</form>
);
}
Email/Password Sign In
function SignInForm() {
const { signIn } = useAuth();
const handleSubmit = async (e: FormEvent) => {
e.preventDefault();
const formData = new FormData(e.target as HTMLFormElement);
try {
await signIn({
email: formData.get("email") as string,
password: formData.get("password") as string,
});
} catch (error) {
console.error("Sign in failed:", error);
}
};
return (
<form onSubmit={handleSubmit}>
<input name="email" type="email" placeholder="Email" required />
<input name="password" type="password" placeholder="Password" required />
<button type="submit">Sign In</button>
</form>
);
}
Social Authentication
function SocialAuth() {
const { signIn } = useAuth();
return (
<div>
<button onClick={() => signIn({ provider: "google" })}>
Continue with Google
</button>
<button onClick={() => signIn({ provider: "github" })}>
Continue with GitHub
</button>
<button onClick={() => signIn({ provider: "discord" })}>
Continue with Discord
</button>
</div>
);
}
Supabase Configuration
Redirect URLs
Configure these redirect URLs in your Supabase project:
Development:
http://localhost:3033/auth/callback
Production:
https://yourdomain.com/auth/callback
Email Templates
Customize email templates in Auth > Templates:
- Confirm signup
- Reset password
- Magic link
- Email change confirmation
Row Level Security (RLS)
Boards handles authorization at the application level, but you can add additional RLS policies:
-- Example: Users can only access their own data
CREATE POLICY "Users can view own profile" ON users
FOR SELECT USING (auth.uid()::text = auth_subject);
Advanced Features
Magic Links
function MagicLinkForm() {
const { signIn } = useAuth();
const handleSubmit = async (e: FormEvent) => {
e.preventDefault();
const formData = new FormData(e.target as HTMLFormElement);
await signIn({
email: formData.get("email") as string,
options: {
shouldCreateUser: true,
},
});
alert("Check your email for the magic link!");
};
return (
<form onSubmit={handleSubmit}>
<input name="email" type="email" placeholder="Email" required />
<button type="submit">Send Magic Link</button>
</form>
);
}
Password Reset
function PasswordReset() {
const [email, setEmail] = useState("");
const handleReset = async () => {
// This would call Supabase's resetPasswordForEmail
// Implementation depends on your auth provider setup
};
return (
<div>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Enter your email"
/>
<button onClick={handleReset}>Reset Password</button>
</div>
);
}
Security Considerations
RLS Policies
While Boards handles authorization, consider adding Supabase RLS as defense-in-depth:
-- Enable RLS on your tables
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
ALTER TABLE boards ENABLE ROW LEVEL SECURITY;
-- Example policies
CREATE POLICY "Users can access own tenant data" ON boards
FOR ALL USING (
tenant_id = (
SELECT tenant_id FROM users
WHERE auth_subject = auth.uid()::text
)
);
Service Role Key
- Never expose service role key in frontend code
- Use environment variables for server-side configuration
- Rotate keys regularly
- Monitor usage in Supabase dashboard
CORS Configuration
Supabase automatically handles CORS for your domain, but verify your settings in Auth > URL Configuration.
Troubleshooting
Common Issues
"Invalid login credentials" error:
- Check email/password are correct
- Verify user has confirmed their email
- Check Auth > Users in Supabase dashboard
Redirect not working:
- Verify redirect URLs are configured correctly
- Check for typos in URLs
- Ensure HTTPS in production
Token not persisting:
- Check Supabase session configuration
- Verify localStorage isn't being cleared
- Check browser privacy settings
Debug Mode
Enable Supabase debug logging:
const authProvider = new SupabaseAuthProvider({
url: process.env.NEXT_PUBLIC_SUPABASE_URL!,
anonKey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
options: {
debug: true,
},
});
Checking Supabase Logs
Monitor authentication in your Supabase dashboard:
- Go to Auth > Logs to see authentication attempts
- Check Logs > API for request details
- Use Logs > Realtime for live debugging