Skip to content

Commit

Permalink
feat(next): provide request context in lazy initialization for RSCs
Browse files Browse the repository at this point in the history
- add createRequestFromHeaders utility for consistent request creation
- pass constructed Request to config function instead of undefined
- enable request-based config customization for RSCs, matching other contexts
- support documented use cases like env-specific provider configuration
- allow header/request access during server-side auth() calls
  • Loading branch information
huboh committed Feb 14, 2025
1 parent 4234129 commit 67ce641
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 6 deletions.
2 changes: 1 addition & 1 deletion packages/next-auth/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
* If you need to override the default values for a provider, you can still call it as a function `GitHub({...})` as before.
*
* ## Lazy initialization
* You can also initialize NextAuth.js lazily (previously known as advanced intialization), which allows you to access the request context in the configuration in some cases, like Route Handlers, Middleware, API Routes or `getServerSideProps`.
* You can also initialize NextAuth.js lazily (previously known as advanced intialization), which allows you to access the request context in the configuration in some cases, like Route Handlers, React Server Components, Middleware, API Routes or `getServerSideProps`.
* The above example becomes:
*
* ```ts title="auth.ts"
Expand Down
25 changes: 20 additions & 5 deletions packages/next-auth/src/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,19 @@ function isReqWrapper(arg: any): arg is NextAuthMiddleware | AppRouteHandlerFn {
return typeof arg === "function"
}

/**
* Creates a Request object from Headers, primarily for server-side contexts
* where we need to reconstruct request information.
*/
function createRequestFromHeaders(headers: Headers): Request {
const url = headers.get("x-url") ||
`${headers.get("x-forwarded-proto") || "http"}://${headers.get("host")}`;

return new Request(url, {
headers: new Headers(headers)
})
}

export function initAuth(
config:
| NextAuthConfig
Expand All @@ -128,10 +141,11 @@ export function initAuth(
if (!args.length) {
// React Server Components
const _headers = await headers()
const _config = await config(undefined) // Review: Should we pass headers() here instead?
const _request = createRequestFromHeaders(_headers)
const _config = await config(_request)
onLazyLoad?.(_config)

return getSession(_headers, _config).then((r) => r.json())
return getSession(_request.headers, _config).then((r) => r.json())
}

if (args[0] instanceof Request) {
Expand Down Expand Up @@ -183,9 +197,10 @@ export function initAuth(
return (...args: WithAuthArgs) => {
if (!args.length) {
// React Server Components
return Promise.resolve(headers()).then((h: Headers) =>
getSession(h, config).then((r) => r.json())
)
return Promise.resolve(headers()).then((h: Headers) =>{
const request = createRequestFromHeaders(h)
return getSession(request.headers, config).then((r) => r.json())
})
}
if (args[0] instanceof Request) {
// middleware.ts inline
Expand Down

0 comments on commit 67ce641

Please sign in to comment.