-
-
Notifications
You must be signed in to change notification settings - Fork 788
feat(route-rules): basic auth #4049
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
222ab46
c594eda
a32579e
23a8592
763d365
6d64618
b9be0c2
8206228
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -386,6 +386,34 @@ | |
| expect(headers).toMatchObject(expectedHeaders); | ||
| }); | ||
|
|
||
| describe("handles route rules - basic auth", () => { | ||
| it("rejects request with bad creds", async () => { | ||
| const { status, headers } = await callHandler({ | ||
| url: "/rules/basic-auth", | ||
| headers: { | ||
| Authorization: "Basic " + btoa("user:wrongpass"), | ||
| }, | ||
| }); | ||
| expect(status).toBe(401); | ||
| expect(headers["www-authenticate"]).toBe('Basic realm="Secure Area"'); | ||
|
Check failure on line 398 in test/tests.ts
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π§© Analysis chainπ Script executed: # First, let's find the fixture basicAuth config
find test -type f -name "*.ts" -o -name "*.js" | head -20Repository: nitrojs/nitro Length of output: 773 π Script executed: # Search for basicAuth in test fixtures
rg -n "basicAuth" test/ --type=ts -A5 -B2Repository: nitrojs/nitro Length of output: 721 π Script executed: # Search for WWW-Authenticate header handling in src
rg -n "WWW-Authenticate|www-authenticate" src/ --type=ts -A2 -B2Repository: nitrojs/nitro Length of output: 39 π Script executed: # Check route-rules implementation
fd -t f "route-rules" src/ --exec cat -n {} \;Repository: nitrojs/nitro Length of output: 9644 π Script executed: # Look for basicAuth in route-rules
rg -n "basicAuth" src/ --type=ts -A5 -B2Repository: nitrojs/nitro Length of output: 1743 π Script executed: # Check the test file to see exact test setup at line 393-398
sed -n '393,398p' test/tests.tsRepository: nitrojs/nitro Length of output: 265 π Script executed: # Look for any h3 version or documentation in package.json
cat package.json | grep -A2 -B2 "h3"Repository: nitrojs/nitro Length of output: 460 π Script executed: # Check if there are any other basicAuth tests or examples in the codebase
rg -n "requireBasicAuth|basicAuth" test/ --type=ts -B2 -A2 | head -50Repository: nitrojs/nitro Length of output: 571 π Script executed: # Check if there's a test setup or fixture initialization that might affect headers
sed -n '389,415p' test/tests.tsRepository: nitrojs/nitro Length of output: 942 π Script executed: # Look for any callHandler function that processes the response
rg -n "callHandler" test/tests.ts -B3 -A10 | head -40Repository: nitrojs/nitro Length of output: 1496 π Script executed: # Check the complete callHandler implementation to see how headers are extracted
sed -n '203,240p' test/tests.tsRepository: nitrojs/nitro Length of output: 1175 π Script executed: # Look for the TestHandlerResult type definition to understand header structure
rg -n "TestHandlerResult" test/ --type=ts -B5 -A5Repository: nitrojs/nitro Length of output: 1364 π Script executed: # Check if there's any middleware or handler setup that might affect basicAuth
rg -n "basicAuth|requireBasicAuth" test/fixture/ --type=ts -A5Repository: nitrojs/nitro Length of output: 568 π Script executed: # Let's check h3 documentation or type definition for requireBasicAuth behavior
rg -n "requireBasicAuth" --type=ts -B3 -A10 | head -30Repository: nitrojs/nitro Length of output: 1427 π Script executed: # Check if there are other basicAuth tests that pass to understand expected behavior
rg -n "www-authenticate|WWW-Authenticate" test/ --type=ts -B5 -A5Repository: nitrojs/nitro Length of output: 617 π Script executed: # Let's check if there's any test output or debug logs that show actual header values
rg -n "Basic realm\|www-authenticate" test/ --type=tsRepository: nitrojs/nitro Length of output: 39 π Script executed: # Check if there are any comments in the PR or test about expected h3 behavior
rg -n "h3|requireBasicAuth" test/tests.ts -B2 -A2 | grep -i "comment\|todo\|fixme\|note"Repository: nitrojs/nitro Length of output: 39 π Script executed: # Let's check what h3 version might have this issue or if there are any known issues
cat package.json | grep -E "h3|version"Repository: nitrojs/nitro Length of output: 250 π Script executed: # See if there's a test that sends no credentials to understand expected behavior difference
sed -n '380,420p' test/tests.tsRepository: nitrojs/nitro Length of output: 1489 π Script executed: # Check if there's any documentation or comments about the basicAuth implementation
head -20 src/runtime/internal/route-rules.tsRepository: nitrojs/nitro Length of output: 936 π Script executed: # Let's check if h3's requireBasicAuth is even being exported from h3 in package.json exports
rg -n "requireBasicAuth" package.jsonRepository: nitrojs/nitro Length of output: 39 π Script executed: # Check if there are any setup/teardown issues or middleware that might strip headers
sed -n '140,200p' test/tests.ts | grep -A10 -B10 "describe\|middleware"Repository: nitrojs/nitro Length of output: 39 π Web query:
π‘ Result: In h3 (the UnJS/h3 framework), Per the HTTP authentication spec, a 401 response for a protected resource must include at least one Sources: π Web query:
π‘ Result: In h3
What it does (behavior / flow)At request time, the middleware:
Security-related implementation details present in the v2 RCsThe v2 RC line includes hardening specifically for Basic Auth comparisons:
Minimal βshapeβ of the implementation (pseudocode)export function basicAuth(opts) {
return async (event) => {
await requireBasicAuth(event, opts) // throws / returns 401 response on failure
}
}Where Sources: [1] (H3 security utils docs), [2] (release note mentioning jitter + constant-time compare), [3] (rc.14 release note about stronger random jitter).
The test at line 398 expects the header but receives The fixture configuration is correct ( The actual root cause lies either in h3's π§° Toolsπͺ GitHub Check: tests-rolldown (ubuntu-latest)[failure] 398-398: test/presets/standard.test.ts > nitro:standard > handles route rules - basic auth > rejects request with bad creds
β― test/tests.ts:398:43 [failure] 398-398: test/presets/node.test.ts > nitro:preset:node-middleware > handles route rules - basic auth > rejects request with bad creds
β― test/tests.ts:398:43 [failure] 398-398: test/presets/nitro-dev.test.ts > nitro:preset:nitro-dev > handles route rules - basic auth > rejects request with bad creds
β― test/tests.ts:398:43 [failure] 398-398: test/presets/netlify.test.ts > nitro:preset:netlify > handles route rules - basic auth > rejects request with bad creds
β― test/tests.ts:398:43 [failure] 398-398: test/presets/deno-server.test.ts > nitro:preset:deno-server > handles route rules - basic auth > rejects request with bad creds
β― test/tests.ts:398:43 [failure] 398-398: test/presets/cloudflare-pages.test.ts > nitro:preset:cloudflare-pages > handles route rules - basic auth > rejects request with bad creds
β― test/tests.ts:398:43 [failure] 398-398: test/presets/cloudflare-module.test.ts > nitro:preset:cloudflare-module > handles route rules - basic auth > rejects request with bad creds
β― test/tests.ts:398:43 [failure] 398-398: test/presets/bun.test.ts > nitro:preset:bun > handles route rules - basic auth > rejects request with bad creds
β― test/tests.ts:398:43 [failure] 398-398: test/presets/aws-lambda.test.ts > nitro:preset:aws-lambda-v1 > handles route rules - basic auth > rejects request with bad creds
β― test/tests.ts:398:43 [failure] 398-398: test/presets/aws-lambda.test.ts > nitro:preset:aws-lambda-v2 > handles route rules - basic auth > rejects request with bad creds
β― test/tests.ts:398:43 π€ Prompt for AI Agents |
||
| }); | ||
|
|
||
| it("allows request with correct password", async () => { | ||
| const { status } = await callHandler({ | ||
| url: "/rules/basic-auth/test", | ||
| headers: { | ||
| Authorization: "Basic " + btoa("admin:secret"), | ||
| }, | ||
| }); | ||
| expect(status).toBe(200); | ||
| }); | ||
|
|
||
| it("disabled basic-auth for sub-rules", async () => { | ||
| const { status } = await callHandler({ url: "/rules/basic-auth/no-auth" }); | ||
| expect(status).toBe(200); | ||
| }); | ||
| }); | ||
|
|
||
| it("handles route rules - allowing overriding", async () => { | ||
| const override = await callHandler({ url: "/rules/nested/override" }); | ||
| expect(override.headers.location).toBe("/other"); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Credentials will be embedded in plaintext in the compiled bundle.
Adding
"basicAuth"toRuntimeRouteRulesmeansserializeRouteRule(line 101) will callJSON.stringify(options)on the basicAuth options object, embeddingpasswordandusernamevalues directly as a string literal in the generated virtual module and therefore in the compiled server bundle.Unlike other entries in
RuntimeRouteRules(headers, redirect, proxy, cache),basicAuthexplicitly carries secrets. Any party with read access to the bundle artifact (e.g., a deployed Docker image layer, edge-worker script, or accidental bundle exposure) can extract the credentials trivially.Consider documenting this trade-off prominently and/or guiding users to supply credentials via environment variables, e.g.:
At minimum, a warning during the build step (via
consola.warn) whenbasicAuthoptions contain a non-empty literalpasswordwould alert users who accidentally hardcode credentials. As per coding guidelines,consolashould be used for logging in build/dev code.π€ Prompt for AI Agents