From afc7430ea9cb1f75e88f964da02ca13c94b232d0 Mon Sep 17 00:00:00 2001 From: hdbjeff Date: Wed, 2 Sep 2026 11:15:37 -0700 Subject: [PATCH 1/3] Document route-owned authentication fallthrough --- reference/http/overview.md | 10 ++++++++++ reference/security/overview.md | 10 ++++++++++ release-notes/v5-lincoln/5.3.md | 4 ++++ 3 files changed, 24 insertions(+) diff --git a/reference/http/overview.md b/reference/http/overview.md index 7772b2a70..7bcfb78bc 100644 --- a/reference/http/overview.md +++ b/reference/http/overview.md @@ -26,6 +26,16 @@ Harper uses a layered middleware chain for HTTP request processing. Components a Request and response objects follow the [WHATWG Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) conventions (`Request` and `Response` classes), providing good composability for layered middleware and clean mapping to REST resource handlers. +### Authentication and fallthrough + + + +Authentication runs before the default middleware chain determines route ownership. A Basic or Bearer credential that Harper recognizes establishes `request.user`. A credential that Harper does not recognize leaves `request.user` unset while its original `Authorization` header continues through the chain. + +A Harper-owned handler settles that deferred authentication failure before responding, so an unrecognized credential cannot turn a protected Harper route into anonymous access. A handler that calls `next(request)` without claiming the route leaves the credential available to later application middleware. This allows an unmounted catch-all handler to authenticate and proxy an open-ended set of application URLs without registering each URL with `urlPath`. + +An application receiving a deferred credential must validate it using its own authentication scheme. If no handler claims the request, Harper returns not found rather than treating the existence of an `Authorization` header as proof that the URL belongs to Harper. Internal Harper authentication errors remain fail-closed. See [Security](../security/overview.md#authentication-and-route-ownership) for the security boundary. + ### Middleware routing diff --git a/reference/security/overview.md b/reference/security/overview.md index f62b4fae4..025f8e3f8 100644 --- a/reference/security/overview.md +++ b/reference/security/overview.md @@ -26,6 +26,16 @@ Harper supports three authentication methods: - [JWT Authentication](./jwt-authentication.md) — Token-based authentication using JSON Web Tokens. Clients authenticate once and receive short-lived operation tokens and longer-lived refresh tokens. - [mTLS Authentication](./mtls-authentication.md) — Mutual TLS certificate-based authentication. +## Authentication and Route Ownership + + + +On the application HTTP port, Harper attempts authentication before resolving which handler owns a request. A valid Harper credential establishes the Harper user as usual. When a Basic or Bearer credential is not recognized by Harper, Harper preserves the original `Authorization` header and defers the unauthorized response until a handler claims the request. + +A Harper-owned route returns the normal unauthorized response before running its operation. If no Harper route claims the request, a later application handler receives the unchanged header and can apply its own authentication scheme. If no handler claims the request, the request ends as not found. Authentication infrastructure failures are not deferred and remain fail-closed. + +This behavior is automatic and has no configuration option. Application handlers that accept non-Harper credentials are responsible for validating those credentials before serving protected content. See [HTTP request handling](../http/overview.md#authentication-and-fallthrough) for the middleware ownership contract. + ## Certificate Management - [Certificate Management](./certificate-management.md) — Managing TLS certificates and Certificate Authorities for HTTPS and mTLS. diff --git a/release-notes/v5-lincoln/5.3.md b/release-notes/v5-lincoln/5.3.md index c7928d4d9..3d1924174 100644 --- a/release-notes/v5-lincoln/5.3.md +++ b/release-notes/v5-lincoln/5.3.md @@ -22,6 +22,10 @@ See [Configuration Options](/reference/v5/configuration/options#node). ## Security +### Route-Owned Authentication + +Harper now defers rejection of an unrecognized Basic or Bearer credential on the application HTTP port until a handler claims the request. Harper-owned routes still return the normal unauthorized response, while unowned routes can fall through to application middleware with the original `Authorization` header unchanged. This lets catch-all applications and reverse proxies apply their own authentication schemes without URL exemptions or header rewriting. Internal authentication failures continue to fail closed. See [Authentication and route ownership](/reference/v5/security/overview#authentication-and-route-ownership). + ### OIDC Trusted Publishing A CI runner can now authenticate to Harper with no stored credential. It presents an identity token minted by its own provider, and if that token verifies against a trust policy configured on the instance, Harper returns a one-hour operation token for the user the policy names — the same exchange npm, PyPI, and AWS STS `AssumeRoleWithWebIdentity` use. This replaces a 30-day refresh-token secret with a rule you configure once and revoke with `drop_oidc_trust`. From 05e6ba2c65d79853ebcd8f8aab55508aefe1397b Mon Sep 17 00:00:00 2001 From: hdbjeff Date: Wed, 2 Sep 2026 11:44:33 -0700 Subject: [PATCH 2/3] Separate route authentication security outcomes in docs --- reference/http/overview.md | 2 +- release-notes/v5-lincoln/5.3.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/reference/http/overview.md b/reference/http/overview.md index 7bcfb78bc..a98020b77 100644 --- a/reference/http/overview.md +++ b/reference/http/overview.md @@ -32,7 +32,7 @@ Request and response objects follow the [WHATWG Fetch API](https://developer.moz Authentication runs before the default middleware chain determines route ownership. A Basic or Bearer credential that Harper recognizes establishes `request.user`. A credential that Harper does not recognize leaves `request.user` unset while its original `Authorization` header continues through the chain. -A Harper-owned handler settles that deferred authentication failure before responding, so an unrecognized credential cannot turn a protected Harper route into anonymous access. A handler that calls `next(request)` without claiming the route leaves the credential available to later application middleware. This allows an unmounted catch-all handler to authenticate and proxy an open-ended set of application URLs without registering each URL with `urlPath`. +A Harper-owned handler settles that deferred authentication failure before responding. This prevents an unrecognized credential from turning a protected Harper route into anonymous access. A handler that calls `next(request)` without claiming the route leaves the credential available to later application middleware. This allows an unmounted catch-all handler to authenticate and proxy an open-ended set of application URLs without registering each URL with `urlPath`. An application receiving a deferred credential must validate it using its own authentication scheme. If no handler claims the request, Harper returns not found rather than treating the existence of an `Authorization` header as proof that the URL belongs to Harper. Internal Harper authentication errors remain fail-closed. See [Security](../security/overview.md#authentication-and-route-ownership) for the security boundary. diff --git a/release-notes/v5-lincoln/5.3.md b/release-notes/v5-lincoln/5.3.md index 3d1924174..a0c3e69ab 100644 --- a/release-notes/v5-lincoln/5.3.md +++ b/release-notes/v5-lincoln/5.3.md @@ -24,7 +24,7 @@ See [Configuration Options](/reference/v5/configuration/options#node). ### Route-Owned Authentication -Harper now defers rejection of an unrecognized Basic or Bearer credential on the application HTTP port until a handler claims the request. Harper-owned routes still return the normal unauthorized response, while unowned routes can fall through to application middleware with the original `Authorization` header unchanged. This lets catch-all applications and reverse proxies apply their own authentication schemes without URL exemptions or header rewriting. Internal authentication failures continue to fail closed. See [Authentication and route ownership](/reference/v5/security/overview#authentication-and-route-ownership). +Harper now defers rejection of an unrecognized Basic or Bearer credential on the application HTTP port until a handler claims the request. Harper-owned routes still return the normal unauthorized response. Unowned routes can fall through to application middleware with the original `Authorization` header unchanged. This lets catch-all applications and reverse proxies apply their own authentication schemes without URL exemptions or header rewriting. Internal authentication failures continue to fail closed. See [Authentication and route ownership](/reference/v5/security/overview#authentication-and-route-ownership). ### OIDC Trusted Publishing From 9bbf239c6772fe32f12f1de3044191e07cbfc807 Mon Sep 17 00:00:00 2001 From: Jeff Ordway Date: Thu, 3 Sep 2026 09:26:38 -0700 Subject: [PATCH 3/3] Document that Harper does not rewrite a deferred-credential 401 Review on HarperFast/harper#2419 found that authentication was re-decorating any 401 returned up the chain: overwriting WWW-Authenticate with Basic, or rewriting it to a login-page redirect for a browser. That silently replaced an application catch-all's own challenge, which is the case this feature exists to support. The fix scopes that rewriting away from deferred credentials, so the externally visible contract now includes response provenance. Also records the WebSocket/MQTT upgrade outcome for an unrecognized credential. Co-Authored-By: Claude Opus 5 (1M context) --- reference/http/overview.md | 2 +- reference/security/overview.md | 4 ++++ release-notes/v5-lincoln/5.3.md | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/reference/http/overview.md b/reference/http/overview.md index a98020b77..16f81c2d1 100644 --- a/reference/http/overview.md +++ b/reference/http/overview.md @@ -34,7 +34,7 @@ Authentication runs before the default middleware chain determines route ownersh A Harper-owned handler settles that deferred authentication failure before responding. This prevents an unrecognized credential from turning a protected Harper route into anonymous access. A handler that calls `next(request)` without claiming the route leaves the credential available to later application middleware. This allows an unmounted catch-all handler to authenticate and proxy an open-ended set of application URLs without registering each URL with `urlPath`. -An application receiving a deferred credential must validate it using its own authentication scheme. If no handler claims the request, Harper returns not found rather than treating the existence of an `Authorization` header as proof that the URL belongs to Harper. Internal Harper authentication errors remain fail-closed. See [Security](../security/overview.md#authentication-and-route-ownership) for the security boundary. +An application receiving a deferred credential must validate it using its own authentication scheme, and the response it produces is returned unchanged — Harper does not replace an application's `WWW-Authenticate` challenge or turn its `401` into a login-page redirect. If no handler claims the request, Harper returns not found rather than treating the existence of an `Authorization` header as proof that the URL belongs to Harper. Internal Harper authentication errors remain fail-closed. See [Security](../security/overview.md#authentication-and-route-ownership) for the security boundary. ### Middleware routing diff --git a/reference/security/overview.md b/reference/security/overview.md index 025f8e3f8..36d83ce7f 100644 --- a/reference/security/overview.md +++ b/reference/security/overview.md @@ -34,6 +34,10 @@ On the application HTTP port, Harper attempts authentication before resolving wh A Harper-owned route returns the normal unauthorized response before running its operation. If no Harper route claims the request, a later application handler receives the unchanged header and can apply its own authentication scheme. If no handler claims the request, the request ends as not found. Authentication infrastructure failures are not deferred and remain fail-closed. +When a request carries a deferred credential, Harper does not rewrite the unauthorized response that comes back. An application handler's own `401` — including its `WWW-Authenticate` challenge for its own scheme — is returned to the client as the handler wrote it, and Harper does not substitute its own challenge or redirect the request to a configured login page. A Harper-owned route settling the deferred credential answers exactly as it did before this behavior existed. + +A WebSocket or MQTT-over-WebSocket upgrade carrying an unrecognized credential is closed with WebSocket close code `3000` rather than being established as an anonymous connection. + This behavior is automatic and has no configuration option. Application handlers that accept non-Harper credentials are responsible for validating those credentials before serving protected content. See [HTTP request handling](../http/overview.md#authentication-and-fallthrough) for the middleware ownership contract. ## Certificate Management diff --git a/release-notes/v5-lincoln/5.3.md b/release-notes/v5-lincoln/5.3.md index a0c3e69ab..bda4cd884 100644 --- a/release-notes/v5-lincoln/5.3.md +++ b/release-notes/v5-lincoln/5.3.md @@ -24,7 +24,7 @@ See [Configuration Options](/reference/v5/configuration/options#node). ### Route-Owned Authentication -Harper now defers rejection of an unrecognized Basic or Bearer credential on the application HTTP port until a handler claims the request. Harper-owned routes still return the normal unauthorized response. Unowned routes can fall through to application middleware with the original `Authorization` header unchanged. This lets catch-all applications and reverse proxies apply their own authentication schemes without URL exemptions or header rewriting. Internal authentication failures continue to fail closed. See [Authentication and route ownership](/reference/v5/security/overview#authentication-and-route-ownership). +Harper now defers rejection of an unrecognized Basic or Bearer credential on the application HTTP port until a handler claims the request. Harper-owned routes still return the normal unauthorized response. Unowned routes can fall through to application middleware with the original `Authorization` header unchanged. This lets catch-all applications and reverse proxies apply their own authentication schemes without URL exemptions or header rewriting, and the unauthorized response such an application returns — including its own `WWW-Authenticate` challenge — is passed back to the client unchanged. Internal authentication failures continue to fail closed. See [Authentication and route ownership](/reference/v5/security/overview#authentication-and-route-ownership). ### OIDC Trusted Publishing