82 lines
2.6 KiB
Markdown
82 lines
2.6 KiB
Markdown
# @wrnexus/helpers
|
|
|
|
Safe convenience helpers for common WrNexus application flows. The package uses
|
|
standard `Context`, `URL`, and `Response` values and has no runtime dependency beyond
|
|
`@wrnexus/core`.
|
|
|
|
## Installation
|
|
|
|
```bash
|
|
bun add @wrnexus/helpers
|
|
```
|
|
|
|
The package is private, so the machine must be authenticated to the `wrnexus` npm
|
|
organization.
|
|
|
|
## Usage
|
|
|
|
### Redirect an unauthenticated forward-auth request
|
|
|
|
The gateway calls an SSO verifier on a different URL from the original application.
|
|
These helpers reconstruct the original URL from the gateway headers and safely place it
|
|
in the login redirect:
|
|
|
|
```ts
|
|
import type { Context } from "@wrnexus/core";
|
|
import { redirectToLogin } from "@wrnexus/helpers";
|
|
|
|
export const GET = async (ctx: Context) => {
|
|
if (await hasValidSession(ctx)) {
|
|
return new Response(null, { status: 204 });
|
|
}
|
|
|
|
return redirectToLogin(ctx, "/login", {
|
|
allowedHosts: ["admin.localhost:3000", "reports.localhost:3000"],
|
|
});
|
|
};
|
|
```
|
|
|
|
This creates a response such as:
|
|
|
|
```text
|
|
Location: http://sso.localhost:3000/login?returnTo=http%3A%2F%2Fadmin.localhost%3A3000%2F
|
|
```
|
|
|
|
Always list the application hosts that are valid redirect destinations. Forwarded host
|
|
headers are rejected when `allowedHosts` is absent or does not match, preventing an open
|
|
redirect.
|
|
|
|
The SSO hostname is the login destination, not an `allowedHosts` entry. For example,
|
|
when protecting `admin.localhost:3000`, keep `admin.localhost:3000` in the allowlist even
|
|
though the verifier runs at `sso.localhost:3000`. WRNexus preserves both hosts across a
|
|
nested gateway request.
|
|
|
|
### Support dynamic tenant domains
|
|
|
|
```ts
|
|
import type { Context } from "@wrnexus/core";
|
|
import { getOriginalRequestOrigin, redirectToLogin } from "@wrnexus/helpers";
|
|
|
|
export const GET = async (ctx: Context) => {
|
|
const allowedHosts = (host: string) => host === "example.test" || host.endsWith(".example.test");
|
|
|
|
console.info("Authentication requested by", getOriginalRequestOrigin(ctx, { allowedHosts }));
|
|
return redirectToLogin(ctx, "https://auth.example.test/login", {
|
|
allowedHosts,
|
|
returnToParam: "continue",
|
|
status: 303,
|
|
});
|
|
};
|
|
```
|
|
|
|
## API
|
|
|
|
- `getOriginalRequestUrl(ctx, options): URL` — reconstruct the gateway URL.
|
|
- `getOriginalRequestOrigin(ctx, options): string` — return only its origin.
|
|
- `getOriginalRequestPath(ctx): string` — return its path and query string.
|
|
- `getOriginalRequestMethod(ctx): string` — return its HTTP method.
|
|
- `redirectToLogin(ctx, loginUrl, options): Response` — create a login redirect with an
|
|
encoded `returnTo` parameter.
|
|
|
|
For direct requests without gateway headers, URL helpers use `ctx.url`.
|