User Authentication Guide
Learn how to implement authentication in your Indie Kit app using useUser hook, auth() function, and withAuthRequired middleware
User Authentication Guide 🔐
Indie Kit provides powerful authentication tools that you can use throughout your application. Let's explore how to implement authentication in different contexts! 🚀
Client-Side Authentication with useUser 💻
The useUser
hook is perfect for client components. It provides user data and loading states:
'use client'
import { useUser } from '@/lib/users/useUser'
export default function ProfileButton() {
const { user, isLoading } = useUser()
if (isLoading) {
return <div>Loading...</div>
}
if (!user) {
return <button onClick={() => signIn()}>Sign In</button>
}
return (
<div className="flex items-center gap-2">
<img
src={user.image}
alt={user.name}
className="w-8 h-8 rounded-full"
/>
<span>{user.name}</span>
</div>
)
}
Features of useUser 🎯
- 🔄 Automatic revalidation
- 🎭 Type-safe user data
- ⌛ Loading states
- 🚫 Error handling
- 🔌 Offline support
Server-Side Authentication with auth() 🔒
For server components and API routes, use the auth()
function:
// src/app/profile/page.tsx
import { auth } from '@/auth'
import { redirect } from 'next/navigation'
export default async function ProfilePage() {
const session = await auth()
if (!session) {
redirect('/login')
}
return (
<div className="p-6">
<h1>Welcome {session.user.name}!</h1>
<p>Email: {session.user.email}</p>
</div>
)
}
When to Use auth() 📋
- ✅ Server Components
- ✅ API Routes
- ✅ Server Actions
- ✅ Middleware
- ✅ Layout Components
Protected API Routes with withAuthRequired 🛡️
Secure your API routes using the withAuthRequired
middleware:
// src/app/api/app/user-settings/route.ts
import { withAuthRequired } from '@/lib/auth/withAuthRequired'
import { NextResponse } from 'next/server'
export const GET = withAuthRequired(async (req, context) => {
const { session } = context
// Access user data from session
const userId = session.user.id
// Your protected API logic here
const settings = await getUserSettings(userId)
return NextResponse.json(settings)
})
export const POST = withAuthRequired(async (req, context) => {
const { session } = context
const data = await req.json()
// Update user settings
await updateUserSettings(session.user.id, data)
return NextResponse.json({ success: true })
})
Benefits of withAuthRequired 🎯
- 🔒 Automatic authentication checking
- 🎭 Type-safe session data
- 🚫 Automatic error responses
- 📝 Session context in handler
- ⚡ Zero-config setup
Authentication Flow Examples 🌊
Protected Dashboard Page
// src/app/(in-app)/dashboard/page.tsx
import { auth } from '@/auth'
import { DashboardMetrics } from '@/components/dashboard/metrics'
export default async function DashboardPage() {
const session = await auth()
return (
<div className="p-6">
<h1>Dashboard</h1>
<DashboardMetrics userId={session.user.id} />
</div>
)
}
User Settings Component
'use client'
import { useUser } from '@/lib/users/useUser'
import { useState } from 'react'
export function UserSettings() {
const { user, isLoading } = useUser()
const [name, setName] = useState(user?.name)
if (isLoading) return <div>Loading settings...</div>
if (!user) return <div>Please sign in</div>
return (
<form className="space-y-4">
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
className="input"
/>
<button type="submit" className="btn">
Save Changes
</button>
</form>
)
}
Best Practices 💫
-
Choose the Right Method
- 🖥️
useUser
for client components - 🔒
auth()
for server components - 🛡️
withAuthRequired
for API routes
- 🖥️
-
Error Handling
- Always handle loading states
- Provide clear error messages
- Implement proper redirects
-
Security Tips
- Validate on both client and server
- Never expose sensitive data
- Use HTTPS in production
- Implement proper CORS policies
-
Performance
- Cache authentication state
- Use loading skeletons
- Implement proper revalidation
Now you're ready to implement authentication throughout your Indie Kit application! Remember to always validate user permissions and handle edge cases appropriately. 🚀