feat(core): introduce api object via createAuth#112
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Caution Review failedPull request was closed or merged during review 📝 WalkthroughWalkthroughThis pull request introduces a new centralized API surface ( Changes
Sequence Diagram(s)sequenceDiagram
participant Client as Client/Request
participant App as Application
participant API as api.getSession()
participant SessionAction as Session Action
participant Cookies as Cookie Store
participant JWT as Jose JWT
Client->>App: POST /api/protected
App->>API: api.getSession({ headers })
API->>SessionAction: getSession({ ctx, headers })
SessionAction->>Cookies: getCookie(headers, sessionToken)
Cookies-->>SessionAction: token string
SessionAction->>JWT: decodeJWT(token)
JWT-->>SessionAction: { user, exp, ...claims }
SessionAction-->>API: { session: { user, expires }, authenticated: true }
API-->>App: SessionResponse
alt session.authenticated === true
App->>Client: 200 { session: ... }
else session.authenticated === false
App->>Client: 401 { session: null, authenticated: false }
end
sequenceDiagram
participant Client as Client
participant App as Application
participant API as api.signOut()
participant SignOutAction as SignOut Action
participant Cookies as Cookie Store
participant JWT as Jose JWT
participant CSRF as CSRF Verification
Client->>App: POST /api/signout
App->>API: api.signOut({ headers, redirectTo, skipCSRFCheck })
API->>SignOutAction: signOut({ ctx, headers, redirectTo, skipCSRFCheck })
SignOutAction->>Cookies: getCookie(headers, sessionToken)
SignOutAction->>Cookies: getCookie(headers, csrfToken)
alt skipCSRFCheck === true
SignOutAction->>CSRF: verifyJWS(csrfToken)
CSRF-->>SignOutAction: verified
else skipCSRFCheck === false
SignOutAction->>SignOutAction: validate CSRF header
SignOutAction->>JWT: decodeJWT(csrfToken)
JWT-->>SignOutAction: decoded
end
SignOutAction->>JWT: decodeJWT(sessionToken)
JWT-->>SignOutAction: session payload
SignOutAction-->>API: Response (202, expired cookies, Location redirect)
API-->>App: Response
App->>Client: 202 Redirect
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (5)
packages/core/src/index.ts (2)
67-78: PincreateAuthreturn type toAuthInstance.Adding an explicit return type makes contract drift detectable at compile time.
♻️ Proposed typing update
-import type { AuthConfig } from "@/@types/index.ts" +import type { AuthConfig, AuthInstance } from "@/@types/index.ts" @@ -export const createAuth = (authConfig: AuthConfig) => { +export const createAuth = (authConfig: AuthConfig): AuthInstance => {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/core/src/index.ts` around lines 67 - 78, The createAuth function currently returns an inferred type; explicitly annotate its return as AuthInstance to prevent contract drift—update the createAuth signature to return AuthInstance (while keeping the body using createInternalConfig and createRouter with signInAction, callbackAction, sessionAction, signOutAction, csrfTokenAction) so the compiler enforces the public shape (handlers, jose, server) matches the AuthInstance interface.
8-24: Re-export the new server/session types from the public barrel.
SessionResponseandAuthServerAPIare introduced but not exposed here, which makes consumer typing less discoverable.♻️ Proposed export update
export type { AuthConfig, AuthInstance, + AuthServerAPI, JoseInstance, Session, + SessionResponse, User, CookieConfig,🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/core/src/index.ts` around lines 8 - 24, The public barrel in packages/core/src/index.ts currently re-exports many types but omits the new server/session types; add SessionResponse and AuthServerAPI to the exported types list so consumers can import them from the public package. Update the export block that currently lists AuthConfig, AuthInstance, JoseInstance, Session, User, etc., to include SessionResponse and AuthServerAPI (the unique symbols to add) alongside the existing exports.packages/core/src/context.ts (2)
33-33: Avoid parsingTRUSTED_ORIGINStwice.Line 33 computes the same env array two times; caching it once makes this path clearer.
♻️ Proposed cleanup
+ const trustedOriginsEnv = getEnvArray("TRUSTED_ORIGINS") @@ - trustedOrigins: getEnvArray("TRUSTED_ORIGINS").length > 0 ? getEnvArray("TRUSTED_ORIGINS") : config?.trustedOrigins, + trustedOrigins: trustedOriginsEnv.length > 0 ? trustedOriginsEnv : config?.trustedOrigins,🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/core/src/context.ts` at line 33, The trustedOrigins initialization currently calls getEnvArray("TRUSTED_ORIGINS") twice; store the result in a local variable (e.g., const envTrusted = getEnvArray("TRUSTED_ORIGINS")) and use that single cached value in the ternary expression that sets trustedOrigins (fallback to config?.trustedOrigins) to avoid duplicate parsing and clarify intent in the trustedOrigins assignment.
10-13: RenamecookieCofigbefore this typo spreads further.Line 10 and Line 35 use
cookieCofig; renaming tocookieConfignow will avoid avoidable churn across the new server API wiring.♻️ Proposed rename in this file
export type InternalContext = GlobalContext & { - cookieCofig: { + cookieConfig: { secure: CookieStoreConfig standard: CookieStoreConfig } } @@ - cookieCofig: { secure: secureCookieStore, standard: standardCookieStore }, + cookieConfig: { secure: secureCookieStore, standard: standardCookieStore },Also applies to: 35-35
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/core/src/context.ts` around lines 10 - 13, Rename the misspelled property cookieCofig to cookieConfig throughout the module: update the type/interface where cookieCofig is declared and any references (e.g., in the context object and usages that read/write cookieCofig) so the symbol is consistently cookieConfig; ensure related types CookieStoreConfig remain unchanged and run the type-checker to catch remaining references to cookieCofig (update imports/exports if the property is exposed).packages/core/src/actions/session/session.ts (1)
12-17: Prefer direct branching over throw/catch for expected unauthenticated flowLine 13–Line 15 uses exceptions for a non-exceptional branch and then handles it locally. A direct unauthorized return path is simpler and removes unnecessary control-flow indirection.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/core/src/actions/session/session.ts` around lines 12 - 17, Replace the throw-based unauthenticated branch in the server.getSession handling with a direct unauthorized return: after calling server.getSession(request) check session.authenticated and if false return an unauthorized Response (e.g., Response.json({ error: "INVALID_JWT_TOKEN", message: "Session not authenticated" }, { status: 401, headers: secureApiHeaders })) instead of throwing AuthInternalError; leave the try/catch to handle real exceptions and remove the local throw usage around AuthInternalError so control flow is direct and clearer in the code that calls server.getSession and builds the Response.json.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/deno/src/index.ts`:
- Line 1: The code uses server.getSession but never imports server; add an
import for the exported server symbol from the module that defines it (the same
module that exports the server instance used elsewhere) and include it alongside
the existing handlers import so calls to server.getSession resolve correctly;
update the import statement that currently reads import { handlers } from
"./auth.ts" to also import server (e.g., import { handlers, server } from
<module-that-exports-server>) so server.getSession(...) works.
- Around line 9-10: The authorization check incorrectly tests the session object
itself (const session = await server.getSession(request); if (!session)) which
is always truthy; update the conditional to check the discriminant returned by
getSession instead (use if (!session.authenticated)) so unauthenticated requests
are rejected; adjust the branch that handles unauthorized access to respond with
the same 401/unauthorized behavior used in other integrations and keep the
variable name session and call site server.getSession(request) unchanged.
In `@apps/oak/src/middleware/with-auth.ts`:
- Line 21: The with-auth middleware references server.getSession(ctx.request)
but `server` is not declared or imported; fix by making the auth server
available to this module—either import the server instance used elsewhere (e.g.,
from your auth/server or auth/index export) or accept it as a parameter to the
withAuth function and use that parameter instead; update the call site to pass
the server if you change the signature, and ensure the code uses the correct
symbol (e.g., server.getSession or injectedServer.getSession) so the getSession
call is in-scope.
In `@apps/supabase/functions/auth/index.ts`:
- Line 15: The current check uses session.user which can throw when getSession()
returns null; change the authorization guard to use the discriminant
session?.authenticated (from the getSession() result) instead of accessing
session.user, and update any downstream logic in the auth handler in
apps/supabase/functions/auth/index.ts to rely on session when authenticated is
true (or handle null session) so you no longer dereference session.user when
session may be null.
In `@packages/core/src/server/create-server.ts`:
- Around line 6-12: getSession currently always reads the session cookie from
ctx.cookies.sessionToken.name (in createServerAPI -> getSession), which breaks
request-dependent cookie selection; update getSession to pick the cookie store
based on the incoming Request (use the same secure/standard selection logic used
elsewhere in your codebase) and then read the session token from that
request-specific cookie store instead of ctx.cookies.sessionToken.name so
HTTP/local requests use the correct cookie namespace.
---
Nitpick comments:
In `@packages/core/src/actions/session/session.ts`:
- Around line 12-17: Replace the throw-based unauthenticated branch in the
server.getSession handling with a direct unauthorized return: after calling
server.getSession(request) check session.authenticated and if false return an
unauthorized Response (e.g., Response.json({ error: "INVALID_JWT_TOKEN",
message: "Session not authenticated" }, { status: 401, headers: secureApiHeaders
})) instead of throwing AuthInternalError; leave the try/catch to handle real
exceptions and remove the local throw usage around AuthInternalError so control
flow is direct and clearer in the code that calls server.getSession and builds
the Response.json.
In `@packages/core/src/context.ts`:
- Line 33: The trustedOrigins initialization currently calls
getEnvArray("TRUSTED_ORIGINS") twice; store the result in a local variable
(e.g., const envTrusted = getEnvArray("TRUSTED_ORIGINS")) and use that single
cached value in the ternary expression that sets trustedOrigins (fallback to
config?.trustedOrigins) to avoid duplicate parsing and clarify intent in the
trustedOrigins assignment.
- Around line 10-13: Rename the misspelled property cookieCofig to cookieConfig
throughout the module: update the type/interface where cookieCofig is declared
and any references (e.g., in the context object and usages that read/write
cookieCofig) so the symbol is consistently cookieConfig; ensure related types
CookieStoreConfig remain unchanged and run the type-checker to catch remaining
references to cookieCofig (update imports/exports if the property is exposed).
In `@packages/core/src/index.ts`:
- Around line 67-78: The createAuth function currently returns an inferred type;
explicitly annotate its return as AuthInstance to prevent contract drift—update
the createAuth signature to return AuthInstance (while keeping the body using
createInternalConfig and createRouter with signInAction, callbackAction,
sessionAction, signOutAction, csrfTokenAction) so the compiler enforces the
public shape (handlers, jose, server) matches the AuthInstance interface.
- Around line 8-24: The public barrel in packages/core/src/index.ts currently
re-exports many types but omits the new server/session types; add
SessionResponse and AuthServerAPI to the exported types list so consumers can
import them from the public package. Update the export block that currently
lists AuthConfig, AuthInstance, JoseInstance, Session, User, etc., to include
SessionResponse and AuthServerAPI (the unique symbols to add) alongside the
existing exports.
ℹ️ Review info
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (28)
apps/bun/src/auth.tsapps/bun/src/index.tsapps/bun/src/lib/get-session.tsapps/deno/src/auth.tsapps/deno/src/index.tsapps/deno/src/lib/get-session.tsapps/elysia/src/auth.tsapps/elysia/src/lib/get-session.tsapps/elysia/src/plugins/with-auth.tsapps/express/src/auth.tsapps/express/src/lib/get-session.tsapps/express/src/lib/verify-session.tsapps/hono/src/auth.tsapps/hono/src/lib/get-session.tsapps/hono/src/middleware/with-auth.tsapps/oak/src/auth.tsapps/oak/src/lib/get-session.tsapps/oak/src/middleware/with-auth.tsapps/supabase/functions/_shared/auth.tsapps/supabase/functions/_shared/get-session.tsapps/supabase/functions/auth/index.tspackages/core/.vscode/settings.jsonpackages/core/src/@types/index.tspackages/core/src/actions/session/session.tspackages/core/src/context.tspackages/core/src/index.tspackages/core/src/server/create-server.tspackages/core/test/actions/session/session.test.ts
💤 Files with no reviewable changes (7)
- apps/bun/src/lib/get-session.ts
- apps/deno/src/lib/get-session.ts
- apps/supabase/functions/_shared/get-session.ts
- apps/elysia/src/lib/get-session.ts
- apps/oak/src/lib/get-session.ts
- apps/express/src/lib/get-session.ts
- apps/hono/src/lib/get-session.ts
Fixes stale build artifacts that prevented AuthInstance API types from being recognized.
There was a problem hiding this comment.
Actionable comments posted: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
apps/elysia/src/plugins/with-auth.ts (1)
7-18:⚠️ Potential issue | 🟠 MajorUnwrap
SessionResponsebefore storing it inctx.session.
api.getSession()returns{ session, authenticated }, but the plugin currently returns that entire object undersession. This makesctx.sessionthe wrapper instead of the actualSession, causing/api/auth/meto expose the wrapped shape.Suggested fix
try { const session = await api.getSession({ headers: ctx.request.headers, }) - if (!session!.authenticated) { + if (!session.authenticated) { return { session: null } } - return { session } + return { session: session.session } } catch { return { session: null } } })🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/elysia/src/plugins/with-auth.ts` around lines 7 - 18, The plugin is storing the entire SessionResponse wrapper in ctx.session; change the handler that calls api.getSession() (the call to api.getSession and the surrounding anonymous async function) to extract the inner Session object (e.g., const { session: actualSession, authenticated } = await api.getSession(...)) and set/return session: actualSession (or null if not authenticated or on error) so ctx.session holds the raw Session; also ensure the get("/api/auth/me", ({ session }) => session) continues to return the unwrapped Session or null.apps/nextjs/app-router/src/lib/server.ts (1)
59-71:⚠️ Potential issue | 🟠 Major
api.signOutrequires CSRF token in headers for security validation.Based on the core
signOutAPI (packages/core/src/api/signOut.ts), the function validates theX-CSRF-Tokenheader unlessskipCSRFCheckis set. The current implementation passes only the request headers without ensuring the CSRF token header is present, which will causeAuthSecurityError("CSRF_HEADER_MISSING")to be thrown.🔧 Suggested approach
Either:
- Retrieve the CSRF token and include it in headers before calling
api.signOut:export const signOut = async (redirectTo: string = "/") => { try { const cookieStore = await cookies() + const csrfToken = await getCSRFToken() + const headersInit = await headers() + const signOutHeaders = new Headers(headersInit) + if (csrfToken) { + signOutHeaders.set("X-CSRF-Token", csrfToken) + } const response = await api.signOut({ - headers: await headers(), + headers: signOutHeaders, })
- Or expose a
skipCSRFCheckoption for server-side calls where the request is already authenticated.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/nextjs/app-router/src/lib/server.ts` around lines 59 - 71, The call to api.signOut currently forwards only headers() and may omit the required X-CSRF-Token, causing AuthSecurityError; update the sign-out flow in this block (cookies(), headers(), api.signOut) to include the CSRF token header or opt out of validation: either extract the CSRF token from headers() (or from wherever your app stores it) and add it as "X-CSRF-Token" to the headers passed into api.signOut, or call api.signOut with the skipCSRFCheck option enabled (e.g., { headers: await headers(), skipCSRFCheck: true }) so the server-side call doesn’t require the header. Ensure the chosen fix is applied where api.signOut is invoked and that cookieStore.delete/name parsing remains unchanged.
♻️ Duplicate comments (3)
apps/astro/src/auth.ts (1)
6-6:⚠️ Potential issue | 🔴 CriticalSame
AuthInstance/apimismatch as the other auth adapters.This export has the same blocking type error: the
AuthInstanceresolved by this app does not currently exposeapi, so the adapter will not type-check until the package/dependency surface is aligned.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/astro/src/auth.ts` at line 6, The export destructures { handlers, jose, api } from createAuth but the resolved AuthInstance type does not include api; update this by either adding api to the AuthInstance interface/type or by removing api from the destructure/export so the exported symbols match the actual AuthInstance shape — locate the createAuth call and the AuthInstance type definition and either extend AuthInstance to include an api property (with the correct type) or change the export to export only handlers and jose to ensure the adapter type-checks.apps/nextjs/pages-router/src/auth.ts (1)
6-6:⚠️ Potential issue | 🔴 CriticalSame
AuthInstance/apimismatch as the other auth adapters.This export hits the same compile-time failure: the
AuthInstanceseen by CI does not currently exposeapi, so this file will not type-check until the package/dependency surface is aligned.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/nextjs/pages-router/src/auth.ts` at line 6, The exported destructure includes `api` which is not present on the `AuthInstance` type causing a type mismatch; either remove `api` from the export or align the type to include it. Locate the line exporting `export const { handlers, jose, api }: AuthInstance = createAuth({` and fix by (A) dropping `api` from the destructured export if `createAuth` does not return it, or (B) update/extend the `AuthInstance` type definition to include the `api` symbol (or cast the result of `createAuth` to a type that includes `api`) so the declared type matches the actual returned shape.apps/oak/src/auth.ts (1)
3-3:⚠️ Potential issue | 🔴 CriticalSame
AuthInstance/apimismatch as the other auth adapters.CI reports the same failure here, so this file will not compile until the resolved
@aura-stack/authtypings includeapi.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/oak/src/auth.ts` at line 3, The export destructures handlers, jose and api from createAuth but the annotated type AuthInstance (used in the declaration "export const { handlers, jose, api }: AuthInstance") does not yet include api; update the declaration so it compiles by either (a) updating the AuthInstance type in the `@aura-stack/auth` typings to include the api property, or (b) removing the explicit ": AuthInstance" annotation and let TypeScript infer the returned shape from createAuth (keeping "export const { handlers, jose, api } = createAuth(...)" ), referencing the createAuth call and the exported symbols handlers, jose, api.
🧹 Nitpick comments (2)
apps/nextjs/app-router/src/app/page.tsx (1)
10-10: Minor:signOutis destructured but unused in this file.Consider removing the unused
signOutdestructuring to keep the code clean, unless it's planned for use in an upcoming change.✂️ Remove unused destructuring
- const { getSession, signIn, signOut } = createAuthServer + const { getSession, signIn } = createAuthServer🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/nextjs/app-router/src/app/page.tsx` at line 10, The destructuring of createAuthServer currently pulls getSession, signIn and signOut but signOut is unused; update the destructuring expression that references createAuthServer to remove signOut (keep getSession and signIn) to eliminate the unused variable and related linter warning, ensuring no other references to signOut remain in the file (e.g., search for signOut usage before removing).packages/core/src/utils.ts (1)
173-177: Consider adding a clarifying comment for the security intent.The function correctly restricts redirects to relative URLs only (preventing open redirect attacks to external domains). However, the logic flow may be unclear to future maintainers:
- Malformed URLs →
"/"- Relative URLs → allowed (internal redirects)
- Valid absolute URLs →
"/"(blocked for security)📝 Suggested documentation improvement
+/** + * Validates and sanitizes redirect URLs to prevent open redirect attacks. + * Only relative URLs (starting with /) are allowed; absolute URLs are + * rejected and replaced with "/" to enforce same-origin redirects. + */ export const validateRedirectTo = (url: string): string => { if (!isRelativeURL(url) && !isValidURL(url)) return "/" if (isRelativeURL(url)) return url return "/" }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/core/src/utils.ts` around lines 173 - 177, The validateRedirectTo function's logic is correct but needs an inline clarifying comment about the security intent: add a short comment above validateRedirectTo explaining that only relative URLs are allowed to prevent open-redirect attacks, that malformed or absolute URLs are intentionally normalized to "/" (internal root), and the ordering (malformed → "/", relative → allowed, absolute → "/") is deliberate; reference the function name validateRedirectTo and mention isRelativeURL and isValidURL so maintainers understand the rationale.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/astro/src/lib/server.ts`:
- Around line 50-55: The sign-out flow discards session-clearing Set-Cookie
headers by calling redirect(redirectTo) after api.signOut(), so instead of
calling redirect inside the if (response.status === 202) branch, return the
Response returned from api.signOut() directly (i.e. return response) so the
Set-Cookie headers from api.signOut() are preserved and sent to the client; keep
using redirect(redirectTo) only for other non-202 cases if needed.
In `@apps/nextjs/app-router/src/lib/client.ts`:
- Around line 36-37: The signIn function currently redirects to a hard-coded
/auth/signIn/... which 404s; update signIn to use the same auth base path used
by the server-side helper in server.ts (the auth path builder at lines ~53-56)
rather than the hard-coded "/auth" so the client and server routes match. Locate
signIn and replace the hard-coded path with the shared auth base (or import and
reuse the server helper / AUTH_BASE_PATH constant) to build
`${AUTH_BASE_PATH}/signIn/${provider}?redirectTo=${encodeURIComponent(redirectTo)}`
so OAuth starts correctly.
- Around line 25-29: The getSession helper is still expecting a top-level user
on the JSON response but the API now returns { authenticated, session }; update
the parsing logic after client.get("/session") to read the JSON into a payload,
unwrap the actual session from payload.session (falling back to the old shape if
needed), and use payload.authenticated (or payload.session presence) when
deciding to return the session; adjust the console.log to log the unwrapped
session instead of the full payload. Target the getSession function around the
client.get("/session") call and replace the current response.json()/session/user
checks with the described unwrap-and-check logic.
In `@apps/nextjs/pages-router/src/lib/server.ts`:
- Around line 9-22: The module currently exports only the standalone getSession
function but consuming code expects createAuthServer.getSession; fix this by
exporting createAuthServer as an object that exposes getSession (e.g., add an
export like export const createAuthServer = { getSession }) so callers can call
createAuthServer.getSession(req); ensure the exported object signature matches
the existing getSession( req: NextApiRequest ): Promise<Session | null> and
leave the existing getSession export intact or re-export it from
createAuthServer to avoid breaking imports.
In `@packages/core/src/api/createApi.ts`:
- Around line 18-20: The public wrapper signOut in createApi.ts should not
force-disable CSRF; remove the hardcoded skipCSRFCheck: true (or forward an
explicit options.skipCSRFCheck that defaults to false) when calling the internal
signOut function so header-bound CSRF validation remains enabled for public
callers, leaving bypass only for internal helpers in signOut.ts.
In `@packages/core/src/api/signOut.ts`:
- Around line 61-63: The else branch calls await ctx.jose.verifyJWS(csrfToken)
without handling rejections; wrap that call in a try/catch and convert any
verification failure into the same AuthSecurityError used on the non-skip path
(throw new AuthSecurityError or reuse the existing helper) so malformed/expired
CSRF tokens produce the auth error contract; ensure you reference
ctx.jose.verifyJWS and AuthSecurityError (and import it if necessary) and mirror
the error message/handling used by the non-skip branch in signOut.
- Around line 70-80: The response currently sets a Location header via
HeadersBuilder.setHeader("Location", redirectTo) but returns status 202, which
browsers ignore for redirects; update the signOut response so that when a
redirectTo is present (or always, if intended) the Response.json call uses a 303
status (See Other) instead of 202 — or conditionally return 303 when redirectTo
is provided and 202 otherwise; modify the code around HeadersBuilder/headersList
and the Response.json(...) status value accordingly.
---
Outside diff comments:
In `@apps/elysia/src/plugins/with-auth.ts`:
- Around line 7-18: The plugin is storing the entire SessionResponse wrapper in
ctx.session; change the handler that calls api.getSession() (the call to
api.getSession and the surrounding anonymous async function) to extract the
inner Session object (e.g., const { session: actualSession, authenticated } =
await api.getSession(...)) and set/return session: actualSession (or null if not
authenticated or on error) so ctx.session holds the raw Session; also ensure the
get("/api/auth/me", ({ session }) => session) continues to return the unwrapped
Session or null.
In `@apps/nextjs/app-router/src/lib/server.ts`:
- Around line 59-71: The call to api.signOut currently forwards only headers()
and may omit the required X-CSRF-Token, causing AuthSecurityError; update the
sign-out flow in this block (cookies(), headers(), api.signOut) to include the
CSRF token header or opt out of validation: either extract the CSRF token from
headers() (or from wherever your app stores it) and add it as "X-CSRF-Token" to
the headers passed into api.signOut, or call api.signOut with the skipCSRFCheck
option enabled (e.g., { headers: await headers(), skipCSRFCheck: true }) so the
server-side call doesn’t require the header. Ensure the chosen fix is applied
where api.signOut is invoked and that cookieStore.delete/name parsing remains
unchanged.
---
Duplicate comments:
In `@apps/astro/src/auth.ts`:
- Line 6: The export destructures { handlers, jose, api } from createAuth but
the resolved AuthInstance type does not include api; update this by either
adding api to the AuthInstance interface/type or by removing api from the
destructure/export so the exported symbols match the actual AuthInstance shape —
locate the createAuth call and the AuthInstance type definition and either
extend AuthInstance to include an api property (with the correct type) or change
the export to export only handlers and jose to ensure the adapter type-checks.
In `@apps/nextjs/pages-router/src/auth.ts`:
- Line 6: The exported destructure includes `api` which is not present on the
`AuthInstance` type causing a type mismatch; either remove `api` from the export
or align the type to include it. Locate the line exporting `export const {
handlers, jose, api }: AuthInstance = createAuth({` and fix by (A) dropping
`api` from the destructured export if `createAuth` does not return it, or (B)
update/extend the `AuthInstance` type definition to include the `api` symbol (or
cast the result of `createAuth` to a type that includes `api`) so the declared
type matches the actual returned shape.
In `@apps/oak/src/auth.ts`:
- Line 3: The export destructures handlers, jose and api from createAuth but the
annotated type AuthInstance (used in the declaration "export const { handlers,
jose, api }: AuthInstance") does not yet include api; update the declaration so
it compiles by either (a) updating the AuthInstance type in the `@aura-stack/auth`
typings to include the api property, or (b) removing the explicit ":
AuthInstance" annotation and let TypeScript infer the returned shape from
createAuth (keeping "export const { handlers, jose, api } = createAuth(...)" ),
referencing the createAuth call and the exported symbols handlers, jose, api.
---
Nitpick comments:
In `@apps/nextjs/app-router/src/app/page.tsx`:
- Line 10: The destructuring of createAuthServer currently pulls getSession,
signIn and signOut but signOut is unused; update the destructuring expression
that references createAuthServer to remove signOut (keep getSession and signIn)
to eliminate the unused variable and related linter warning, ensuring no other
references to signOut remain in the file (e.g., search for signOut usage before
removing).
In `@packages/core/src/utils.ts`:
- Around line 173-177: The validateRedirectTo function's logic is correct but
needs an inline clarifying comment about the security intent: add a short
comment above validateRedirectTo explaining that only relative URLs are allowed
to prevent open-redirect attacks, that malformed or absolute URLs are
intentionally normalized to "/" (internal root), and the ordering (malformed →
"/", relative → allowed, absolute → "/") is deliberate; reference the function
name validateRedirectTo and mention isRelativeURL and isValidURL so maintainers
understand the rationale.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: f9363638-60da-498b-a190-50e868f28250
📒 Files selected for processing (40)
apps/astro/src/auth.tsapps/astro/src/lib/server.tsapps/bun/src/auth.tsapps/bun/src/index.tsapps/cloudflare/src/auth.tsapps/deno/src/auth.tsapps/deno/src/index.tsapps/elysia/src/auth.tsapps/elysia/src/plugins/with-auth.tsapps/express/src/auth.tsapps/express/src/lib/verify-session.tsapps/express/test/index.test.tsapps/hono/src/auth.tsapps/hono/src/middleware/with-auth.tsapps/nextjs/app-router/src/app/page.tsxapps/nextjs/app-router/src/app/profile/page.tsxapps/nextjs/app-router/src/auth.tsapps/nextjs/app-router/src/lib/client.tsapps/nextjs/app-router/src/lib/server.tsapps/nextjs/pages-router/src/auth.tsapps/nextjs/pages-router/src/lib/server.tsapps/oak/src/auth.tsapps/oak/src/middleware/with-auth.tsapps/react-router/app/actions/auth.server.tsapps/react-router/app/auth.tsapps/supabase/functions/_shared/auth.tsapps/supabase/functions/auth/index.tsapps/tanstack-start/src/auth.tspackages/core/CHANGELOG.mdpackages/core/src/@types/index.tspackages/core/src/actions/session/session.tspackages/core/src/actions/signOut/signOut.tspackages/core/src/api/createApi.tspackages/core/src/api/getSession.tspackages/core/src/api/signOut.tspackages/core/src/context.tspackages/core/src/cookie.tspackages/core/src/index.tspackages/core/src/utils.tspackages/core/test/cookie.test.ts
🚧 Files skipped from review as they are similar to previous changes (6)
- apps/bun/src/auth.ts
- apps/hono/src/auth.ts
- apps/express/src/auth.ts
- apps/deno/src/index.ts
- apps/supabase/functions/_shared/auth.ts
- apps/deno/src/auth.ts
Description
This pull request introduces the
apiobject returned by thecreateAuthfunction, enabling direct interaction with Aura Auth server capabilities without issuing HTTP requests to mounted endpoints. The new API provides built-in utilities to retrieve and sign out sessions programmatically on the server, eliminating the need to call the/sessionor/signOutendpoints usingfetchorRequest.This improvement simplifies server-side integrations and enhances performance by avoiding unnecessary network calls while maintaining the same authentication logic used by the HTTP handlers.
This PR was motivated by the integration examples included in the repository. Across the 15 integrations, many of them implemented nearly identical logic to retrieve session data or execute authentication actions from both server and client contexts. In most cases, these interactions were performed using
fetchrequests to the same server where Aura Auth was mounted. While this approach works correctly, it introduces unnecessary internal requests and makes the flow less transparent, since the server ends up making HTTP requests or redirects to itself.To address this, the new
apiutilities allow the server to interact directly with the internal logic that powers the endpoints, instead of calling the endpoints themselves. This removes the need to constructRequestobjects or performfetchcalls when the execution already occurs within the same runtime.Additionally, these utilities are inherently trusted because they operate within the same origin and runtime context as the mounted server. As a result, there is no need to introduce additional validation layers that would normally be required for external HTTP requests.
This PR is specifically focused on improving the server-side developer experience, reducing duplicated code across integrations, and eliminating unnecessary request overhead.
The
apiinterface enables server-side access to authentication utilities while keeping the implementation consistent with the existing internal flows used by Aura Auth handlers.