Indie Kit DocsIndie Kit Docs
Tutorials

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 💫

  1. Choose the Right Method

    • 🖥️ useUser for client components
    • 🔒 auth() for server components
    • 🛡️ withAuthRequired for API routes
  2. Error Handling

    • Always handle loading states
    • Provide clear error messages
    • Implement proper redirects
  3. Security Tips

    • Validate on both client and server
    • Never expose sensitive data
    • Use HTTPS in production
    • Implement proper CORS policies
  4. 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. 🚀