Authentication
Secure authentication with email/password, OAuth providers, and magic links.
Overview
Lubes Auth provides a complete authentication system out of the box. It handles user registration, login, session management, and integrates with row-level security.
Multiple Providers
Email, OAuth, magic links
JWT Sessions
Secure token-based auth
RLS Integration
Database-level security
Email/Password Authentication
Sign Up
import { auth } from '@/lib/lubes'
// Sign up with email and password
const { user, session, error } = await auth.signUp({
email: 'user@example.com',
password: 'secure-password-123',
metadata: {
name: 'John Doe',
avatar_url: 'https://example.com/avatar.png',
},
})
if (error) {
console.error('Sign up failed:', error.message)
return
}
console.log('Welcome!', user.email)Sign In
// Sign in with email and password
const { user, session, error } = await auth.signIn({
email: 'user@example.com',
password: 'secure-password-123',
})
if (error) {
if (error.code === 'invalid_credentials') {
console.error('Wrong email or password')
}
return
}
// Session tokens are automatically stored
console.log('Signed in as:', user.email)Password Reset
// Request password reset email
await auth.resetPasswordForEmail('user@example.com', {
redirectTo: 'https://myapp.com/reset-password',
})
// User clicks link in email, then:
await auth.updatePassword('new-secure-password-456')OAuth Providers
Enable social login with popular OAuth providers. Configure providers in your dashboard settings.
Supported Providers
Google
GitHub
GitLab
Discord
Twitter
Apple
Microsoft
Slack
OAuth Sign In
// Redirect to OAuth provider
await auth.signInWithOAuth({
provider: 'github',
redirectTo: 'https://myapp.com/auth/callback',
scopes: ['user:email'], // Optional additional scopes
})
// In your callback page, the session is automatically set
// Just redirect to your app
const { user, session } = await auth.getSession()Link OAuth to Existing Account
// User must be signed in first
await auth.linkOAuthAccount({
provider: 'google',
redirectTo: 'https://myapp.com/settings/accounts',
})
// List linked accounts
const accounts = await auth.getLinkedAccounts()
// [{ provider: 'github', email: '...' }, { provider: 'google', email: '...' }]
// Unlink an account
await auth.unlinkOAuthAccount('google')Magic Links
Passwordless authentication via email. Users receive a one-time link that signs them in.
// Send magic link email
await auth.signInWithMagicLink({
email: 'user@example.com',
redirectTo: 'https://myapp.com/dashboard',
})
// User clicks link in email
// They're automatically signed in and redirected
// Check if user is signed in
const { user, session } = await auth.getSession()
if (user) {
console.log('Signed in via magic link!')
}Magic Link Best Practices
- β’ Links expire after 1 hour by default
- β’ Each link can only be used once
- β’ Consider rate limiting magic link requests
- β’ Always use HTTPS for redirectTo URLs
Session Management
Get Current Session
// Get current session (client-side)
const { user, session } = await auth.getSession()
if (!user) {
// Not authenticated
redirect('/login')
}
// Access user data
console.log(user.id, user.email, user.metadata)
// Access tokens
console.log(session.access_token)
console.log(session.expires_at)Session Events
// Listen for auth state changes
auth.onAuthStateChange((event, session) => {
switch (event) {
case 'SIGNED_IN':
console.log('User signed in:', session.user.email)
break
case 'SIGNED_OUT':
console.log('User signed out')
break
case 'TOKEN_REFRESHED':
console.log('Token refreshed')
break
case 'USER_UPDATED':
console.log('User profile updated')
break
}
})Sign Out
// Sign out current session
await auth.signOut()
// Sign out all sessions (all devices)
await auth.signOut({ scope: 'global' })User Management
Update User
// Update user metadata
await auth.updateUser({
metadata: {
name: 'Jane Doe',
avatar_url: 'https://example.com/new-avatar.png',
},
})
// Update email (sends verification)
await auth.updateUser({
email: 'newemail@example.com',
})
// Update password
await auth.updateUser({
password: 'new-secure-password',
})Delete Account
// User can delete their own account
await auth.deleteUser()
// This will:
// - Delete the user record
// - Invalidate all sessions
// - Trigger cascading deletes based on your DB schemaRow-Level Security
Integrate authentication with PostgreSQL RLS policies for database-level security.
SQL Migration
-- Enable RLS on a table
ALTER TABLE posts ENABLE ROW LEVEL SECURITY;
-- Policy: Users can only see their own posts
CREATE POLICY "Users can view own posts"
ON posts FOR SELECT
USING (auth.uid() = user_id);
-- Policy: Users can only insert their own posts
CREATE POLICY "Users can insert own posts"
ON posts FOR INSERT
WITH CHECK (auth.uid() = user_id);
-- Policy: Users can only update their own posts
CREATE POLICY "Users can update own posts"
ON posts FOR UPDATE
USING (auth.uid() = user_id);
-- Policy: Users can only delete their own posts
CREATE POLICY "Users can delete own posts"
ON posts FOR DELETE
USING (auth.uid() = user_id);The auth.uid() function returns the current user's ID from the JWT token. RLS policies are automatically enforced for all database queries.