Auth
Session Management
How sessions work and how to configure them
Sessions track authenticated users across requests. Better Auth handles session storage, cookies, and expiration automatically.
Default Configuration
Out of the box, sessions are configured with:
| Setting | Default | Description |
|---|---|---|
expiresIn | 7 days | Session duration |
updateAge | 24 hours | How often to refresh |
Sessions refresh automatically when users are active.
How Sessions Work
- Sign in: User authenticates via email OTP or OAuth
- Create session: Better Auth creates a session record in your database
- Set cookie: A secure HTTP-only cookie is sent to the browser
- Validate requests: On each request, the cookie is validated against the database
- Refresh: Active sessions are automatically extended
Customizing Session Duration
import { } from "better-auth"
export const = ({
// ...
: {
: 60 * 60 * 24 * 30, // 30 days
: 60 * 60 * 24 // Refresh every 24 hours
}
})Common Configurations
| Use Case | expiresIn | updateAge |
|---|---|---|
| Standard app | 7 days | 24 hours |
| High security | 1 hour | 15 minutes |
| "Remember me" | 30 days | 24 hours |
| Mobile app | 90 days | 7 days |
Session Storage
Sessions are stored in your database via the Drizzle adapter:
database: (, {
: "pg",
: {
: // Your sessions table
}
})The sessions table stores:
id- Unique session IDuserId- Associated usertoken- Session token (in cookie)expiresAt- Expiration timestampipAddress- Client IP (optional)userAgent- Browser info (optional)
Accessing Session Data
In Server Components
import { } from "@/lib/auth"
import { } from "next/headers"
export default async function () {
const = await .api.getSession({
: await ()
})
// session.user - User object
// session.session - Session metadata
}In Client Components
"use client"
import { } from "@startupkit/auth"
export function () {
const { , , } = ()
}Session Metadata
const = await .api.getSession({
: await ()
})
.(.session)
// {
// id: "session_123",
// userId: "user_456",
// expiresAt: Date,
// ipAddress: "192.168.1.1",
// userAgent: "Mozilla/5.0..."
// }Invalidating Sessions
Sign Out Current Session
"use client"
import { } from "@startupkit/auth"
export function () {
const { } = ()
return < ={}>Sign Out</>
}Sign Out All Sessions
For "sign out everywhere" functionality:
import { } from "@/lib/auth"
import { } from "next/headers"
export async function () {
const = await .api.getSession({
: await ()
})
if () {
// Delete all sessions for this user
await db.delete(sessions)
.where(eq(sessions.userId, .user.id))
}
}Session Refresh
Sessions automatically refresh when updateAge has passed:
- User makes a request
- Better Auth checks session age
- If older than
updateAge, extendsexpiresAt - User continues without interruption
This ensures active users stay logged in.
Cookie Configuration
Better Auth uses secure HTTP-only cookies:
export const = ({
// Cookies are configured automatically, but you can customize:
: {
: "myapp", // Custom cookie prefix
: {
: true,
: ".myapp.com" // Share across subdomains
}
}
})Cookie Settings
| Setting | Value |
|---|---|
httpOnly | true (can't be accessed by JS) |
secure | true in production |
sameSite | lax |
path | / |
Multiple Sessions
Users can have multiple active sessions (different devices):
// Get all sessions for current user
const = await .()
.()
.((.userId, .))
// Display in UI
<>
{.( => (
< ={.}>
{.} - {.}
< ={() => (.)}>
Revoke
</>
</>
))}
</ul>Security Considerations
IP Address Validation
Track IP for security monitoring:
const = await .api.getSession({
: await ()
})
// Check for suspicious IP changes
if (.session.ipAddress !== ) {
// Log security event
await ({
: "SUSPICIOUS_IP_CHANGE",
: .user.id
})
}Force Re-authentication
For sensitive actions, require fresh authentication:
export async function () {
const = await .api.getSession({
: await ()
})
// Check when session was created
const = .() - .session.createdAt.getTime()
const = 15 * 60 * 1000
if ( > ) {
throw new ("Please re-authenticate for this action")
}
// Proceed with sensitive action
}Debugging Sessions
Check Session in Database
SELECT * FROM "Session" WHERE "userId" = 'user_123';Log Session Events
export const = ({
: {
: async () => {
if (.newSession) {
.("New session created:", .newSession.id)
}
}
}
})Next Steps
- requireAuth - Protect pages with redirect
- withAuth - Get session for conditional rendering
- useAuth - Client-side auth hook