Skip to content

Commit 074bdf0

Browse files
authored
feat: expose request origin in server auth context (#304)
1 parent f30fdde commit 074bdf0

10 files changed

Lines changed: 54 additions & 12 deletions

File tree

docs/content/1.getting-started/2.configuration.md

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -198,16 +198,28 @@ import { defineServerAuth } from '@onmax/nuxt-better-auth/config'
198198
export default defineServerAuth((ctx) => ({
199199
emailAndPassword: { enabled: true },
200200

201-
// Access the database connection via ctx.db when using NuxtHub
202-
// Example: pass ctx.db to your own plugin/helper.
203-
// Do not set `database` here when using module-managed adapters.
204201
appName: ctx.runtimeConfig.public.siteUrl ? 'Better Auth App' : 'Better Auth',
202+
}))
203+
```
204+
205+
- `ctx.runtimeConfig`: Nuxt runtime config.
206+
- `ctx.db`: NuxtHub database connection when NuxtHub DB is enabled. Do not set `database` when using module-managed adapters.
207+
- `ctx.requestOrigin`: Current request origin when auth is created with `serverAuth(event)`.
208+
209+
Use `requestOrigin` when Better Auth config needs the current request host, such as trusted origins:
210+
211+
```ts [server/auth.config.ts]
212+
import { defineServerAuth } from '@onmax/nuxt-better-auth/config'
205213

206-
// Access runtime config if needed
207-
// someValue: ctx.runtimeConfig.customKey
214+
export default defineServerAuth(({ requestOrigin }) => ({
215+
trustedOrigins: requestOrigin ? [requestOrigin] : [],
208216
}))
209217
```
210218

219+
::note
220+
For configured canonical URLs, read `runtimeConfig.public.siteUrl`. `requestOrigin` is optional and only available when auth is created from a request event. If allowed origins vary while using an explicit `siteUrl`, configure those origins explicitly or use Better Auth's `trustedOrigins` function form, because the auth instance can be cached.
221+
::
222+
211223
### Session Enrichment
212224

213225
You can enrich session payloads with Better Auth's `custom-session` plugin through `plugins` in `defineServerAuth`. This module does not provide a separate `requestSession.enrich` option.

src/module/type-templates.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,15 @@ declare module '#nuxt-better-auth' {
9191
interface ServerAuthContext {
9292
runtimeConfig: RuntimeConfig
9393
db: ${hasHubDb ? `typeof import('@nuxthub/db')['db']` : 'undefined'}
94+
requestOrigin?: string
9495
}
9596
type PluginTypes = InferPluginTypes<_Config>
9697
}
9798
9899
interface _AugmentedServerAuthContext {
99100
runtimeConfig: RuntimeConfig
100101
db: ${hasHubDb ? `typeof import('@nuxthub/db')['db']` : 'undefined'}
102+
requestOrigin?: string
101103
}
102104
103105
declare module '@onmax/nuxt-better-auth/config' {

src/runtime/server/utils/auth.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ function withDevTrustedOrigins(
249249
export function serverAuth(event?: H3Event): AuthInstance {
250250
const runtimeConfig = useRuntimeConfig()
251251
const siteUrl = getBaseURL(event)
252+
const requestOrigin = resolveEventOrigin(event)
252253
const hasExplicitSiteUrl = runtimeConfig.public.siteUrl && typeof runtimeConfig.public.siteUrl === 'string'
253254
const cacheKey = hasExplicitSiteUrl ? '__explicit__' : siteUrl
254255

@@ -257,7 +258,7 @@ export function serverAuth(event?: H3Event): AuthInstance {
257258
return cached
258259

259260
const database = createDatabase()
260-
const userConfig = createServerAuth({ runtimeConfig, db }) as BetterAuthOptions & {
261+
const userConfig = createServerAuth({ runtimeConfig, db, requestOrigin }) as BetterAuthOptions & {
261262
secondaryStorage?: BetterAuthOptions['secondaryStorage']
262263
}
263264
const trustedOrigins = withDevTrustedOrigins(userConfig.trustedOrigins, Boolean(hasExplicitSiteUrl))

src/runtime/types/augment.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export interface AuthSession {
3030
export interface ServerAuthContext {
3131
runtimeConfig: Record<string, unknown>
3232
db: unknown
33+
requestOrigin?: string
3334
}
3435

3536
// Extended by generated types from configured socialProviders keys.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
import { fileURLToPath } from 'node:url'
2+
3+
const serverConfig = fileURLToPath(new URL('./server/auth.config', import.meta.url))
4+
15
export default defineNuxtConfig({
26
extends: ['../_base-module'],
7+
auth: {
8+
serverConfig,
9+
},
310
})
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
export default defineEventHandler((event) => {
2-
const auth = serverAuth(event) as { options?: { baseURL?: string } }
3-
return { baseURL: auth.options?.baseURL }
2+
const auth = serverAuth(event) as { options?: { appName?: string, baseURL?: string } }
3+
return { appName: auth.options?.appName, baseURL: auth.options?.baseURL }
44
})
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { defineServerAuth } from '../../../../src/runtime/config'
2+
3+
export default defineServerAuth(({ requestOrigin }) => ({
4+
appName: requestOrigin || 'missing-request-origin',
5+
socialProviders: {
6+
github: { clientId: 'test', clientSecret: 'test' },
7+
},
8+
}))

test/cases/plugins-type-inference/server/auth.config.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ function customAdminLikePlugin() {
2424
} as const
2525
}
2626

27-
export default defineServerAuth({
27+
export default defineServerAuth(() => ({
2828
emailAndPassword: { enabled: true },
2929
plugins: [customAdminLikePlugin(), username()] as const,
3030
user: {
@@ -35,4 +35,4 @@ export default defineServerAuth({
3535
},
3636
},
3737
},
38-
})
38+
}))

test/schema-generator.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,15 @@ describe('defineServerAuth', () => {
157157
expect(factory({ runtimeConfig: {} as any, db: {} as any })).toEqual({ hasDb: true })
158158
expect(factory({ runtimeConfig: {} as any, db: undefined })).toEqual({ hasDb: false })
159159
})
160+
161+
it('function syntax receives requestOrigin context', () => {
162+
const factory = defineServerAuth(({ requestOrigin }) => ({ requestOrigin }))
163+
expect(factory({
164+
runtimeConfig: {} as any,
165+
db: undefined,
166+
requestOrigin: 'https://example.com',
167+
})).toEqual({ requestOrigin: 'https://example.com' })
168+
})
160169
})
161170

162171
describe('defineClientAuth', () => {

test/server-auth-base-url-cache.test.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ describe('serverAuth baseURL inference', async () => {
1515
},
1616
})
1717
expect(firstResponse.status).toBe(200)
18-
const firstBody = await firstResponse.json() as { baseURL: string | undefined }
18+
const firstBody = await firstResponse.json() as { appName: string | undefined, baseURL: string | undefined }
1919

2020
const secondResponse = await fetch(url('/api/test/base-url'), {
2121
headers: {
@@ -24,9 +24,11 @@ describe('serverAuth baseURL inference', async () => {
2424
},
2525
})
2626
expect(secondResponse.status).toBe(200)
27-
const secondBody = await secondResponse.json() as { baseURL: string | undefined }
27+
const secondBody = await secondResponse.json() as { appName: string | undefined, baseURL: string | undefined }
2828

29+
expect(firstBody.appName).toBe('https://first.example.com')
2930
expect(firstBody.baseURL).toBe('https://first.example.com')
31+
expect(secondBody.appName).toBe('https://second.example.com')
3032
expect(secondBody.baseURL).toBe('https://second.example.com')
3133
})
3234
})

0 commit comments

Comments
 (0)