@cauthyhq/node 1.0.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +71 -0
- package/README.md +81 -24
- package/dist/{cauthy-B6Sm3T8M.d.ts → cauthy-C7gZ-pbv.d.ts} +88 -3
- package/dist/{cauthy-ClP5orP4.d.mts → cauthy-CCSSj3Lg.d.mts} +88 -3
- package/dist/express.d.mts +2 -1
- package/dist/express.d.ts +2 -1
- package/dist/fastify.d.mts +2 -1
- package/dist/fastify.d.ts +2 -1
- package/dist/hono.d.mts +2 -1
- package/dist/hono.d.ts +2 -1
- package/dist/identity-BTJ8NB_w.d.mts +27 -0
- package/dist/identity-BTJ8NB_w.d.ts +27 -0
- package/dist/index.d.mts +21 -2
- package/dist/index.d.ts +21 -2
- package/dist/index.js +686 -66
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +681 -66
- package/dist/index.mjs.map +1 -1
- package/dist/keys.js.map +1 -1
- package/dist/keys.mjs.map +1 -1
- package/dist/mcp.js.map +1 -1
- package/dist/mcp.mjs.map +1 -1
- package/dist/next.d.mts +2 -1
- package/dist/next.d.ts +2 -1
- package/dist/testing.d.mts +49 -1
- package/dist/testing.d.ts +49 -1
- package/dist/testing.js +488 -5
- package/dist/testing.js.map +1 -1
- package/dist/testing.mjs +486 -4
- package/dist/testing.mjs.map +1 -1
- package/package.json +8 -3
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 1.2.0
|
|
4
|
+
|
|
5
|
+
One variable for every application: `CAUTHY_KEY`.
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- **`CAUTHY_KEY`** (`key/cauthy-key.md` of the spec): Cauthy's address, the application's client and a 32-byte secret in one value, made by Cauthy's dashboard in the browser. `createCauthy()` reads it and nothing else: the session-cookie keys and an Ed25519 key are derived from it, the application authenticates with `private_key_jwt` (`EdDSA`) on every token and revoke call, never with a client secret, and asks Cauthy who it is (`GET /v1/connect/self`: workspace, system, addresses), revalidated every 5 minutes. The `key` option takes it in code.
|
|
10
|
+
- **Startup**: a damaged key throws `CauthyKeyError` at once with its reason (`key_format`, `key_version`, `key_checksum`, `key_issuer`, `key_client`, `key_secret`, `key_contract_issuer`, `key_previous_mismatch`), never the value. Cauthy unreachable: the server starts and `/api/auth/*` answers `503 unavailable` until Cauthy answers. Cauthy refusing the key: `503 misconfigured`, logged once with the `kid`. `auth.ready()` awaits the identity.
|
|
11
|
+
- **The redirect URI** comes from the request's origin when it is one of the application's addresses in Cauthy, else the only one; otherwise `400 unknown_origin`.
|
|
12
|
+
- **A contract on top of the key**: `createCauthy({ contract: { graph, system } })` with `CAUTHY_KEY` needs no key store and no table. The key proves the link's service client; the JWKS route publishes the key's Ed25519 public half (and the previous key's during a rotation). The key must name the graph's Cauthy.
|
|
13
|
+
- **`CAUTHY_KEY_PREVIOUS`** (`keyPrevious`) for rotations: its sessions are read, never written. `CAUTHY_SECRET` and `PACT_ROOT_KEY` beside the key are read-only too while an application moves (one warning each); with `PACT_ROOT_KEY`, a contract and `keys`, the old RS256 keys stay published beside the new one.
|
|
14
|
+
- **`createVerifierFromEnv()`**: a token verifier from `CAUTHY_KEY` alone (issuer, audience and workspace from Cauthy).
|
|
15
|
+
- `verifyWebhook` takes the issuer from `CAUTHY_KEY` when it is set.
|
|
16
|
+
- `parseKey`, `composeKey`, `KEY_REPLACES`, `CauthyKeyError`, and the types `CauthyKey`, `CauthyKeyReason`, `Identity`.
|
|
17
|
+
- **`@cauthyhq/node/testing`**: `FakeCauthy.issueKey(issuer?, { clientId? })`, `revokeKey(kid)`, `registeredKids()`, `appUrls`, `system`, `tenantId`, `contract`, `oauthRequests`. The fake checks Ed25519 assertions (signature, `kid`, `iss`/`sub`/`aud`, lifetime, replay) and answers `GET /v1/connect/self`, with `ETag`.
|
|
18
|
+
|
|
19
|
+
### Refused beside `CAUTHY_KEY`
|
|
20
|
+
|
|
21
|
+
`CAUTHY_ISSUER`, `CAUTHY_CLIENT_ID`, `CAUTHY_CLIENT_SECRET`, `CAUTHY_SYSTEM`, `CAUTHY_TENANT`, `CAUTHY_SYSTEM_KEY`, `CAUTHY_SYSTEM_KEY_ID`, `CAUTHY_BASE_URL`, `CAUTHY_AUDIENCE`, `CAUTHY_TENANT_ID`, and the options `issuer`, `clientId`, `clientSecret`, `secret`, `system`, `tenant`, `audience`, `tenantId`, `systemKey`, `rootKey` (and `keys`, except beside `PACT_ROOT_KEY` with a contract while moving).
|
|
22
|
+
|
|
23
|
+
### Deprecated (removed in 2.0)
|
|
24
|
+
|
|
25
|
+
One `DeprecationWarning` (code `CAUTHY_DEPRECATED`) per process each: configuring with the `CAUTHY_*` variables or their options; `PACT_ROOT_KEY[_PREVIOUS]` and the `keys` store; a verifier reading `CAUTHY_ISSUER`, `CAUTHY_AUDIENCE` or `CAUTHY_TENANT_ID`. They keep working through 1.x.
|
|
26
|
+
|
|
27
|
+
### Unchanged
|
|
28
|
+
|
|
29
|
+
Applications on the 1.1 variables or on `PACT_ROOT_KEY` work as before, apart from the warning. The MCP variables (`CAUTHY_MCP_*`) are not part of this change.
|
|
30
|
+
|
|
31
|
+
## 1.1.0 — security release
|
|
32
|
+
|
|
33
|
+
Cauthy now marks the tokens a machine holds, and names the client a person's token was issued through. This release makes `verifyToken` use those marks. Refusing a machine's token where a person is expected is a fix, not a break, so it ships as a minor version: upgrade.
|
|
34
|
+
|
|
35
|
+
### Security
|
|
36
|
+
|
|
37
|
+
- **A client's own token no longer passes as a person's.** A `client_credentials` token carries `token_use: "client"` and the client's public `client_id`. `verifyToken`, `createTokenVerifier`, `auth.verifyToken` and `auth.tokenVerifier` now refuse it with the reason `client_token` (rule R13 of the spec's `verification/rules.md`), by the claim's presence, whatever its value. In 1.0 such a token was accepted as a person whose `userId` was the client's id.
|
|
38
|
+
- **By contract, a person's token issued through another client is refused** with `wrong_client` (rule R15): `auth.verifyToken` and `auth.tokenVerifier` check the token's `azp` against the link's sign-in client. A token with no `azp` passes. A call that names another `clientId` in contract mode is a `CauthyConfigError`.
|
|
39
|
+
- `token_use` and `azp`, when present, must be strings (`invalid_claim` otherwise, rule R8).
|
|
40
|
+
|
|
41
|
+
### Backends that serve machines
|
|
42
|
+
|
|
43
|
+
If an endpoint is called by machines with a `client_credentials` token, pass `allowClientTokens: true` to the verifier that guards it:
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
const verifyMachine = auth.tokenVerifier({ allowClientTokens: true })
|
|
47
|
+
const who = await verifyMachine(request)
|
|
48
|
+
who.clientId // the client's public id; who.userId is its internal id
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Without it those calls get `client_token` (answer 401) after the upgrade.
|
|
52
|
+
|
|
53
|
+
### Added
|
|
54
|
+
|
|
55
|
+
- `TokenIdentity.authorizedParty`: the token's `azp`, the client a person's token was issued through; absent when none was named.
|
|
56
|
+
- `TokenIdentity.clientId`: the token's `client_id` (a client's own token, with `allowClientTokens`; an AI agent's).
|
|
57
|
+
- `VerifyTokenOptions.allowClientTokens` (default `false`) and `VerifyTokenOptions.clientId` (default none; by contract, the link's sign-in client).
|
|
58
|
+
- `TokenRefusal` gains `client_token` and `wrong_client`.
|
|
59
|
+
|
|
60
|
+
### Notes
|
|
61
|
+
|
|
62
|
+
- Cauthy now answers its JWKS with `max-age=300` and publishes a key at least that long before it signs with it. Nothing changes here: the keys are kept for the answer's `max-age` and fetched again on an unknown `kid`.
|
|
63
|
+
- A session that began through a client renews only through it. The SDK already renews with the `clientId` it signed in with, and sends that `clientId` on its own screens' calls: keep one `clientId` per deployment.
|
|
64
|
+
|
|
65
|
+
### Development
|
|
66
|
+
|
|
67
|
+
- vitest 4.1.12, fastify 5.12.8 (tests), and postcss 8.5.32 and esbuild 0.28.2 by override: every open advisory was in development dependencies only. `npm audit` reports none.
|
|
68
|
+
|
|
69
|
+
## 1.0.0
|
|
70
|
+
|
|
71
|
+
First release: the server half of `cauthy-auth` 0.42 (see the README, "Moving from cauthy-auth").
|
package/README.md
CHANGED
|
@@ -12,25 +12,20 @@ Node 20 or later. ESM and CommonJS. One dependency: `jose`.
|
|
|
12
12
|
|
|
13
13
|
## The five-minute path
|
|
14
14
|
|
|
15
|
-
**1.
|
|
15
|
+
**1. Connect the application in Cauthy's dashboard** (**Integrate → Applications → Connect an application**), with its address, e.g. `http://localhost:3000`. The dashboard makes the application's key in your browser and shows it once, as one line.
|
|
16
16
|
|
|
17
|
-
**2.
|
|
17
|
+
**2. Put that line in `.env`** (keep it out of git):
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
| `CAUTHY_CLIENT_ID` | The client id the dashboard showed in step 1 |
|
|
23
|
-
| `CAUTHY_CLIENT_SECRET` | Only if you registered the application as a confidential client in the dashboard: the client secret it showed once. Public clients need none, and neither does contract mode |
|
|
24
|
-
| `CAUTHY_SECRET` | You make it: `openssl rand -base64 32`. It encrypts the session cookie; keep it out of git |
|
|
25
|
-
| `CAUTHY_TENANT` | Your workspace's slug in Cauthy, e.g. `acme`, for the sign-in screens your application draws itself |
|
|
26
|
-
| `CAUTHY_BASE_URL` | Your application's public address, e.g. `http://localhost:3000` |
|
|
19
|
+
CAUTHY_KEY=cauthy1.…
|
|
20
|
+
|
|
21
|
+
That is the whole environment: Cauthy's address, the application's client and its secret are in the key; the workspace, the system and the application's addresses are asked of Cauthy when it starts. The [five-minute guide](https://cauthy.docs.vennet.dev/en/guide/get-started/) walks through it.
|
|
27
22
|
|
|
28
23
|
**3. Create it and mount it.**
|
|
29
24
|
|
|
30
25
|
```ts
|
|
31
26
|
// auth.ts
|
|
32
27
|
import { createCauthy } from '@cauthyhq/node'
|
|
33
|
-
export const auth = createCauthy() // reads
|
|
28
|
+
export const auth = createCauthy() // reads CAUTHY_KEY
|
|
34
29
|
```
|
|
35
30
|
|
|
36
31
|
```ts
|
|
@@ -80,6 +75,45 @@ await auth.organizations(session) // the person
|
|
|
80
75
|
|
|
81
76
|
See [`examples/acme-crm`](examples/acme-crm) for a whole application.
|
|
82
77
|
|
|
78
|
+
## CAUTHY_KEY
|
|
79
|
+
|
|
80
|
+
One value: Cauthy's address, the application's client and a 32-byte secret,
|
|
81
|
+
with a checksum (`cauthy1.<issuer>.<client>.<secret>.<check>`, specified in
|
|
82
|
+
the spec's [`key/cauthy-key.md`](https://github.com/vennet-developers/cauthy-sdk-spec/blob/main/key/cauthy-key.md)).
|
|
83
|
+
The SDK derives the session-cookie keys and an Ed25519 key from it, proves
|
|
84
|
+
itself to Cauthy with that key (`private_key_jwt`, a fresh assertion on every
|
|
85
|
+
token and revoke call; no client secret is ever sent), and asks Cauthy who it
|
|
86
|
+
is (`GET /v1/connect/self`). Cauthy keeps only the public half.
|
|
87
|
+
|
|
88
|
+
| When | What happens |
|
|
89
|
+
| --- | --- |
|
|
90
|
+
| `createCauthy()` | The key is parsed at once: a damaged paste throws `CauthyKeyError` naming the reason (`key_format`, `key_checksum`, …), never the key. Then Cauthy is asked who the application is, in the background |
|
|
91
|
+
| Cauthy not reachable yet | The server starts; `/api/auth/*` answers `503 unavailable` until the answer comes (retried from 1 to 30 seconds) |
|
|
92
|
+
| Cauthy refuses the key (revoked, never registered) | Logged once with the key's `kid`; `/api/auth/*` answers `503 misconfigured` |
|
|
93
|
+
| Running | The answer is kept and asked again every 5 minutes; while Cauthy is down the last one stands |
|
|
94
|
+
| `await auth.ready()` | The identity, waited for: call it at startup to fail early |
|
|
95
|
+
|
|
96
|
+
The redirect URI is built from the request's origin when it is one of the
|
|
97
|
+
application's addresses in Cauthy, from the only one when there is just one,
|
|
98
|
+
and the request is refused with `400 unknown_origin` otherwise. `baseURL`
|
|
99
|
+
still overrides it. Beside `CAUTHY_KEY` the variables it replaces
|
|
100
|
+
(`CAUTHY_ISSUER`, `CAUTHY_CLIENT_ID`, `CAUTHY_CLIENT_SECRET`, `CAUTHY_SYSTEM`,
|
|
101
|
+
`CAUTHY_TENANT`, `CAUTHY_SYSTEM_KEY`, `CAUTHY_SYSTEM_KEY_ID`, `CAUTHY_BASE_URL`,
|
|
102
|
+
`CAUTHY_AUDIENCE`, `CAUTHY_TENANT_ID`) and the options they stand for are
|
|
103
|
+
refused at startup, naming them.
|
|
104
|
+
|
|
105
|
+
**Lost or leaked:** make a new key on the application's card and revoke the
|
|
106
|
+
old one. **Rotating:** move the current value to `CAUTHY_KEY_PREVIOUS`, put
|
|
107
|
+
the new one in `CAUTHY_KEY`, deploy, and remove `CAUTHY_KEY_PREVIOUS` after
|
|
108
|
+
the window: sessions made with the previous key are still read, and nothing
|
|
109
|
+
new is written with it.
|
|
110
|
+
|
|
111
|
+
**Moving from the variables of 1.1:** on the application's card, **Move to
|
|
112
|
+
CAUTHY_KEY**. Deploy with `CAUTHY_KEY` and keep `CAUTHY_SECRET` for the window
|
|
113
|
+
(old sessions stay readable; one warning says to remove it), remove the other
|
|
114
|
+
variables, then **Remove the secret**. The variables of 1.1 and `PACT_ROOT_KEY`
|
|
115
|
+
still work in 1.x with one `DeprecationWarning` per process and leave in 2.0.
|
|
116
|
+
|
|
83
117
|
## Verifying a token
|
|
84
118
|
|
|
85
119
|
For an API that receives Cauthy access tokens from somewhere other than the browser's cookie:
|
|
@@ -88,14 +122,22 @@ For an API that receives Cauthy access tokens from somewhere other than the brow
|
|
|
88
122
|
import { auth } from './auth'
|
|
89
123
|
|
|
90
124
|
// Where each value comes from:
|
|
91
|
-
// issuer the instance's own (
|
|
92
|
-
// tenantId by contract, the link's tenant_id; otherwise
|
|
93
|
-
// audience
|
|
125
|
+
// issuer the instance's own (CAUTHY_KEY, or the contract; deprecated: CAUTHY_ISSUER)
|
|
126
|
+
// tenantId by contract, the link's tenant_id; on CAUTHY_KEY, Cauthy's answer; otherwise `tenantId` or CAUTHY_TENANT_ID (deprecated)
|
|
127
|
+
// audience on CAUTHY_KEY, Cauthy's answer; otherwise `audience` or CAUTHY_AUDIENCE (deprecated): your Cauthy's JWT_AUDIENCE
|
|
128
|
+
// clientId by contract, the link's sign-in client: a person's token issued through another is refused (wrong_client)
|
|
94
129
|
const verify = auth.tokenVerifier() // throws CauthyConfigError now if one is missing
|
|
95
130
|
const who = await verify(request) // or: await auth.verifyToken(request)
|
|
96
131
|
```
|
|
97
132
|
|
|
98
|
-
|
|
133
|
+
On `CAUTHY_KEY`, the issuer, the audience and the workspace are Cauthy's answer: `auth.tokenVerifier()` waits for it. With no instance:
|
|
134
|
+
|
|
135
|
+
```ts
|
|
136
|
+
import { createVerifierFromEnv } from '@cauthyhq/node'
|
|
137
|
+
const verify = await createVerifierFromEnv() // reads CAUTHY_KEY; asks Cauthy once
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Standalone, with no instance and no key, everything is explicit:
|
|
99
141
|
|
|
100
142
|
```ts
|
|
101
143
|
import { createTokenVerifier } from '@cauthyhq/node'
|
|
@@ -106,6 +148,8 @@ const verify = createTokenVerifier({ issuer: 'https://id.example.com', audience:
|
|
|
106
148
|
|
|
107
149
|
- **The audience and the workspace are required.** Without them a token issued for another application or workspace would be accepted.
|
|
108
150
|
- A system's own token (`sys` claim, whatever its value) and a guest's token (`anon: true`) are refused where a person is expected. Pass `allowSystem` or `allowAnonymous` for an endpoint that takes them.
|
|
151
|
+
- A client's own token (a `client_credentials` grant: `token_use: "client"`, whatever the value) is refused with `client_token` where a person is expected. A backend that serves machines too passes `allowClientTokens: true`; the identity then carries `clientId`, the client's public id (its `userId` is the client's internal id).
|
|
152
|
+
- `authorizedParty` is the token's `azp`: the client a person's token was issued through, absent when none was named. With `clientId` (by contract, always the link's sign-in client), a token whose `azp` names another client is refused with `wrong_client`; a token with no `azp` passes.
|
|
109
153
|
- Clock tolerance is 30 seconds (`leeway`, 0 to 60). A token over 8192 bytes, with a repeated JSON name, a fractional date or a wrongly typed claim is refused.
|
|
110
154
|
- Keys are fetched from `<issuer>/.well-known/jwks.json` with no redirect, within 5 seconds, at most 64 KiB, and kept for the answer's `max-age`.
|
|
111
155
|
|
|
@@ -117,8 +161,10 @@ const verify = createTokenVerifier({ issuer: 'https://id.example.com', audience:
|
|
|
117
161
|
| --- | --- |
|
|
118
162
|
| `cauthy-auth` | `@cauthyhq/node` |
|
|
119
163
|
| `cauthy-auth/express`, `/fastify`, `/hono`, `/next`, `/mcp`, `/keys`, `/theme` | `@cauthyhq/node/express`, … (same names) |
|
|
120
|
-
| `cauthy-auth/react`, `/
|
|
121
|
-
| `
|
|
164
|
+
| `cauthy-auth/react`, `/styles.css` | `@cauthyhq/react`, `@cauthyhq/react/styles.css` |
|
|
165
|
+
| `cauthy-auth/client` | `@cauthyhq/js` |
|
|
166
|
+
| `cauthy-auth/vue`, `/svelte` | No 1.0 wrapper yet: keep `cauthy-auth` 0.43 in the browser (security fixes until 2027-02-06) |
|
|
167
|
+
| `npx cauthy-auth …` | The `cauthy` CLI: `npx @cauthyhq/cli …` |
|
|
122
168
|
|
|
123
169
|
Everything that behaves differently from 0.42:
|
|
124
170
|
|
|
@@ -138,19 +184,20 @@ Everything that behaves differently from 0.42:
|
|
|
138
184
|
|
|
139
185
|
## Contract mode
|
|
140
186
|
|
|
141
|
-
|
|
187
|
+
A contract is a layer on top of an application that runs on `CAUTHY_KEY`: the environment stays that one line, and the vendored graph adds the link (system proof, drift, the link's policies). No key store and no table:
|
|
142
188
|
|
|
143
189
|
```ts
|
|
144
190
|
import { createCauthy } from '@cauthyhq/node'
|
|
145
|
-
import { postgresKeyStore } from '@cauthyhq/node/keys'
|
|
146
191
|
import graph from './contracts/graph.json'
|
|
147
192
|
|
|
148
|
-
export const auth = createCauthy({ contract: { graph, system: 'acme-crm' }
|
|
193
|
+
export const auth = createCauthy({ contract: { graph, system: 'acme-crm' } }) // and CAUTHY_KEY in the environment
|
|
149
194
|
```
|
|
150
195
|
|
|
151
|
-
|
|
196
|
+
The key proves the link's service client (`pact.<link>.service`); people sign in through its public client (`pact.<link>`). The key must name the graph's Cauthy (`key_contract_issuer` otherwise). The application publishes the key's public half at the contract's `jwks_url` path (`/.well-known/pact-jwks.json` by default), and the previous key's too during a rotation. The Express, Hono and Fastify adapters route that path to the handler as they do `/api/auth`, so those need no route of their own for it. **Next.js and TanStack Start still need a route file** for it that calls `auth.handler(request)`.
|
|
152
197
|
|
|
153
|
-
|
|
198
|
+
The 1.1 way (`PACT_ROOT_KEY` and `keys: postgresKeyStore(query)`) keeps working through 1.x with a deprecation warning. Moving: generate `CAUTHY_KEY` on the application's card, deploy it with `PACT_ROOT_KEY` and the `keys` option still beside it for the window (old sessions stay readable, its RS256 keys stay published beside the new Ed25519 key), then remove `PACT_ROOT_KEY`, the option and the table.
|
|
199
|
+
|
|
200
|
+
It refuses to start when any variable `CAUTHY_KEY` replaces is also set, when the link names its workspace by slug and the graph has no `tenant_id` for it yet, when a workspace named by id is pinned to a different `tenant_id`, when `system_proof` is not `off`, `auto` or `required`, or when the link asks for a system proof without a `service` block. When the link sets `require_verified_email`, a person whose address is not confirmed gets no session. See [`contract/pact.md`](https://github.com/vennet-developers/cauthy-sdk-spec/blob/main/contract/pact.md).
|
|
154
201
|
|
|
155
202
|
## Options added in 1.0
|
|
156
203
|
|
|
@@ -164,13 +211,23 @@ It refuses to start when any `CAUTHY_*` variable of the standard mode is also se
|
|
|
164
211
|
|
|
165
212
|
## Testing your application
|
|
166
213
|
|
|
167
|
-
`@cauthyhq/node/testing` is a Cauthy that lives in memory (`FakeCauthy`) and a browser that keeps cookies (`Browser`), for the tests of your own application. **Test-only**: it signs in whoever it was told about and checks
|
|
214
|
+
`@cauthyhq/node/testing` is a Cauthy that lives in memory (`FakeCauthy`) and a browser that keeps cookies (`Browser`), for the tests of your own application. **Test-only**: it signs in whoever it was told about and checks little a real Cauthy does. Do not import it from production code.
|
|
215
|
+
|
|
216
|
+
```ts
|
|
217
|
+
const fake = new FakeCauthy()
|
|
218
|
+
fake.appUrls = ['http://localhost:3000']
|
|
219
|
+
const auth = createCauthy({ key: await fake.issueKey(), fetch: fake.fetch })
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
`issueKey(issuer?)` makes a `CAUTHY_KEY` for `fake.clientId` and registers its public half, as the dashboard does; from then on that client must prove itself with the key's assertion on every token and revoke call. `revokeKey(kid)` revokes it. `serveFakeCauthy(fake, port)` serves it over HTTP; issue the key with that address (`http://127.0.0.1:<port>`) for a process outside yours.
|
|
168
223
|
|
|
169
224
|
## Conformance
|
|
170
225
|
|
|
171
|
-
|
|
226
|
+
The auth-bff conformance suite runs at level `strict` against `examples/acme-crm` on an in-memory Cauthy, the application on `CAUTHY_KEY` alone (with the runner's `key.*` checks); the spec's token vectors run against `verifyToken`, and its `CAUTHY_KEY` vectors against the parser and the derivation:
|
|
172
227
|
|
|
173
228
|
SPEC_DIR=../cauthy-sdk-spec LEVEL=strict npm run conformance
|
|
229
|
+
SPEC_DIR=../cauthy-sdk-spec LEVEL=switches npm run conformance # also the dashboard switches, on the in-memory Cauthy
|
|
230
|
+
SPEC_DIR=../cauthy-sdk-spec MODE=variables npm run conformance # the 1.1 way, for a runner without --key-env
|
|
174
231
|
SPEC_DIR=../cauthy-sdk-spec npm run vectors
|
|
175
232
|
|
|
176
233
|
## Security
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { K as KeyStore, P as PactKeys } from './keys-D5k0omTb.js';
|
|
2
2
|
import { JWTVerifyGetKey, JWK } from 'jose';
|
|
3
3
|
import { CauthyTheme } from './theme.js';
|
|
4
|
+
import { I as Identity } from './identity-BTJ8NB_w.js';
|
|
4
5
|
|
|
5
6
|
/** What createCauthy is given to run by contract. */
|
|
6
7
|
interface ContractOptions {
|
|
@@ -110,7 +111,7 @@ declare class CauthyWebhookError extends Error {
|
|
|
110
111
|
constructor(reason: string);
|
|
111
112
|
}
|
|
112
113
|
interface VerifyWebhookOptions {
|
|
113
|
-
/** Cauthy's address. Default: `CAUTHY_ISSUER`. */
|
|
114
|
+
/** Cauthy's address. Default: the one `CAUTHY_KEY` names, else `CAUTHY_ISSUER`. */
|
|
114
115
|
issuer?: string;
|
|
115
116
|
/**
|
|
116
117
|
* This endpoint's own public address, exactly as it is registered in Cauthy.
|
|
@@ -150,6 +151,17 @@ declare function verifyWebhook(request: Request, options?: VerifyWebhookOptions)
|
|
|
150
151
|
|
|
151
152
|
/** How an application is set up to sign its people in with Cauthy. */
|
|
152
153
|
interface CauthyOptions {
|
|
154
|
+
/**
|
|
155
|
+
* The application's CAUTHY_KEY, made in Cauthy's dashboard: Cauthy's
|
|
156
|
+
* address, the application's client and its secret, in one value. Default:
|
|
157
|
+
* `CAUTHY_KEY`. With it nothing else is read: the workspace, the system and
|
|
158
|
+
* the application's addresses come from Cauthy (`GET /v1/connect/self`),
|
|
159
|
+
* and passing `issuer`, `clientId`, `clientSecret`, `secret`, `system`,
|
|
160
|
+
* `tenant`, `audience`, `tenantId`, `systemKey` or `rootKey` is refused.
|
|
161
|
+
*/
|
|
162
|
+
key?: string;
|
|
163
|
+
/** The key being replaced, during a rotation: read, never written with. Default: `CAUTHY_KEY_PREVIOUS`. */
|
|
164
|
+
keyPrevious?: string;
|
|
153
165
|
/** Cauthy's public address, e.g. `https://id.example.com`. Default: `CAUTHY_ISSUER`. */
|
|
154
166
|
issuer?: string;
|
|
155
167
|
/** The application's OAuth client id. Default: `CAUTHY_CLIENT_ID`. */
|
|
@@ -398,6 +410,13 @@ type SessionStatus = 'authenticated' | 'unauthenticated' | 'expired';
|
|
|
398
410
|
declare class CauthyConfigError extends Error {
|
|
399
411
|
constructor(message: string);
|
|
400
412
|
}
|
|
413
|
+
/** Why a CAUTHY_KEY was refused (key/cauthy-key.md §3, §8, §9). */
|
|
414
|
+
type CauthyKeyReason = 'key_format' | 'key_version' | 'key_checksum' | 'key_issuer' | 'key_client' | 'key_secret' | 'key_contract_issuer' | 'key_previous_mismatch';
|
|
415
|
+
/** A refused CAUTHY_KEY. The message names the reason, never the key. */
|
|
416
|
+
declare class CauthyKeyError extends CauthyConfigError {
|
|
417
|
+
readonly reason: CauthyKeyReason;
|
|
418
|
+
constructor(reason: CauthyKeyReason, message: string);
|
|
419
|
+
}
|
|
401
420
|
|
|
402
421
|
/** The part of an organization that says what its member may do. */
|
|
403
422
|
interface Permitted {
|
|
@@ -637,6 +656,18 @@ declare function pushCatalog(o: Omit<PushPolicyOptions, 'roles' | 'catalog'> & {
|
|
|
637
656
|
resources: CatalogResource[];
|
|
638
657
|
}): Promise<CatalogResource[]>;
|
|
639
658
|
|
|
659
|
+
type PublicJwk = {
|
|
660
|
+
kty: 'OKP';
|
|
661
|
+
crv: 'Ed25519';
|
|
662
|
+
x: string;
|
|
663
|
+
};
|
|
664
|
+
interface Signer {
|
|
665
|
+
kid: string;
|
|
666
|
+
publicJwk: PublicJwk;
|
|
667
|
+
/** §6's assertion. iat in seconds; jti a fresh UUID v4. */
|
|
668
|
+
assertion(clientId: string, tokenEndpoint: string, jti?: string, iat?: number): Promise<string>;
|
|
669
|
+
}
|
|
670
|
+
|
|
640
671
|
/** The key an application signs its assertions with. */
|
|
641
672
|
interface SystemKey {
|
|
642
673
|
/** The private key: PKCS#8 PEM, or a JWK (as an object or its JSON). RSA, for RS256. */
|
|
@@ -679,6 +710,17 @@ interface SystemOptions {
|
|
|
679
710
|
keys?: PactKeys;
|
|
680
711
|
/** The client the keys prove: the system's own, beside the sign-in client. */
|
|
681
712
|
keysClientId?: string;
|
|
713
|
+
/**
|
|
714
|
+
* CAUTHY_KEY's Ed25519 key (key/cauthy-key.md §6) and the client it proves:
|
|
715
|
+
* every token is asked with an EdDSA assertion. Takes the place of `key`,
|
|
716
|
+
* `keys` and the secret.
|
|
717
|
+
*/
|
|
718
|
+
signer?: {
|
|
719
|
+
clientId: string;
|
|
720
|
+
signer: Promise<Signer>;
|
|
721
|
+
};
|
|
722
|
+
/** The system `check` asks about when it is known only later (CAUTHY_KEY: from Cauthy's answer). */
|
|
723
|
+
currentSystem?: () => string;
|
|
682
724
|
fetch?: typeof fetch;
|
|
683
725
|
/** How long a call to Cauthy may take before it fails with `503 unavailable`, in milliseconds. Default: 2000. */
|
|
684
726
|
timeoutMs?: number;
|
|
@@ -832,13 +874,20 @@ interface TokenIdentity {
|
|
|
832
874
|
system?: string;
|
|
833
875
|
/** Set when the token is a guest's (only with `allowAnonymous`). */
|
|
834
876
|
anonymous?: true;
|
|
877
|
+
/** The client a person's token was issued through (`azp`); absent when none was named. */
|
|
878
|
+
authorizedParty?: string;
|
|
879
|
+
/**
|
|
880
|
+
* The token's `client_id`: on a client's own token (only with
|
|
881
|
+
* `allowClientTokens`), the client's public id; on an AI agent's, the agent's.
|
|
882
|
+
*/
|
|
883
|
+
clientId?: string;
|
|
835
884
|
/** UTC, ISO 8601. */
|
|
836
885
|
expiresAt: string;
|
|
837
886
|
/** The token as it arrived, to pass on. */
|
|
838
887
|
token: string;
|
|
839
888
|
}
|
|
840
889
|
/** Why a token was refused: the closed list of verification/rules.md, and `no_token` when none was given. */
|
|
841
|
-
type TokenRefusal = 'no_token' | 'too_large' | 'malformed' | 'alg_not_allowed' | 'unsupported_header' | 'missing_kid' | 'unknown_kid' | 'weak_key' | 'bad_signature' | 'missing_claim' | 'invalid_claim' | 'wrong_issuer' | 'wrong_audience' | 'expired' | 'not_yet_valid' | 'issued_in_future' | 'wrong_tenant' | 'system_token' | 'anonymous_token';
|
|
890
|
+
type TokenRefusal = 'no_token' | 'too_large' | 'malformed' | 'alg_not_allowed' | 'unsupported_header' | 'missing_kid' | 'unknown_kid' | 'weak_key' | 'bad_signature' | 'missing_claim' | 'invalid_claim' | 'wrong_issuer' | 'wrong_audience' | 'expired' | 'not_yet_valid' | 'issued_in_future' | 'wrong_tenant' | 'system_token' | 'client_token' | 'anonymous_token' | 'wrong_client';
|
|
842
891
|
/**
|
|
843
892
|
* Cauthy's keys could not be fetched (or are not a key set): the token may be
|
|
844
893
|
* good, and the application cannot tell. Answer 503, not 401. It is not a
|
|
@@ -880,6 +929,20 @@ interface VerifyTokenOptions {
|
|
|
880
929
|
allowSystem?: boolean;
|
|
881
930
|
/** Accept a guest's token (`anon: true`). Default: false (rule R14). */
|
|
882
931
|
allowAnonymous?: boolean;
|
|
932
|
+
/**
|
|
933
|
+
* Accept a client's own token (a `token_use` claim, from a
|
|
934
|
+
* `client_credentials` grant) too: for a backend that serves machines as
|
|
935
|
+
* well as people. Default: false, so a machine never passes as a person
|
|
936
|
+
* (rule R13). The identity then carries `clientId`.
|
|
937
|
+
*/
|
|
938
|
+
allowClientTokens?: boolean;
|
|
939
|
+
/**
|
|
940
|
+
* The client this backend signs people in through. When set, a person's
|
|
941
|
+
* token issued through another client (an `azp` naming another) is refused
|
|
942
|
+
* with `wrong_client` (rule R15); a token with no `azp` passes. In contract
|
|
943
|
+
* mode it is the link's sign-in client. Default: none, and `azp` is not checked.
|
|
944
|
+
*/
|
|
945
|
+
clientId?: string;
|
|
883
946
|
}
|
|
884
947
|
/**
|
|
885
948
|
* Cauthy's published keys (K1 to K5 of verification/rules.md): fetched with a
|
|
@@ -904,6 +967,19 @@ declare function createTokenVerifier(options?: VerifyTokenOptions): (from: strin
|
|
|
904
967
|
* which checks them once, at startup).
|
|
905
968
|
*/
|
|
906
969
|
declare function verifyToken(from: string | Request | Headers, options?: VerifyTokenOptions): Promise<TokenIdentity>;
|
|
970
|
+
/**
|
|
971
|
+
* A verifier made from the environment. With `CAUTHY_KEY` the issuer, the
|
|
972
|
+
* audience and the workspace are Cauthy's answer to `GET /v1/connect/self`
|
|
973
|
+
* (asked with the key's assertion, once); nothing else is read, and any of
|
|
974
|
+
* `issuer`, `audience`, `tenantId` given beside it is refused. Without it,
|
|
975
|
+
* `CAUTHY_ISSUER`, `CAUTHY_AUDIENCE` and `CAUTHY_TENANT_ID`, deprecated.
|
|
976
|
+
*
|
|
977
|
+
* const verify = await createVerifierFromEnv()
|
|
978
|
+
* const who = await verify(request)
|
|
979
|
+
*/
|
|
980
|
+
declare function createVerifierFromEnv(options?: Omit<VerifyTokenOptions, 'issuers'> & {
|
|
981
|
+
key?: string;
|
|
982
|
+
}): Promise<(from: string | Request | Headers) => Promise<TokenIdentity>>;
|
|
907
983
|
|
|
908
984
|
/**
|
|
909
985
|
* Where the probes go: the running application's origin
|
|
@@ -922,6 +998,13 @@ interface Resolved {
|
|
|
922
998
|
interface Cauthy {
|
|
923
999
|
/** Serves the routes under `basePath`: login, callback, session, refresh, logout, account. */
|
|
924
1000
|
handler(request: Request): Promise<Response>;
|
|
1001
|
+
/**
|
|
1002
|
+
* Who the application is. On CAUTHY_KEY, Cauthy's answer to
|
|
1003
|
+
* `GET /v1/connect/self`, waited for: it rejects with `CauthyApiError`
|
|
1004
|
+
* `503 misconfigured` when Cauthy refuses the key. Otherwise what is
|
|
1005
|
+
* configured, at once (`key: null`). Await it at startup to fail early.
|
|
1006
|
+
*/
|
|
1007
|
+
ready(): Promise<Identity>;
|
|
925
1008
|
/**
|
|
926
1009
|
* Checks that this handler is what answers under `basePath` in the running
|
|
927
1010
|
* application, and throws `CauthyConfigError` naming the route when another
|
|
@@ -990,6 +1073,8 @@ interface Cauthy {
|
|
|
990
1073
|
* an API of this application: `verifyToken` with this instance's issuer, its
|
|
991
1074
|
* workspace (by contract, the link's `tenant_id`; otherwise `tenantId` or
|
|
992
1075
|
* `CAUTHY_TENANT_ID`) and its audience (`audience` or `CAUTHY_AUDIENCE`).
|
|
1076
|
+
* By contract it also refuses a person's token issued through another
|
|
1077
|
+
* client than the link's (`wrong_client`).
|
|
993
1078
|
*/
|
|
994
1079
|
verifyToken(from: string | Request | Headers, options?: Partial<VerifyTokenOptions>): Promise<TokenIdentity>;
|
|
995
1080
|
/** The same, built once: throws `CauthyConfigError` now if the audience or the workspace is missing. */
|
|
@@ -1032,4 +1117,4 @@ interface CauthyPact {
|
|
|
1032
1117
|
}
|
|
1033
1118
|
declare function createCauthy(given?: CauthyOptions): Cauthy;
|
|
1034
1119
|
|
|
1035
|
-
export {
|
|
1120
|
+
export { createCauthy as $, type AttributeType as A, type PolicyRole as B, type Cauthy as C, type PublicSession as D, type PushPolicyOptions as E, type Resolved as F, type ResolvedContract as G, type RoleOf as H, STANDARD_VARIABLES as I, type JsonValue as J, type SessionOrganization as K, type SessionStatus as L, type MountTarget as M, type NewMember as N, type Organization as O, type PactItem as P, type SessionUser as Q, type ReplayStore as R, type Session as S, type SystemKey as T, type SystemOptions as U, type SystemPolicy as V, type TokenIdentity as W, type TokenRefusal as X, type VerifyTokenOptions as Y, type VerifyWebhookOptions as Z, can as _, type CatalogResource as a, createSystem as a0, createTokenVerifier as a1, createVerifierFromEnv as a2, definePolicy as a3, failClosed as a4, memoryReplayStore as a5, policySource as a6, pullCatalog as a7, pullPolicy as a8, pushCatalog as a9, pushPolicy as aa, readContract as ab, remoteKeys as ac, verifyToken as ad, verifyWebhook as ae, CauthyApiError as b, CauthyConfigError as c, type CauthyEvent as d, CauthyKeyError as e, type CauthyKeyReason as f, type CauthyOptions as g, type CauthyPact as h, type CauthySystem as i, CauthyTokenError as j, CauthyUnavailableError as k, CauthyWebhookError as l, type CheckOf as m, type CheckQuestion as n, type CheckResult as o, type CheckRule as p, type ConditionalPermission as q, type ContractOptions as r, type OrganizationMember as s, type OrganizationRef as t, type PactStatus as u, type PermissionOf as v, type Permitted as w, type Policy as x, type PolicyDefinition as y, type PolicyPermission as z };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { K as KeyStore, P as PactKeys } from './keys-D5k0omTb.mjs';
|
|
2
2
|
import { JWTVerifyGetKey, JWK } from 'jose';
|
|
3
3
|
import { CauthyTheme } from './theme.mjs';
|
|
4
|
+
import { I as Identity } from './identity-BTJ8NB_w.mjs';
|
|
4
5
|
|
|
5
6
|
/** What createCauthy is given to run by contract. */
|
|
6
7
|
interface ContractOptions {
|
|
@@ -110,7 +111,7 @@ declare class CauthyWebhookError extends Error {
|
|
|
110
111
|
constructor(reason: string);
|
|
111
112
|
}
|
|
112
113
|
interface VerifyWebhookOptions {
|
|
113
|
-
/** Cauthy's address. Default: `CAUTHY_ISSUER`. */
|
|
114
|
+
/** Cauthy's address. Default: the one `CAUTHY_KEY` names, else `CAUTHY_ISSUER`. */
|
|
114
115
|
issuer?: string;
|
|
115
116
|
/**
|
|
116
117
|
* This endpoint's own public address, exactly as it is registered in Cauthy.
|
|
@@ -150,6 +151,17 @@ declare function verifyWebhook(request: Request, options?: VerifyWebhookOptions)
|
|
|
150
151
|
|
|
151
152
|
/** How an application is set up to sign its people in with Cauthy. */
|
|
152
153
|
interface CauthyOptions {
|
|
154
|
+
/**
|
|
155
|
+
* The application's CAUTHY_KEY, made in Cauthy's dashboard: Cauthy's
|
|
156
|
+
* address, the application's client and its secret, in one value. Default:
|
|
157
|
+
* `CAUTHY_KEY`. With it nothing else is read: the workspace, the system and
|
|
158
|
+
* the application's addresses come from Cauthy (`GET /v1/connect/self`),
|
|
159
|
+
* and passing `issuer`, `clientId`, `clientSecret`, `secret`, `system`,
|
|
160
|
+
* `tenant`, `audience`, `tenantId`, `systemKey` or `rootKey` is refused.
|
|
161
|
+
*/
|
|
162
|
+
key?: string;
|
|
163
|
+
/** The key being replaced, during a rotation: read, never written with. Default: `CAUTHY_KEY_PREVIOUS`. */
|
|
164
|
+
keyPrevious?: string;
|
|
153
165
|
/** Cauthy's public address, e.g. `https://id.example.com`. Default: `CAUTHY_ISSUER`. */
|
|
154
166
|
issuer?: string;
|
|
155
167
|
/** The application's OAuth client id. Default: `CAUTHY_CLIENT_ID`. */
|
|
@@ -398,6 +410,13 @@ type SessionStatus = 'authenticated' | 'unauthenticated' | 'expired';
|
|
|
398
410
|
declare class CauthyConfigError extends Error {
|
|
399
411
|
constructor(message: string);
|
|
400
412
|
}
|
|
413
|
+
/** Why a CAUTHY_KEY was refused (key/cauthy-key.md §3, §8, §9). */
|
|
414
|
+
type CauthyKeyReason = 'key_format' | 'key_version' | 'key_checksum' | 'key_issuer' | 'key_client' | 'key_secret' | 'key_contract_issuer' | 'key_previous_mismatch';
|
|
415
|
+
/** A refused CAUTHY_KEY. The message names the reason, never the key. */
|
|
416
|
+
declare class CauthyKeyError extends CauthyConfigError {
|
|
417
|
+
readonly reason: CauthyKeyReason;
|
|
418
|
+
constructor(reason: CauthyKeyReason, message: string);
|
|
419
|
+
}
|
|
401
420
|
|
|
402
421
|
/** The part of an organization that says what its member may do. */
|
|
403
422
|
interface Permitted {
|
|
@@ -637,6 +656,18 @@ declare function pushCatalog(o: Omit<PushPolicyOptions, 'roles' | 'catalog'> & {
|
|
|
637
656
|
resources: CatalogResource[];
|
|
638
657
|
}): Promise<CatalogResource[]>;
|
|
639
658
|
|
|
659
|
+
type PublicJwk = {
|
|
660
|
+
kty: 'OKP';
|
|
661
|
+
crv: 'Ed25519';
|
|
662
|
+
x: string;
|
|
663
|
+
};
|
|
664
|
+
interface Signer {
|
|
665
|
+
kid: string;
|
|
666
|
+
publicJwk: PublicJwk;
|
|
667
|
+
/** §6's assertion. iat in seconds; jti a fresh UUID v4. */
|
|
668
|
+
assertion(clientId: string, tokenEndpoint: string, jti?: string, iat?: number): Promise<string>;
|
|
669
|
+
}
|
|
670
|
+
|
|
640
671
|
/** The key an application signs its assertions with. */
|
|
641
672
|
interface SystemKey {
|
|
642
673
|
/** The private key: PKCS#8 PEM, or a JWK (as an object or its JSON). RSA, for RS256. */
|
|
@@ -679,6 +710,17 @@ interface SystemOptions {
|
|
|
679
710
|
keys?: PactKeys;
|
|
680
711
|
/** The client the keys prove: the system's own, beside the sign-in client. */
|
|
681
712
|
keysClientId?: string;
|
|
713
|
+
/**
|
|
714
|
+
* CAUTHY_KEY's Ed25519 key (key/cauthy-key.md §6) and the client it proves:
|
|
715
|
+
* every token is asked with an EdDSA assertion. Takes the place of `key`,
|
|
716
|
+
* `keys` and the secret.
|
|
717
|
+
*/
|
|
718
|
+
signer?: {
|
|
719
|
+
clientId: string;
|
|
720
|
+
signer: Promise<Signer>;
|
|
721
|
+
};
|
|
722
|
+
/** The system `check` asks about when it is known only later (CAUTHY_KEY: from Cauthy's answer). */
|
|
723
|
+
currentSystem?: () => string;
|
|
682
724
|
fetch?: typeof fetch;
|
|
683
725
|
/** How long a call to Cauthy may take before it fails with `503 unavailable`, in milliseconds. Default: 2000. */
|
|
684
726
|
timeoutMs?: number;
|
|
@@ -832,13 +874,20 @@ interface TokenIdentity {
|
|
|
832
874
|
system?: string;
|
|
833
875
|
/** Set when the token is a guest's (only with `allowAnonymous`). */
|
|
834
876
|
anonymous?: true;
|
|
877
|
+
/** The client a person's token was issued through (`azp`); absent when none was named. */
|
|
878
|
+
authorizedParty?: string;
|
|
879
|
+
/**
|
|
880
|
+
* The token's `client_id`: on a client's own token (only with
|
|
881
|
+
* `allowClientTokens`), the client's public id; on an AI agent's, the agent's.
|
|
882
|
+
*/
|
|
883
|
+
clientId?: string;
|
|
835
884
|
/** UTC, ISO 8601. */
|
|
836
885
|
expiresAt: string;
|
|
837
886
|
/** The token as it arrived, to pass on. */
|
|
838
887
|
token: string;
|
|
839
888
|
}
|
|
840
889
|
/** Why a token was refused: the closed list of verification/rules.md, and `no_token` when none was given. */
|
|
841
|
-
type TokenRefusal = 'no_token' | 'too_large' | 'malformed' | 'alg_not_allowed' | 'unsupported_header' | 'missing_kid' | 'unknown_kid' | 'weak_key' | 'bad_signature' | 'missing_claim' | 'invalid_claim' | 'wrong_issuer' | 'wrong_audience' | 'expired' | 'not_yet_valid' | 'issued_in_future' | 'wrong_tenant' | 'system_token' | 'anonymous_token';
|
|
890
|
+
type TokenRefusal = 'no_token' | 'too_large' | 'malformed' | 'alg_not_allowed' | 'unsupported_header' | 'missing_kid' | 'unknown_kid' | 'weak_key' | 'bad_signature' | 'missing_claim' | 'invalid_claim' | 'wrong_issuer' | 'wrong_audience' | 'expired' | 'not_yet_valid' | 'issued_in_future' | 'wrong_tenant' | 'system_token' | 'client_token' | 'anonymous_token' | 'wrong_client';
|
|
842
891
|
/**
|
|
843
892
|
* Cauthy's keys could not be fetched (or are not a key set): the token may be
|
|
844
893
|
* good, and the application cannot tell. Answer 503, not 401. It is not a
|
|
@@ -880,6 +929,20 @@ interface VerifyTokenOptions {
|
|
|
880
929
|
allowSystem?: boolean;
|
|
881
930
|
/** Accept a guest's token (`anon: true`). Default: false (rule R14). */
|
|
882
931
|
allowAnonymous?: boolean;
|
|
932
|
+
/**
|
|
933
|
+
* Accept a client's own token (a `token_use` claim, from a
|
|
934
|
+
* `client_credentials` grant) too: for a backend that serves machines as
|
|
935
|
+
* well as people. Default: false, so a machine never passes as a person
|
|
936
|
+
* (rule R13). The identity then carries `clientId`.
|
|
937
|
+
*/
|
|
938
|
+
allowClientTokens?: boolean;
|
|
939
|
+
/**
|
|
940
|
+
* The client this backend signs people in through. When set, a person's
|
|
941
|
+
* token issued through another client (an `azp` naming another) is refused
|
|
942
|
+
* with `wrong_client` (rule R15); a token with no `azp` passes. In contract
|
|
943
|
+
* mode it is the link's sign-in client. Default: none, and `azp` is not checked.
|
|
944
|
+
*/
|
|
945
|
+
clientId?: string;
|
|
883
946
|
}
|
|
884
947
|
/**
|
|
885
948
|
* Cauthy's published keys (K1 to K5 of verification/rules.md): fetched with a
|
|
@@ -904,6 +967,19 @@ declare function createTokenVerifier(options?: VerifyTokenOptions): (from: strin
|
|
|
904
967
|
* which checks them once, at startup).
|
|
905
968
|
*/
|
|
906
969
|
declare function verifyToken(from: string | Request | Headers, options?: VerifyTokenOptions): Promise<TokenIdentity>;
|
|
970
|
+
/**
|
|
971
|
+
* A verifier made from the environment. With `CAUTHY_KEY` the issuer, the
|
|
972
|
+
* audience and the workspace are Cauthy's answer to `GET /v1/connect/self`
|
|
973
|
+
* (asked with the key's assertion, once); nothing else is read, and any of
|
|
974
|
+
* `issuer`, `audience`, `tenantId` given beside it is refused. Without it,
|
|
975
|
+
* `CAUTHY_ISSUER`, `CAUTHY_AUDIENCE` and `CAUTHY_TENANT_ID`, deprecated.
|
|
976
|
+
*
|
|
977
|
+
* const verify = await createVerifierFromEnv()
|
|
978
|
+
* const who = await verify(request)
|
|
979
|
+
*/
|
|
980
|
+
declare function createVerifierFromEnv(options?: Omit<VerifyTokenOptions, 'issuers'> & {
|
|
981
|
+
key?: string;
|
|
982
|
+
}): Promise<(from: string | Request | Headers) => Promise<TokenIdentity>>;
|
|
907
983
|
|
|
908
984
|
/**
|
|
909
985
|
* Where the probes go: the running application's origin
|
|
@@ -922,6 +998,13 @@ interface Resolved {
|
|
|
922
998
|
interface Cauthy {
|
|
923
999
|
/** Serves the routes under `basePath`: login, callback, session, refresh, logout, account. */
|
|
924
1000
|
handler(request: Request): Promise<Response>;
|
|
1001
|
+
/**
|
|
1002
|
+
* Who the application is. On CAUTHY_KEY, Cauthy's answer to
|
|
1003
|
+
* `GET /v1/connect/self`, waited for: it rejects with `CauthyApiError`
|
|
1004
|
+
* `503 misconfigured` when Cauthy refuses the key. Otherwise what is
|
|
1005
|
+
* configured, at once (`key: null`). Await it at startup to fail early.
|
|
1006
|
+
*/
|
|
1007
|
+
ready(): Promise<Identity>;
|
|
925
1008
|
/**
|
|
926
1009
|
* Checks that this handler is what answers under `basePath` in the running
|
|
927
1010
|
* application, and throws `CauthyConfigError` naming the route when another
|
|
@@ -990,6 +1073,8 @@ interface Cauthy {
|
|
|
990
1073
|
* an API of this application: `verifyToken` with this instance's issuer, its
|
|
991
1074
|
* workspace (by contract, the link's `tenant_id`; otherwise `tenantId` or
|
|
992
1075
|
* `CAUTHY_TENANT_ID`) and its audience (`audience` or `CAUTHY_AUDIENCE`).
|
|
1076
|
+
* By contract it also refuses a person's token issued through another
|
|
1077
|
+
* client than the link's (`wrong_client`).
|
|
993
1078
|
*/
|
|
994
1079
|
verifyToken(from: string | Request | Headers, options?: Partial<VerifyTokenOptions>): Promise<TokenIdentity>;
|
|
995
1080
|
/** The same, built once: throws `CauthyConfigError` now if the audience or the workspace is missing. */
|
|
@@ -1032,4 +1117,4 @@ interface CauthyPact {
|
|
|
1032
1117
|
}
|
|
1033
1118
|
declare function createCauthy(given?: CauthyOptions): Cauthy;
|
|
1034
1119
|
|
|
1035
|
-
export {
|
|
1120
|
+
export { createCauthy as $, type AttributeType as A, type PolicyRole as B, type Cauthy as C, type PublicSession as D, type PushPolicyOptions as E, type Resolved as F, type ResolvedContract as G, type RoleOf as H, STANDARD_VARIABLES as I, type JsonValue as J, type SessionOrganization as K, type SessionStatus as L, type MountTarget as M, type NewMember as N, type Organization as O, type PactItem as P, type SessionUser as Q, type ReplayStore as R, type Session as S, type SystemKey as T, type SystemOptions as U, type SystemPolicy as V, type TokenIdentity as W, type TokenRefusal as X, type VerifyTokenOptions as Y, type VerifyWebhookOptions as Z, can as _, type CatalogResource as a, createSystem as a0, createTokenVerifier as a1, createVerifierFromEnv as a2, definePolicy as a3, failClosed as a4, memoryReplayStore as a5, policySource as a6, pullCatalog as a7, pullPolicy as a8, pushCatalog as a9, pushPolicy as aa, readContract as ab, remoteKeys as ac, verifyToken as ad, verifyWebhook as ae, CauthyApiError as b, CauthyConfigError as c, type CauthyEvent as d, CauthyKeyError as e, type CauthyKeyReason as f, type CauthyOptions as g, type CauthyPact as h, type CauthySystem as i, CauthyTokenError as j, CauthyUnavailableError as k, CauthyWebhookError as l, type CheckOf as m, type CheckQuestion as n, type CheckResult as o, type CheckRule as p, type ConditionalPermission as q, type ContractOptions as r, type OrganizationMember as s, type OrganizationRef as t, type PactStatus as u, type PermissionOf as v, type Permitted as w, type Policy as x, type PolicyDefinition as y, type PolicyPermission as z };
|
package/dist/express.d.mts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
-
import { S as Session, C as Cauthy } from './cauthy-
|
|
2
|
+
import { S as Session, C as Cauthy } from './cauthy-CCSSj3Lg.mjs';
|
|
3
3
|
import './keys-D5k0omTb.mjs';
|
|
4
4
|
import 'jose';
|
|
5
5
|
import './theme.mjs';
|
|
6
|
+
import './identity-BTJ8NB_w.mjs';
|
|
6
7
|
|
|
7
8
|
declare global {
|
|
8
9
|
namespace Express {
|