diff --git a/docs/content/2.core-concepts/4.auto-imports-aliases.md b/docs/content/2.core-concepts/4.auto-imports-aliases.md index ba7269f..2a99d79 100644 --- a/docs/content/2.core-concepts/4.auto-imports-aliases.md +++ b/docs/content/2.core-concepts/4.auto-imports-aliases.md @@ -9,7 +9,7 @@ description: What the module registers for you. Use auto-imported utilities from @onmax/nuxt-better-auth. - Client (auto-imported in Vue): `useUserSession()`, `useSignIn()`, `useSignUp()` -- Server (auto-imported in `server/`): `serverAuth(event?)`, `getRequestSession(event)`, `getUserSession(event)`, `setSessionCookie(event, token)`, `requireUserSession(event, options?)` +- Server (auto-imported in `server/`): `serverAuth(event?)`, `getRequestSession(event)`, `getUserSession(event)`, `createSession(event, userId)`, `setSessionCookie(event, token)`, `requireUserSession(event, options?)` - Component: `` 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 @@ -33,6 +33,7 @@ Source: https://github.com/nuxt-modules/better-auth - `serverAuth(event?)` - `getRequestSession(event)` - `getUserSession(event)` +- `createSession(event, userId)` - `setSessionCookie(event, token)` - `requireUserSession(event, options?)` @@ -56,6 +57,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. `getUserSession(event)` does not memoize by itself. +Use `createSession(event, userId)` when a custom server handler finishes its own verification logic and needs a Better Auth session record without reaching into module internals. Use `setSessionCookie(event, token)` when a custom server handler completes its own verification step and needs to attach a Better Auth session cookie to the response. ### Client Composables (auto-imported in Vue components) diff --git a/docs/content/5.api/2.server-utils.md b/docs/content/5.api/2.server-utils.md index 97052bb..a31581b 100644 --- a/docs/content/5.api/2.server-utils.md +++ b/docs/content/5.api/2.server-utils.md @@ -103,6 +103,24 @@ export default defineServerAuth({ This uses Better Auth's plugin API and does not require a module-specific option. :: +## createSession + +Creates a Better Auth session for a user and returns the created session record. Use this helper in custom server-side authentication flows after your handler verifies the user identity. + +```ts [server/api/custom-auth.post.ts] +export default defineEventHandler(async (event) => { + const userId = await verifyCustomLoginAndReturnUserId(event) + const session = await createSession(event, userId) + + return { + sessionId: session.id, + token: session.token, + } +}) +``` + +Pair this helper with your preferred cookie strategy. When you also use the module cookie helper, you can set the returned token on the response after creating the session. + ## setSessionCookie Sets the Better Auth session token cookie on the current response. Use this helper in custom server-side authentication flows after you obtain or create a valid Better Auth session token. diff --git a/src/runtime/server/utils/session.ts b/src/runtime/server/utils/session.ts index 793de8d..d00c35e 100644 --- a/src/runtime/server/utils/session.ts +++ b/src/runtime/server/utils/session.ts @@ -1,4 +1,4 @@ -import type { AppSession, RequireSessionOptions } from '#nuxt-better-auth' +import type { AppSession, AuthSession, RequireSessionOptions } from '#nuxt-better-auth' import type { H3Event } from 'h3' import { createError } from 'h3' import { matchesUser } from '../../utils/match-user' @@ -323,6 +323,11 @@ export async function setSessionCookie(event: H3Event, token: string): Promise { + const context = await getServerAuthContext(event) + return context.internalAdapter.createSession?.(userId, false) as Promise +} + export async function requireUserSession(event: H3Event, options?: RequireSessionOptions): Promise { const session = await getRequestSession(event) diff --git a/test/get-request-session.test.ts b/test/get-request-session.test.ts index 3daf62a..2449d55 100644 --- a/test/get-request-session.test.ts +++ b/test/get-request-session.test.ts @@ -353,3 +353,33 @@ describe('setSessionCookie', () => { expect(getSessionMock).toHaveBeenCalledTimes(1) }) }) + +describe('createSession', () => { + beforeEach(() => { + vi.clearAllMocks() + getSessionMock.mockReset() + createSessionMock.mockReset() + }) + + it('delegates to Better Auth internalAdapter.createSession with dontRememberMe disabled', async () => { + createSessionMock.mockResolvedValue({ + id: 's1', + userId: 'u1', + token: 'token-1', + expiresAt: new Date(), + createdAt: new Date(), + updatedAt: new Date(), + }) + + const { createSession } = await import('../src/runtime/server/utils/session') + const event = createEvent() + const session = await createSession(event, 'u1') + + expect(createSessionMock).toHaveBeenCalledWith('u1', false) + expect(session).toMatchObject({ + id: 's1', + userId: 'u1', + token: 'token-1', + }) + }) +})