Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/content/2.core-concepts/1.server-auth.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Use server-side auth utilities in @nuxtjs/better-auth.
- `getUserSession(event)` — get current session (auto-imported in `server/`)
- `requireUserSession(event, options?)` — throws 401 if not authenticated, supports role matching
- `getRequestSession(event)` — request-cached session, preferred over repeated `getUserSession` in same request
- `setRequestSession(event, session)` — supply an authenticated session to downstream helpers for the current request
- `refreshSessionCookieCache(event)` — refresh Better Auth's cached session cookie after server-side session data changes
- All server utils are auto-imported, no import statements needed
```
Expand All @@ -27,6 +28,7 @@ Use this page when you need authentication state or Better Auth APIs inside Nitr
| Task | Use | Example |
|------|-----|---------|
| Get request-cached session context | `getRequestSession(event)` | Cache once per request with context-backed storage when available |
| Supply a request session | `setRequestSession(event, session)` | Reuse a session resolved by trusted server authentication |
| Get current session | `getUserSession(event)` | Check if user is logged in |
| Refresh cached session cookie | `refreshSessionCookieCache(event)` | Use after updating data returned by Better Auth session helpers |
| Require authentication | `requireUserSession(event)` | Protect an API route |
Expand Down
4 changes: 3 additions & 1 deletion docs/content/2.core-concepts/4.auto-imports-aliases.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ description: What the module registers for you.
Use auto-imported utilities from @nuxtjs/better-auth.

- Client (auto-imported in Vue): `useUserSession()`, `useUserSessionState()`, `useAuthClient()`, `useSignIn()`, `useSignUp()`, `useAuthClientAction()`, `runWithSessionRefresh()`
- Server (auto-imported in `server/`): `serverAuth(event?)`, `getRequestSession(event)`, `getUserSession(event)`, `refreshSessionCookieCache(event)`, `createSession(event, userId)`, `setSessionCookie(event, token)`, `requireUserSession(event, options?)`
- Server (auto-imported in `server/`): `serverAuth(event?)`, `getRequestSession(event)`, `setRequestSession(event, session)`, `getUserSession(event)`, `refreshSessionCookieCache(event)`, `createSession(event, userId)`, `setSessionCookie(event, token)`, `requireUserSession(event, options?)`
- Component: `<BetterAuthState>` for auth-ready rendering
- Alias `#nuxt-better-auth` exports types: `AuthUser`, `AuthSession`, `AuthSocialProviderId`
- Use `getRequestSession(event)` over repeated `getUserSession(event)` calls — it caches per request
Expand All @@ -35,6 +35,7 @@ Use this page when you want a quick inventory of what the module registers for y

- `serverAuth(event?)`
- `getRequestSession(event)`
- `setRequestSession(event, session)`
- `getUserSession(event)`
- `refreshSessionCookieCache(event)`
- `createSession(event, userId)`
Expand All @@ -59,6 +60,7 @@ export default defineEventHandler(async (event) => {
```

Use `getRequestSession(event)` when multiple handlers or middleware in the same request need session data. The helper should be preferred over repeated `getUserSession(event)` calls in the same request chain.
Use `setRequestSession(event, session)` after trusted server code authenticates a request and resolves a complete `AppSession` that downstream session helpers should reuse. The value applies only to the current request and does not set a session cookie.
`getUserSession(event)` does not memoize by itself.
Use `refreshSessionCookieCache(event)` after server-side code updates data returned by the Better Auth session. This refreshes the cached session cookie. It does not update the session or user record; perform that update first.

Expand Down
21 changes: 21 additions & 0 deletions docs/content/5.api/2.server-utils.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,27 @@ Use this helper when multiple handlers/middleware in the same request need sessi
`getRequestSession` stays type-compatible in projects that use narrowed `h3` typings where `H3Event` does not explicitly declare `context`.
::

## setRequestSession

Supplies an `AppSession | null` to `getRequestSession`, `getUserSession`, and `requireUserSession` for the rest of the current request. Use it when trusted server code authenticates a request through another mechanism, such as a verified bearer token, and resolves the complete application session itself.

```ts [server/middleware/bearer-session.ts]
export default defineEventHandler(async (event) => {
const claims = await verifyBearerToken(event)
const session = await resolveCurrentAppSession(claims)

setRequestSession(event, session)

// Later middleware and handlers reuse the supplied value.
})
```

The helper makes the supplied value authoritative immediately, so an older session lookup or refresh cannot overwrite it when that work settles. Pass `null` to cache an unauthenticated result for the current request.

::warning
`setRequestSession` trusts the supplied value. Authenticate the request and enforce bearer-token audience and scope restrictions before calling it. The helper does not create, update, or clear a Better Auth session cookie.
::

## refreshSessionCookieCache

Refreshes Better Auth's cached session cookie on the current response, then refreshes the request-cached session used by `getRequestSession(event)`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ These helpers are auto-imported inside `server/` in full mode:
- `serverAuth(event?)`
- `getUserSession(event)`
- `getRequestSession(event)`
- `setRequestSession(event, session)`
- `refreshSessionCookieCache(event)`
- `requireUserSession(event, options?)`
- `createSession(event, userId)`
Expand All @@ -19,6 +20,7 @@ These helpers are auto-imported inside `server/` in full mode:
| Access raw Better Auth APIs | `serverAuth(event)` |
| Read session if it exists | `getUserSession(event)` |
| Reuse the same session lookup in one request | `getRequestSession(event)` |
| Supply a session resolved by trusted server authentication | `setRequestSession(event, session)` |
| Refresh Better Auth's cached session cookie after server-side updates | `refreshSessionCookieCache(event)` |
| Enforce auth | `requireUserSession(event, options?)` |
| Create a session in a custom flow | `createSession(event, userId)` |
Expand All @@ -38,6 +40,20 @@ export default defineEventHandler(async (event) => {

`requireUserSession(event)` throws `401` when unauthenticated and `403` when the user match or custom rule fails.

## Supply a verified request session

Use `setRequestSession(event, session)` when another server authentication layer verifies the request and resolves a complete `AppSession` for existing session helpers to reuse.

```ts
const claims = await verifyBearerToken(event)
const session = await resolveCurrentAppSession(claims)

setRequestSession(event, session)
await requireUserSession(event)
```

The supplied value applies only to the current request and does not set a session cookie. Authenticate the value and enforce bearer-token audience and scope restrictions before calling the helper.

## Refresh cached session data

Use `refreshSessionCookieCache(event)` after server-side code updates data returned by `auth.api.getSession()`, `getUserSession(event)`, or `getRequestSession(event)`.
Expand Down
37 changes: 25 additions & 12 deletions src/runtime/server/utils/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,46 +306,59 @@ function updateRequestHeaders(event: ServerEvent, sessionCookie: string, cleared

export async function getRequestSession(event: ServerEvent): Promise<AppSession | null> {
const context = getRequestSessionContext(event)
if (context.requestSession !== undefined)
return context.requestSession

const inFlight = context[requestSessionLoadKey]
if (inFlight)
return inFlight

if (context.requestSession !== undefined)
return context.requestSession

const load = loadSession(event)

context[requestSessionLoadKey] = load
try {
const session = await load
context.requestSession = session
if (context[requestSessionLoadKey] === load)
context.requestSession = session
return session
}
finally {
delete context[requestSessionLoadKey]
if (context[requestSessionLoadKey] === load)
delete context[requestSessionLoadKey]
}
}

export async function getUserSession(event: ServerEvent): Promise<AppSession | null> {
const context = getRequestSessionContext(event)
if (context.requestSession !== undefined)
return context.requestSession

const inFlight = context[requestSessionLoadKey]
if (inFlight)
return inFlight

if (context.requestSession !== undefined)
return context.requestSession

return loadSession(event)
}

export function setRequestSession(event: ServerEvent, session: AppSession | null): void {
const context = getRequestSessionContext(event)
context.requestSession = session
delete context[requestSessionLoadKey]
}

export async function refreshSessionCookieCache(event: ServerEvent): Promise<AppSession | null> {
const context = getRequestSessionContext(event)
const inFlight = context[requestSessionLoadKey]
if (inFlight)
await inFlight.catch(() => undefined)
const load = (inFlight ?? Promise.resolve(null)).catch(() => undefined).then(async () => {
if (context[requestSessionLoadKey] !== load)
return context.requestSession ?? null

delete context.requestSession
const { headers, response } = await loadFreshSession(event)

if (context[requestSessionLoadKey] !== load)
return context.requestSession ?? null

delete context.requestSession
const load = loadFreshSession(event).then(({ headers, response }) => {
appendSetCookieHeaders(event, headers)
context.requestSession = response
return response
Expand Down
Loading
Loading