mirror of
https://github.com/nestriness/nestri.git
synced 2026-09-19 17:25:19 +03:00
Two changes to who may start a flow here, and where a refusal is delivered. A host reached at its own hostname sits on a different registrable domain from this issuer, deliberately: that is what stops a cookie set there from ever reaching this one. The default rule allows a redirect back to whatever hostname the request arrived on, so it refused exactly the case the separation created. Which is a real problem rather than a theoretical one, because a session cookie without a Domain attribute is host-only, so a browser arriving at one of those hostnames for the first time carries no cookie whether or not it is signed in, and sending it here to sign in again changes nothing. So a client id that is a single hostname under that zone, whose redirect_uri is https and that same hostname at one reserved path, is allowed. Making the client id the hostname is the load-bearing part: a token's audience is its client id, so the session that comes back is bound to the host it will live on and is not a credential anywhere else. Separately, and worth its own paragraph: a refused client's redirect_uri was still used to report the refusal. The check that approves that URI is the one that just failed, so /authorize was an open redirector to anywhere at all -- no sign-in required, on the hostname people are asked to type a password into. It is now a page here. Before: GET /authorize?client_id=web&redirect_uri=https://somewhere.example/callback -> 302 https://somewhere.example/callback?error=unauthorized_client
packages/auth (@nestri/auth)
Framework-agnostic OpenAuth implementation for Nestri — the OAuth/OIDC issuer, client, subjects, and the login UI. A vendored/forked build of OpenAuth.
What it does
Everything needed to run your own authentication provider:
issuer.ts— the authorization server: routes for/authorize,/callback,/token,/userinfo,.well-known/*, plus the login UI (React renderer).client.ts—createClientto verify JWTs against the issuer ("who is this token?").subject.ts— typed JWT subjects (zodschemas for the token payload).provider/*— drop-in OAuth/OIDC providers (steam, discord, github, google, apple, microsoft, slack, spotify, twitch, x, yahoo, facebook, linkedin, cognito, keycloak, jumpcloud, oauth2, oidc, password, ssh, code, arctic).storage/*— persistence adapters for keys/sessions/codes:memory,cloudflare(KV),aws,dynamo.ui/*— the login page components (forms, password, code, theme, CSS).jwt.ts,keys.ts,pkce.ts,random.ts— signing, keypair management, PKCE, randomness.
Usage
Consumed by the apps/auth worker, e.g.:
import { issuer } from '@nestri/auth/index';
import { CloudflareStorage } from '@nestri/auth/storage/cloudflare';
import { SteamProvider } from '@nestri/auth/provider/steam';
The API uses createClient (from @openauth/openauth/client) or the bundled client.ts to verify
tokens against the issuer URL.
Scripts
bun test # run tests
bun run build # build (see script/build.ts)
Note
@openauthjs is the upstream project; this package's exports are meant to be API-compatible with a
pinned preference toward tree-shaking-friendly imports. Prefer importing subpaths over the barrel
(@nestri/auth/index).