Skip to content

Session Management

🔒 Configure how user sessions are created, stored, and validated.

Why Session Management?

ConcernSession Handles It
"Remember me"Session expiration settings
Multiple devicesSession per device tracking
SecuritySession invalidation on logout
Token refreshAutomatic re-authentication

🟢 Beginner Tip: Sessions are how your app "remembers" that a user is logged in. Without sessions, users would have to log in on every page load.


Session Configuration

typescript
import { auth } from "nevr/plugins/auth"

auth({
  session: {
    // Session duration (default: 7 days)
    expiresIn: 60 * 60 * 24 * 7, // seconds
    
    // Update session on each request
    updateAge: 60 * 60 * 24, // Update if session is 1 day old
    
    // Cookie settings
    cookie: {
      name: "nevr.session_token",
      secure: process.env.NODE_ENV === "production",
      sameSite: "lax",
      path: "/",
      httpOnly: true,
    },
  },
})

Session Storage

By default, sessions are stored in your database. The auth plugin creates a session table automatically.

Session Schema

typescript
// Auto-generated by auth plugin
{
  id: string,           // Session ID
  userId: string,       // Reference to user
  token: string,        // Session token (hashed)
  expiresAt: datetime,  // When session expires
  ipAddress: string,    // Client IP
  userAgent: string,    // Browser info
  createdAt: datetime,
  updatedAt: datetime,
}

Client Usage

Get Current Session

typescript
import { client } from "./lib/client"

// One-time fetch
const { data } = await client.auth.getSession()

if (data) {
  console.log("Logged in as:", data.user.email)
  console.log("Session expires:", data.session.expiresAt)
} else {
  console.log("Not logged in")
}
typescript
// React example with reactive session
import { useStore } from "@nanostores/react"
import { client } from "./lib/client"

function UserStatus() {
  const session = useStore(client.$session)
  
  if (session.isPending) {
    return <div>Loading...</div>
  }
  
  if (!session.data) {
    return <div>Not logged in</div>
  }
  
  return <div>Welcome, {session.data.user.name}!</div>
}

Session Revalidation

Configure automatic session refresh:

typescript
import { authClient } from "nevr/plugins/auth/client"

import { createTypedClient } from "nevr/client"
import { authClient } from "nevr/plugins/auth/client"
import type { API } from "../server/api"

const client = createTypedClient<API>({
  plugins: [
    authClient({
      session: {
        // Refetch session every 5 minutes
        refetchInterval: 60 * 5,
        
        // Refetch when tab gets focus
        refetchOnWindowFocus: true,
      },
    }),
  ],
})

React Integration

Auth Provider Pattern

tsx
import { createContext, useContext, useEffect, useState } from "react"
import { useStore } from "@nanostores/react"
import { client } from "./lib/client"

const AuthContext = createContext<{
  user: User | null
  isLoading: boolean
  signOut: () => Promise<void>
}>({
  user: null,
  isLoading: true,
  signOut: async () => {},
})

export function AuthProvider({ children }: { children: React.ReactNode }) {
  const session = useStore(client.$session)
  
  const signOut = async () => {
    await client.auth.signOut()
  }
  
  return (
    <AuthContext.Provider value={{
      user: session.data?.user ?? null,
      isLoading: session.isPending,
      signOut,
    }}>
      {children}
    </AuthContext.Provider>
  )
}

export function useAuth() {
  return useContext(AuthContext)
}

Usage in Components

tsx
function Dashboard() {
  const { user, isLoading, signOut } = useAuth()
  
  if (isLoading) return <Spinner />
  if (!user) return <Redirect to="/login" />
  
  return (
    <div>
      <h1>Welcome, {user.name}</h1>
      <button onClick={signOut}>Sign Out</button>
    </div>
  )
}

Session Security

Invalidate All Sessions

Force logout from all devices:

typescript
// Server-side
await api.driver.deleteMany("session", {
  userId: user.id
})

Get Active Sessions

typescript
const { data } = await client.auth.getSession()

// Session includes device info
console.log(data.session.userAgent)  // "Mozilla/5.0..."
console.log(data.session.ipAddress)  // "192.168.1.1"

JWT vs Session Tokens

Nevr uses session tokens (not JWT) by default:

FeatureSession Tokens (Nevr)JWT
StorageDatabaseToken itself
RevocationInstantWait for expiry
SizeSmall cookieLarge token
SecurityCan't be tamperedCan be decoded
ScalabilityDB lookup requiredStateless

🟡 Intermediate Tip: Session tokens are more secure for most apps. JWT is better for microservices that need stateless auth.


Session Endpoints

EndpointMethodDescription
/auth/sessionGETGet current session
/auth/sign-outPOSTDestroy session
/auth/sessionsGETList all user sessions
/auth/sessions/:idDELETERevoke specific session

Next Steps

Released under the MIT License.