You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/content/1.guide/11.client.md
+3-1Lines changed: 3 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -87,9 +87,11 @@ if (!trusted) {
87
87
88
88
### Authenticating with a one-time code
89
89
90
-
The dev server prints a single-use 6-digit code (expires in five minutes, rotates after repeated wrong attempts); `requestTrustWithCode` exchanges it for a persisted node-issued token shared across sibling tabs:
90
+
The dev server prints a single-use 6-digit code (expires in five minutes, rotates after repeated wrong attempts) when an untrusted RPC client asks for one: call `requestAuthCode()` when your auth UI shows, passing `{ reissue: true }` from a "re-issue" button to rotate the code first. `requestTrustWithCode` then exchanges it for a persisted node-issued token shared across sibling tabs:
91
91
92
92
```ts
93
+
awaitrpc.requestAuthCode()
94
+
// … the developer reads the code from the terminal …
Copy file name to clipboardExpand all lines: docs/content/1.guide/14.security.md
+4-4Lines changed: 4 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -19,14 +19,14 @@ An RPC handler runs with the full privileges of its Node process (filesystem, ch
19
19
20
20
## The pre-trust gate
21
21
22
-
One rule decides what an untrusted connection may call: **a method is reachable before trust iff its name starts with `anonymous:`** (`isAnonymousRpcMethod`, from `devframe/constants`); only the two handshake methods below qualify.
22
+
One rule decides what an untrusted connection may call: **a method is reachable before trust iff its name starts with `anonymous:`** (`isAnonymousRpcMethod`, from `devframe/constants`); only the handshake and code-request methods below qualify.
23
23
24
24
The RPC server binding enforces this: pass `auth: authHandler` (its `.authorize` becomes the gate) or your own `authorize(methodName, session)`. Every other call from an untrusted session throws [`DF0036`](/errors/DF0036). `rpc.call` / `rpc.callOptional` / `rpc.callEvent` hold calls issued during the first handshake and release them once it settles.
25
25
26
26
## Authentication flow
27
27
28
28
1. A fresh RPC client calls `anonymous:devframe:auth` with its stored token (empty on first run); the server returns `{ isTrusted: false }` and the UI prompts for a code.
29
-
2. The dev server shows a 6-digit codein the terminal (`auth.printBanner()` once listening).
29
+
2. The auth UI requests a code (`rpc.requestAuthCode()`, sent automatically when the built-in notice view first shows, or by its "re-issue" button with `{ reissue: true }` to rotate the code first); the dev server prints the 6-digit code, its expiry, and the requesting browser in the terminal. An already-authorized page never triggers a print.
30
30
3. The developer enters it; the browser calls `requestTrustWithCode(code)`.
31
31
4. The server verifies the code, mints a high-entropy bearer token, trusts the session, and returns it.
32
32
5. The browser persists the token and presents it on reconnect (or via a `?devframe_auth_token=` query param the connect-time hook checks first); sibling tabs receive it over the `devframe-auth` channel and become trusted.
@@ -51,11 +51,11 @@ Pass `clientAuthTokens` for CI/shared machines to skip the prompt, or a custom `
51
51
52
52
### Auth methods
53
53
54
-
The two `anonymous:`-prefixed handshake methods re-authenticate a stored token (`anonymous:devframe:auth`) and exchange a one-time code for a token (`anonymous:devframe:auth:exchange`); `devframe:auth:revoke` self-revokes, and the `devframe:auth:revoked` event drops affected RPC clients to untrusted. Wire shapes are in the [Node-Side API reference](/references/node-api#auth-methods).
54
+
The `anonymous:`-prefixed methods re-authenticate a stored token (`anonymous:devframe:auth`), exchange a one-time code for a token (`anonymous:devframe:auth:exchange`), and ask the server to print its code banner (`anonymous:devframe:auth:request-code`); `devframe:auth:revoke` self-revokes, and the `devframe:auth:revoked` event drops affected RPC clients to untrusted. Wire shapes are in the [Node-Side API reference](/references/node-api#auth-methods).
55
55
56
56
Node primitives in `devframe/node/auth` (`getTempAuthCode` / `refreshTempAuthCode`, `exchangeTempAuthCode`, `verifyAuthToken`, `buildOtpAuthUrl`, and `revokeAuthToken`) implement the same flow for a host framework wiring its own gate; signatures are in the [reference](/references/node-api#node-auth-primitives).
57
57
58
-
RPC client methods (`devframe/client`): `requestTrustWithCode(code)`, `requestTrustWithToken(token)`, and `ensureTrusted(timeout?)` / `isTrusted` (the trust gate).
58
+
RPC client methods (`devframe/client`): `requestAuthCode(options?)` (print the code banner; `{ reissue: true }` rotates the code first), `requestTrustWithCode(code)`, `requestTrustWithToken(token)`, and `ensureTrusted(timeout?)` / `isTrusted` (the trust gate).
Copy file name to clipboardExpand all lines: docs/content/2.adapters/1.initiate.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -129,7 +129,7 @@ Fetch handlers only hand over `Request`s, so the host framework binds the RPC so
129
129
130
130
## Auth
131
131
132
-
The running devframe **gates by default**. The interactive OTP handler wires automatically, printing its code/magic-link banner once the public origin is known, whether from the `origin` option or derived from a request whose own origin is loopback or exactly matches an `allowedOrigins` entry. A non-loopback deployment (behind a proxy, on a LAN, on a public host) sets `origin` explicitly so the magic link resolves to the intended address; a raw inbound `Host` header and forwarded headers are never trusted. Pass `auth: false` for single-user localhost, or a `DevframeAuthHandler` for a custom scheme.
132
+
The running devframe **gates by default**. The interactive OTP handler wires automatically, printing its code/magic-link banner when an untrusted browser client asks for a code (`rpc.requestAuthCode()`); an already-authorized page triggers no print. The magic link's origin comes from the `origin` option, or is derived from a request whose own origin is loopback or exactly matches an `allowedOrigins` entry. A non-loopback deployment (behind a proxy, on a LAN, on a public host) sets `origin` explicitly so the magic link resolves to the intended address; a raw inbound `Host` header and forwarded headers are never trusted. Pass `auth: false` for single-user localhost, or a `DevframeAuthHandler` for a custom scheme.
|`banner`| a small boxed console message | Called with `{ code, url }`; prints via `printBanner()`. |
33
+
|`banner`| a small boxed console message | Called with `{ code, url, expireAt, requester? }` (`requester` is the asking browser client's `{ ua, origin }`, present on client-requested prints); prints via `printBanner()`. |
34
34
|`onTrusted`|`undefined`| Called with `{ session, authToken }` (the trust session and its token) once a code exchange succeeds, so a host framework rendering its own banner can retract it. |
35
35
|`serverUrl`|`context.host.resolveOrigin()`| Magic-link base URL. |
|`onConnect(peer, session)`| Connect-time trust from a bearer on the WS upgrade URL (`?devframe_auth_token=`). |
44
-
|`printBanner()`| Prints the code + magic-link URL. |
44
+
|`printBanner()`| Prints the code + magic-link URL, at most once per code. |
45
45
46
46
## Using the pieces directly
47
47
@@ -60,6 +60,6 @@ if (!auth.authorize(methodName, session))
60
60
auth.onConnect(peer, session)
61
61
```
62
62
63
-
An exchange rotates the code and prints the new one, and `onTrusted` fires after that, so a host framework retracting a sticky notice drops that follow-up too and calls `auth.printBanner()`when it next wants a code on screen.
63
+
The banner prints on demand: an untrusted browser client requests it over `anonymous:devframe:auth:request-code` (the RPC client's `requestAuthCode()`, sent when an auth UI first shows or its "re-issue" action runs), or the host calls `auth.printBanner()`itself. An exchange rotates the code silently, and `onTrusted` fires so a host framework rendering a sticky notice can retract it.
64
64
65
65
Auth storage is internal, not `devframe/node/hub-internals`.
Copy file name to clipboardExpand all lines: docs/content/8.references/4.node-api.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -180,6 +180,7 @@ The wire-level RPC methods of the trust handshake: [Security](/guide/security#au
180
180
|------------|-----------|-------|
181
181
|`anonymous:devframe:auth`| client → server |`{ authToken, ua, origin }` → `{ isTrusted }`: re-authenticate a stored token |
182
182
|`anonymous:devframe:auth:exchange`| client → server |`{ code, ua, origin }` → `{ authToken \| null }`: exchange a code for a token |
183
+
|`anonymous:devframe:auth:request-code`| client → server |`{ ua, origin, reissue? }` → print the code banner in the server terminal (`reissue: true` rotates the code first) |
183
184
|`devframe:auth:revoke`| client → server | self-revoke the caller's own token |
184
185
|`devframe:auth:revoked`| server → client | event: token revoked |
0 commit comments