chore(examples): add Express integration app#96
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. 2 Skipped Deployments
|
|
No actionable comments were generated in the recent review. 🎉 📝 WalkthroughWalkthroughThis PR adds a complete Express integration for Aura Auth: package/config files, an Express server and entrypoint, auth setup (createAuth handlers & jose), middleware to bridge Web API handlers to Express, session utilities and verification middleware, TypeScript types, tests, README, .env example, and .gitignore. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant Express as Express Server
participant AuthBridge as Auth Middleware
participant Aura as Aura Auth Handler
participant GitHub as GitHub OAuth
Client->>Express: GET /api/auth/signIn/github
Express->>AuthBridge: toExpressHandler
AuthBridge->>Aura: Invoke Aura Web API handler (Web Request)
Aura->>GitHub: Redirect to OAuth authorize
GitHub-->>Aura: OAuth response/redirect
Aura-->>AuthBridge: Web Response (302 + Set-Cookie)
AuthBridge-->>Express: Apply response (headers, cookies, Location)
Express-->>Client: 302 redirect with Location
sequenceDiagram
participant Client
participant Express as Express Server
participant Verify as verifySession
participant GetSession as getSession
participant Jose as jose (decoder)
participant Protected as Protected Route
Client->>Express: GET /api/protected (with cookie)
Express->>Verify: verifySession middleware
Verify->>GetSession: extract cookie & decode
GetSession->>Jose: decode JWT
Jose-->>GetSession: session payload
GetSession-->>Verify: Session object
Verify->>Express: attach session to res.locals
Express->>Protected: handler executes and returns 200 + session
Protected-->>Client: 200 with user/session data
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 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: 9
🧹 Nitpick comments (8)
apps/express/src/lib/get-session.ts (1)
14-22: Manual cookie parsing is redundant givencookie-parsermiddleware.
cookie-parseris a listed runtime dependency and presumably applied viaapp.use(cookieParser())inindex.ts. When active,req.cookiesis already a parsedRecord<string, string>, making the manualsplit/decodeURIComponentpipeline on the rawCookieheader redundant. Usingreq.cookiesis shorter, avoids double-parsing, and handles edge cases (e.g. cookies with=in the value, whitespace variants) consistently with the rest of the app.♻️ Proposed refactor
export const getSession = async (request: Request): Promise<Session | null> => { - const cookieHeader = request.headers.cookie - if (!cookieHeader) return null try { - const cookies = Object.fromEntries( - cookieHeader - .split(";") - .map((c) => c.trim().split("=")) - .map(([key, ...val]) => [decodeURIComponent(key), decodeURIComponent(val.join("="))]) - ) - - const sessionCookieKey = Object.keys(cookies).find((k) => k.includes("session_token")) + const cookies: Record<string, string> = request.cookies ?? {} + const sessionCookieKey = Object.keys(cookies).find((k) => k.includes("session_token")) if (!sessionCookieKey) return nullNote: this requires
@types/cookie-parserindevDependenciesto give TypeScript thereq.cookiestype on the ExpressRequest.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/express/src/lib/get-session.ts` around lines 14 - 22, The manual cookie parsing in getSession (the cookieHeader split/decodeURIComponent block) is redundant — replace that logic by reading the parsed cookies from request.cookies (provided by cookie-parser middleware) and use that Record<string,string> for session lookup; remove the custom split/map pipeline in the getSession function and rely on req.cookies to avoid double-parsing and handle edge cases, and ensure `@types/cookie-parser` is added to devDependencies so TypeScript recognizes request.cookies on the Express Request type.apps/express/src/auth.ts (1)
4-4:oauthexport enumerates all built-in providers, not the configured ones.
Object.keys(builtInOAuthProviders)returns all 10 built-in providers (github,bitbucket,figma, …), butcreateAuthis configured with only["github"]. Any consumer iterating this array to render sign-in buttons or derive available providers will see 10 options when only 1 is functional.Consider either aligning the export with the actual configuration or renaming it to make its scope clear (e.g.
availableOAuthProviders).♻️ Proposed fix
-export const oauth = Object.keys(builtInOAuthProviders) as BuiltInOAuthProvider[] +/** All built-in OAuth providers supported by Aura Auth (not all are configured in this app). */ +export const allOAuthProviders = Object.keys(builtInOAuthProviders) as BuiltInOAuthProvider[] + +/** OAuth providers enabled in this app's createAuth config. */ +export const configuredOAuthProviders: BuiltInOAuthProvider[] = ["github"]🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/express/src/auth.ts` at line 4, The exported oauth array is listing every key from builtInOAuthProviders (export const oauth) rather than the actual providers configured in createAuth, causing UI to show non-functional options; update the export to reflect the configured providers (e.g., derive the list from the createAuth configuration or export a new name like availableOAuthProviders that is populated from the actual auth config) or rename the existing export to make its scope explicit (oauthAllProviders) and add a separate configuredProviders/availableOAuthProviders export that reads the provider keys used in createAuth so consumers only see functional providers.apps/express/tsconfig.json (1)
6-6:test/is excluded from type-checking.The
includearray covers onlysrc. Thetype-checkscript (tsc --noEmit) will therefore silently skipapps/express/test/. Consider adding"test"toinclude, or adding a separatetsconfig.test.jsonthat extends this file and adds thetestdirectory, so TypeScript type errors in tests are caught in CI.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/express/tsconfig.json` at line 6, The tsconfig’s "include" only lists "src" so the test directory is skipped by the type-check step; update the "include" array to also include "test" (add "test") or create a new tsconfig.test.json that extends this tsconfig and adds "test" to its "include", and ensure the CI/type-check script (the `type-check` step invoking tsc --noEmit) uses the updated config so types in apps/express/test/ are checked.apps/express/.gitignore (1)
1-186: Deduplicate entries and remove framework-specific artifacts not relevant to Express.The file appears to be assembled from multiple gitignore templates without deduplication. Several entries appear 2–3 times (
.DS_Store,dist,.env,logs,*.log,.cache,.nuxt,.nitro,.output,node_modules). Additionally, entries specific to TanStack Start / Nuxt scaffolding (count.txt,todos.json,.tanstack,.vinxi,.nitro,.nuxt,.output) are unlikely to be needed for an Express app.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/express/.gitignore` around lines 1 - 186, The .gitignore contains duplicate and irrelevant entries merged from multiple templates; remove repeated entries (e.g., .DS_Store, dist, .env, logs, *.log, .cache, node_modules) so each pattern appears only once and delete framework-specific artifacts not used by an Express app (examples: .nuxt, .nitro, .output, .tanstack, .vinxi, count.txt, todos.json) leaving only Express-relevant ignores (node_modules, logs, coverage, .env, build/dist outputs, editor caches). Ensure unique entries remain for patterns like .env, .env.*, !.env.example, node_modules, coverage, .DS_Store, dist, .cache, logs, and remove the duplicated blocks and unrelated framework lines.apps/express/src/middleware/with-auth.ts (1)
14-24: LGTM — middleware logic is correct and well-documented.The guard pattern (null session → 401, session present → attach to
res.localsandnext()) is clean. The JSDoc example in the comment matches the implementation.One optional improvement: augment
res.localswith theSessiontype to get compile-time safety on downstream handlers that readres.locals.session:// e.g., in a express.d.ts or types.d.ts file in src/ import type { Session } from "@aura-stack/auth" declare global { namespace Express { interface Locals { session?: Session } } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/express/src/middleware/with-auth.ts` around lines 14 - 24, Add a TypeScript declaration merging so Express.Res.locals is typed with the Session shape used in withAuth: create a global declaration file that imports type { Session } from "@aura-stack/auth" and augments the Express namespace with interface Locals { session?: Session }, then ensure the declaration file is included in the TS build so downstream handlers reading res.locals.session get compile-time safety; reference the withAuth middleware and res.locals.session when applying this change.apps/express/vitest.config.ts (1)
10-13: Consider making coverage opt-in rather than always-on.
enabled: truemeans every invocation ofvitestin this workspace runs V8 instrumentation, adding measurable overhead to local dev iterations. The conventional pattern is to enable coverage only via the--coverageCLI flag (or in CI config), leavingenabledeither absent orfalsehere.♻️ Proposed change
coverage: { provider: "v8", - enabled: true, },🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/express/vitest.config.ts` around lines 10 - 13, The vitest coverage block currently has enabled: true which forces V8 instrumentation on every run; change the coverage config so it is opt-in by removing or setting enabled to false in the coverage object (the section containing provider: "v8" and enabled) and rely on the --coverage CLI flag or CI config to enable coverage when needed; ensure the coverage provider remains set to "v8" if you keep the block but make enabled opt-in.apps/express/test/index.test.ts (1)
56-64: No positive-path test for/api/protected— consider adding an authenticated case.The suite only tests the 401 unauthenticated path. Without an authenticated test,
withAuthcorrectly populatingres.locals.sessionand the handler returning it are never exercised.💡 Suggested additional test
test("returns 200 with session when a valid session cookie is present", async () => { const sessionToken = await jose.encodeJWT({ sub: "johndoe", name: "John Doe", email: "johndoe@example.com", }) const response = await supertest(app) .get("/api/protected") .set("Cookie", [`aura-auth.session_token=${sessionToken}`]) expect(response.status).toBe(200) expect(response.body).toMatchObject({ message: "You have access to this protected resource.", session: expect.objectContaining({ sub: "johndoe" }), }) })🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/express/test/index.test.ts` around lines 56 - 64, Add a positive-path test to apps/express/test/index.test.ts that exercises the withAuth middleware and the GET /api/protected handler: generate a valid token with jose.encodeJWT, set it on the request as the cookie name aura-auth.session_token, call supertest(app).get("/api/protected") with .set("Cookie", [...]) and assert response.status is 200 and response.body includes the expected message plus a session object containing the subject (e.g., sub: "johndoe"); this ensures withAuth populates res.locals.session and the handler returns it.apps/express/src/middleware/auth.ts (1)
74-76: Caught error is silently discarded — add logging before the 500 response.Without logging, runtime failures in the auth handler are invisible. At minimum, emit the error to stderr.
♻️ Proposed change
} catch (error) { + console.error("[authMiddleware] handler threw:", error) return res.status(500).json({ error: "Internal Server Error" }) }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/express/src/middleware/auth.ts` around lines 74 - 76, The catch block inside the auth middleware that currently does "return res.status(500).json({ error: 'Internal Server Error' })" is discarding the thrown error; modify that catch to log the error to stderr before returning the 500 (use console.error(error) or the existing logger if available) so runtime failures in the auth handler are visible; ensure you reference the same catch block in the auth middleware (auth.ts) and keep the response behavior unchanged except for the added logging.
🤖 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/express/.env.example`:
- Around line 1-6: Add distinct per-variable comments clarifying that
AURA_AUTH_SALT is an opaque salt/nonce used for key derivation or hashing/pepper
(e.g., for deriving token keys or hashing secrets) and that AURA_AUTH_SECRET is
the actual secret signing key used to sign and verify JWT tokens; keep the
existing example generation hints (openssl rand -base64 32) and leave empty
string defaults in the template to avoid embedding real credentials. Ensure you
name the variables AURA_AUTH_SALT and AURA_AUTH_SECRET in the comments so
contributors know which to set and why.
In `@apps/express/package.json`:
- Line 2: The package "name" in package.json is colliding with the npm express
package; change the "name" field (e.g., to a scoped, unique identifier like
"@aura-stack/express-example") and update any workspace dependency references
that point to "express" so they now reference the new scoped name; ensure the
package.json "name" value is valid per npm rules and then run a workspace
install to verify no workspace:* entry resolves to the real express package.
- Line 11: The package's "test" script runs "vitest run" but vitest is missing
from this package's devDependencies; update apps/express package.json to add
"vitest" under devDependencies so the package is self-contained (ensure the
package name "vitest" is added at an appropriate version and saved into the
devDependencies section adjacent to the existing scripts/devDependencies
entries).
In `@apps/express/README.md`:
- Line 19: Replace the incorrect docs-site phrasing in apps/express/README.md
with a brief description that this repo is the Express integration app (e.g.,
how to run the Express server locally for development), and update the default
local URL from http://localhost:3000 to http://localhost:8080 so it matches the
server startup logic in src/index.ts which uses process.env.PORT ?? 8080.
In `@apps/express/src/auth.ts`:
- Around line 10-15: The logger object currently has level: "debug" and an
unconditional console.log in its log({ message, structuredData, msgId }) method
which will spam production; change the logger to derive its level from an
environment variable (e.g., process.env.LOG_LEVEL or gate by
process.env.NODE_ENV !== "production") and update the log method in the same
logger object so it only calls console.log when the resolved level permits debug
output (or when LOG_LEVEL === "debug"), otherwise no-op or route to a less
verbose output; modify the logger configuration and the log function (the
logger.level value and logger.log method) to use that env check.
In `@apps/express/src/index.ts`:
- Around line 25-28: The module currently calls app.listen(PORT, ...) at import
time, causing tests to open a real TCP socket; remove that unconditional call
from index.ts and either: 1) create a new entrypoint server.ts that imports {
app } from "./index.js", reads PORT (process.env.PORT ?? 8080) and calls
app.listen(...) with the same log lines, then update your start/main config to
point to server.ts, or 2) wrap the existing app.listen(...) in a runtime-only
guard (e.g., only call app.listen when require.main === module or when
process.env.NODE_ENV !== 'test') so tests can import { app } without starting
the server. Ensure symbols referenced are app, PORT and the new server.ts
entrypoint so tests import index.ts but the real listen happens only in
server.ts or behind the guard.
In `@apps/express/src/lib/get-session.ts`:
- Line 35: Replace the unsafe non-null assertion on exp in the expires
assignment by explicitly checking that the JWT claim exp exists and is a number
before converting it to an ISO string: in get-session.ts (the code that builds
the session object and sets expires), remove the `exp!` usage and if `exp` is a
finite number compute `new Date(exp * 1000).toISOString()`; otherwise set the
expires field to undefined (or omit it) so tokens without exp are handled
gracefully instead of producing a RangeError.
In `@apps/express/src/middleware/auth.ts`:
- Around line 37-45: The current loop in middleware/auth.ts uses
webResponse.headers.getSetCookie?.() ?? [value], but the fallback treats a
comma-joined Set-Cookie string as one cookie which corrupts cookies on older
Node.js; either remove the fallback entirely if you guarantee Node >= 18.14.1,
or replace the fallback with logic that splits the comma-joined string into
individual cookie strings (e.g., split the fallback value on ", " or a regex
that splits only between cookies) and then call res.append("Set-Cookie", cookie)
for each cookie using the result of webResponse.headers.getSetCookie(); update
the code around the webResponse.headers.entries() loop to use that corrected
fallback.
- Around line 16-29: The current code forwards original req.headers but always
serializes req.body to JSON when building the new globalThis.Request, causing a
Content-Type mismatch; before creating the Request in the block that builds
headers and body (references: req.headers, req.body, headers, new
globalThis.Request), detect when you serialize the body (method not "GET" or
"HEAD") and ensure the Content-Type header is set to "application/json" by
removing or overwriting any existing content-type entry (e.g.,
headers.set('content-type', 'application/json')) so the forwarded headers match
the JSON payload.
---
Nitpick comments:
In `@apps/express/.gitignore`:
- Around line 1-186: The .gitignore contains duplicate and irrelevant entries
merged from multiple templates; remove repeated entries (e.g., .DS_Store, dist,
.env, logs, *.log, .cache, node_modules) so each pattern appears only once and
delete framework-specific artifacts not used by an Express app (examples: .nuxt,
.nitro, .output, .tanstack, .vinxi, count.txt, todos.json) leaving only
Express-relevant ignores (node_modules, logs, coverage, .env, build/dist
outputs, editor caches). Ensure unique entries remain for patterns like .env,
.env.*, !.env.example, node_modules, coverage, .DS_Store, dist, .cache, logs,
and remove the duplicated blocks and unrelated framework lines.
In `@apps/express/src/auth.ts`:
- Line 4: The exported oauth array is listing every key from
builtInOAuthProviders (export const oauth) rather than the actual providers
configured in createAuth, causing UI to show non-functional options; update the
export to reflect the configured providers (e.g., derive the list from the
createAuth configuration or export a new name like availableOAuthProviders that
is populated from the actual auth config) or rename the existing export to make
its scope explicit (oauthAllProviders) and add a separate
configuredProviders/availableOAuthProviders export that reads the provider keys
used in createAuth so consumers only see functional providers.
In `@apps/express/src/lib/get-session.ts`:
- Around line 14-22: The manual cookie parsing in getSession (the cookieHeader
split/decodeURIComponent block) is redundant — replace that logic by reading the
parsed cookies from request.cookies (provided by cookie-parser middleware) and
use that Record<string,string> for session lookup; remove the custom split/map
pipeline in the getSession function and rely on req.cookies to avoid
double-parsing and handle edge cases, and ensure `@types/cookie-parser` is added
to devDependencies so TypeScript recognizes request.cookies on the Express
Request type.
In `@apps/express/src/middleware/auth.ts`:
- Around line 74-76: The catch block inside the auth middleware that currently
does "return res.status(500).json({ error: 'Internal Server Error' })" is
discarding the thrown error; modify that catch to log the error to stderr before
returning the 500 (use console.error(error) or the existing logger if available)
so runtime failures in the auth handler are visible; ensure you reference the
same catch block in the auth middleware (auth.ts) and keep the response behavior
unchanged except for the added logging.
In `@apps/express/src/middleware/with-auth.ts`:
- Around line 14-24: Add a TypeScript declaration merging so Express.Res.locals
is typed with the Session shape used in withAuth: create a global declaration
file that imports type { Session } from "@aura-stack/auth" and augments the
Express namespace with interface Locals { session?: Session }, then ensure the
declaration file is included in the TS build so downstream handlers reading
res.locals.session get compile-time safety; reference the withAuth middleware
and res.locals.session when applying this change.
In `@apps/express/test/index.test.ts`:
- Around line 56-64: Add a positive-path test to apps/express/test/index.test.ts
that exercises the withAuth middleware and the GET /api/protected handler:
generate a valid token with jose.encodeJWT, set it on the request as the cookie
name aura-auth.session_token, call supertest(app).get("/api/protected") with
.set("Cookie", [...]) and assert response.status is 200 and response.body
includes the expected message plus a session object containing the subject
(e.g., sub: "johndoe"); this ensures withAuth populates res.locals.session and
the handler returns it.
In `@apps/express/tsconfig.json`:
- Line 6: The tsconfig’s "include" only lists "src" so the test directory is
skipped by the type-check step; update the "include" array to also include
"test" (add "test") or create a new tsconfig.test.json that extends this
tsconfig and adds "test" to its "include", and ensure the CI/type-check script
(the `type-check` step invoking tsc --noEmit) uses the updated config so types
in apps/express/test/ are checked.
In `@apps/express/vitest.config.ts`:
- Around line 10-13: The vitest coverage block currently has enabled: true which
forces V8 instrumentation on every run; change the coverage config so it is
opt-in by removing or setting enabled to false in the coverage object (the
section containing provider: "v8" and enabled) and rely on the --coverage CLI
flag or CI config to enable coverage when needed; ensure the coverage provider
remains set to "v8" if you keep the block but make enabled opt-in.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
apps/express/test/index.test.ts (1)
65-85: Theaura-auth.csrf_tokencookie on a GET request is unnecessary.CSRF protection applies to state-changing methods (POST, PUT, DELETE). Setting a CSRF cookie on this GET request has no effect but may mislead readers into thinking CSRF validation occurs on reads. Consider removing it to keep the test focused, or add a separate POST-based test that actually exercises CSRF validation.
Suggested simplification
const response = await supertest(app) .get("/api/protected") - .set("Cookie", [`aura-auth.session_token=${sessionToken}`, `aura-auth.csrf_token=valid_csrf_token`]) + .set("Cookie", [`aura-auth.session_token=${sessionToken}`])🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/express/test/index.test.ts` around lines 65 - 85, The test "returns protected data when a valid session cookie is present" sets an unnecessary CSRF cookie; remove the `aura-auth.csrf_token` entry from the Cookie header in that test so it only sends `aura-auth.session_token` (or alternatively add a new POST test that sends both `aura-auth.session_token` and `aura-auth.csrf_token` to exercise CSRF validation). Locate the test block in apps/express/test/index.test.ts (the async test named "returns protected data when a valid session cookie is present") and update the supertest call to omit the CSRF cookie or create a separate POST-based test to validate CSRF behavior.apps/express/src/middlewares/auth.ts (1)
61-65: Redirect responses return a JSON body instead of a bare redirect.For 3xx responses, this sends both the
Locationheader (line 57) and a JSON body{message, location}. Standard HTTP clients follow theLocationheader and ignore the body, so this works, but it's unconventional. If this is intentional (e.g., for SPA clients that inspect the body), consider adding a brief comment explaining the design choice.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/express/src/middlewares/auth.ts` around lines 61 - 65, The redirect branch in the auth middleware currently returns a JSON body (uses webResponse.headers.get("location") and res.json) for 3xx responses; change it to perform a proper HTTP redirect by using the Express redirect mechanism or by setting the status and Location header and ending the response (i.e., remove the JSON body). Update the branch that checks webResponse.status >= 300 && webResponse.status < 400 so it calls res.redirect(location) or res.status(webResponse.status).set('Location', location).end() instead of res.json, and optionally add a comment if returning JSON for SPA clients is intentional.
🤖 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/express/src/server.ts`:
- Around line 1-3: The Vitest config for the express app lacks a resolve.alias
mapping for the "@/..." TypeScript path, so tests fail to resolve imports like
import { verifySession } from "@/lib/verify-session.js"; update
apps/express/vitest.config.ts (the defineConfig block) to add a resolve.alias
entry mapping "@" to the project's src directory (e.g., using
path.resolve(__dirname, "./src")) so Vitest can resolve "@/..." imports at test
runtime.
---
Duplicate comments:
In `@apps/express/package.json`:
- Line 11: The package.json "test" script references vitest but vitest is
missing from devDependencies; add "vitest" (and optional related packages like
"@vitest/coverage-c8" if used) to the devDependencies section of
apps/express/package.json so the test script can run reliably; update the
version to a suitable semver (e.g., "^1.0.0") consistent with the repo's test
tooling and run npm/yarn install to validate.
- Line 2: The package name "express" in apps/express package.json conflicts with
the official npm package; update the "name" field (currently "express") to a
scoped, unique identifier such as "@aura-stack/express-example" (or another
org-prefixed name) so pnpm workspace resolution won't shadow the Express
framework; ensure any workspace references (e.g., "express": "workspace:*") are
updated to the new name as well.
In `@apps/express/src/lib/get-session.ts`:
- Line 35: Remove the redundant non-null assertion on exp in the expires
assignment inside getSession (the guard if (!exp) return null already ensures
exp is defined); update the line that sets expires to use new Date(exp *
1000).toISOString() without the trailing ! so the code relies on the earlier
guard rather than force-asserting the value.
---
Nitpick comments:
In `@apps/express/src/middlewares/auth.ts`:
- Around line 61-65: The redirect branch in the auth middleware currently
returns a JSON body (uses webResponse.headers.get("location") and res.json) for
3xx responses; change it to perform a proper HTTP redirect by using the Express
redirect mechanism or by setting the status and Location header and ending the
response (i.e., remove the JSON body). Update the branch that checks
webResponse.status >= 300 && webResponse.status < 400 so it calls
res.redirect(location) or res.status(webResponse.status).set('Location',
location).end() instead of res.json, and optionally add a comment if returning
JSON for SPA clients is intentional.
In `@apps/express/test/index.test.ts`:
- Around line 65-85: The test "returns protected data when a valid session
cookie is present" sets an unnecessary CSRF cookie; remove the
`aura-auth.csrf_token` entry from the Cookie header in that test so it only
sends `aura-auth.session_token` (or alternatively add a new POST test that sends
both `aura-auth.session_token` and `aura-auth.csrf_token` to exercise CSRF
validation). Locate the test block in apps/express/test/index.test.ts (the async
test named "returns protected data when a valid session cookie is present") and
update the supertest call to omit the CSRF cookie or create a separate
POST-based test to validate CSRF behavior.
Description
This pull request introduces an Express integration example for
@aura-stack/auth. The new example demonstrates how to integrate Aura Auth within a backend framework, providing middleware to manage OAuth 2.0 authentication flows, session handling, CSRF protection, and sign-out functionality. The application also mounts additional endpoints such as/healthand/api/protectedto validate and demonstrate the integration behavior in a server environment.Note
This is the first backend-focused integration example and the first to include automated testing. Unlike frontend integration, where flows are typically driven by browser interactions, backend environments require explicit request handling and verification, which motivated the inclusion of test coverage for authentication flows.
Resources
Summary by CodeRabbit
New Features
Documentation
Tests
Chores