@keycardai/eve 0.1.0 → 0.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/README.md +48 -9
- package/dist/esm/connections.d.ts +21 -0
- package/dist/esm/connections.d.ts.map +1 -1
- package/dist/esm/connections.js +0 -3
- package/dist/esm/connections.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/interactive.d.ts +77 -4
- package/dist/esm/interactive.d.ts.map +1 -1
- package/dist/esm/interactive.js +124 -15
- package/dist/esm/interactive.js.map +1 -1
- package/dist/esm/requireAuth.d.ts +9 -6
- package/dist/esm/requireAuth.d.ts.map +1 -1
- package/dist/esm/requireAuth.js +1 -4
- package/dist/esm/requireAuth.js.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -16,12 +16,19 @@ Three adapters, each one plugging into an eve primitive instead of wrapping it:
|
|
|
16
16
|
pnpm add @keycardai/eve
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
`eve` is a peer dependency, pinned to `>=0.
|
|
20
|
-
built and verified against eve `0.
|
|
19
|
+
`eve` is a peer dependency, pinned to `>=0.54.3 <0.55.0`. This package was
|
|
20
|
+
built and verified against eve `0.54.3`. eve is in public beta and ships
|
|
21
21
|
releases most days, and its connection and auth surfaces are still moving, so
|
|
22
22
|
the range deliberately stops at the next minor rather than tracking `^`. Widen
|
|
23
23
|
it only after re-running this package's tests against the newer eve.
|
|
24
24
|
|
|
25
|
+
The narrowness is the point rather than an oversight, and so is keeping the
|
|
26
|
+
range current: a consumer who runs a newer eve and installs this anyway —
|
|
27
|
+
`--legacy-peer-deps` — silently loses the check, and the incompatibilities
|
|
28
|
+
surface at build time instead. Two of them are what the 0.47 → 0.54 bump had to
|
|
29
|
+
fix: an `auth` key list that `displayName` is not in, and a `requireAuth`
|
|
30
|
+
options type with no `reason` field.
|
|
31
|
+
|
|
25
32
|
eve itself declares `engines.node: ">=24"` and is ESM only. This package
|
|
26
33
|
imports eve for types only (`import type { ... } from "eve/connections"`), so
|
|
27
34
|
nothing here pulls eve into the runtime and the package builds and tests on
|
|
@@ -139,13 +146,39 @@ export default defineMcpClientConnection({
|
|
|
139
146
|
description: "Documents the user has authorized.",
|
|
140
147
|
auth: Keycard.interactive({
|
|
141
148
|
zoneUrl: process.env.KEYCARD_ZONE_URL!,
|
|
142
|
-
clientId: process.env.KEYCARD_CLIENT_ID!,
|
|
143
149
|
resource: "https://docs.example.com",
|
|
144
150
|
requestScopes: ["documents.read"],
|
|
151
|
+
connectionName: "Docs",
|
|
145
152
|
}),
|
|
146
153
|
});
|
|
147
154
|
```
|
|
148
155
|
|
|
156
|
+
**There is no `clientId`, and adding one usually breaks the flow.** eve mints a
|
|
157
|
+
fresh callback URL for every attempt — `/eve/v1/connections/:name/callback/
|
|
158
|
+
:attemptId/:token` — while [RFC 9700][rfc9700] requires the authorization server
|
|
159
|
+
to match `redirect_uri` against the client's registered list by exact string
|
|
160
|
+
comparison. A client registered ahead of time cannot name a URL that is
|
|
161
|
+
generated later, so the request is rejected with something like
|
|
162
|
+
`Unauthorized redirect URI`. Leaving `clientId` unset registers a client per
|
|
163
|
+
attempt instead (RFC 7591), whose single redirect URI is the callback that
|
|
164
|
+
attempt will actually return to. Each client is public and PKCE-bound, so
|
|
165
|
+
nothing secret enters eve's durable resume state; if the server issues a
|
|
166
|
+
confidential client anyway, the attempt is abandoned rather than journaling a
|
|
167
|
+
secret.
|
|
168
|
+
|
|
169
|
+
Set `clientId` only when that client's registered redirect URIs already cover
|
|
170
|
+
eve's callback. Note that a Keycard application `identifier` is not a client id:
|
|
171
|
+
zones identify clients by [Client ID Metadata Document][cimd] — an HTTPS URL
|
|
172
|
+
with a path, serving the client's metadata — so a value like
|
|
173
|
+
`urn:app:my-agent` fails with `Unsupported client identifier prefix: urn`.
|
|
174
|
+
|
|
175
|
+
Per-attempt clients accumulate in the zone. They hold no secret and their
|
|
176
|
+
callback is single-use, but a server returning `registration_client_uri` and
|
|
177
|
+
`registration_access_token` allows RFC 7592 deletion once a grant settles.
|
|
178
|
+
|
|
179
|
+
[rfc9700]: https://datatracker.ietf.org/doc/html/rfc9700
|
|
180
|
+
[cimd]: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-client-id-metadata-document-02
|
|
181
|
+
|
|
149
182
|
The definition implements the same three-method form as eve's
|
|
150
183
|
`defineInteractiveAuthorization`, over `@keycardai/oauth`'s v3 web-app flow:
|
|
151
184
|
|
|
@@ -153,11 +186,13 @@ The definition implements the same three-method form as eve's
|
|
|
153
186
|
principal. Otherwise it throws `ConnectionAuthorizationRequiredError`, so eve
|
|
154
187
|
emits `authorization.required`, runs `startAuthorization` in a durable step,
|
|
155
188
|
and parks the turn on a framework-owned callback.
|
|
156
|
-
- `startAuthorization`
|
|
157
|
-
|
|
158
|
-
|
|
189
|
+
- `startAuthorization` registers this attempt's client (unless `clientId` is
|
|
190
|
+
set), calls `beginAuthorization` for the connection's resource list against
|
|
191
|
+
eve's minted callback URL, and returns the challenge URL plus the `state`,
|
|
192
|
+
PKCE verifier and client id as JSON resume state.
|
|
159
193
|
- `completeAuthorization` calls `completeAuthorization` with eve's callback
|
|
160
|
-
params and the journaled resume state,
|
|
194
|
+
params and the journaled resume state, redeeming as the client that attempt's
|
|
195
|
+
authorization request ran as, and hands eve the token.
|
|
161
196
|
|
|
162
197
|
**Resume without authorization cannot yield a credential.** `getToken` is the
|
|
163
198
|
only path that returns a token, and it reads a store only
|
|
@@ -212,8 +247,12 @@ const auth = Keycard.onBehalfOf({
|
|
|
212
247
|
`fakeZoneClient()` records every exchange, impersonation, and client
|
|
213
248
|
credentials call, and can fail one resource or every request. `keycardAuth()`
|
|
214
249
|
takes a `verify` seam in place of the JWKS-backed verifier, and
|
|
215
|
-
`Keycard.interactive()` takes a `flow` seam in place of the
|
|
216
|
-
|
|
250
|
+
`Keycard.interactive()` takes a `flow` seam in place of the web-flow calls —
|
|
251
|
+
`begin`, `complete`, and the `register` used for per-attempt clients. A flow
|
|
252
|
+
without `register` is rejected at construction unless a `clientId` is also
|
|
253
|
+
given, so a test cannot accidentally exercise a combination that cannot work in
|
|
254
|
+
production. An injected `client` or `flow` supersedes `zoneUrl`, so a test needs
|
|
255
|
+
no zone.
|
|
217
256
|
|
|
218
257
|
## Not included: the Keycard gateway MCP proxy
|
|
219
258
|
|
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
import type { ConnectionPrincipal, NonInteractiveAuthorizationDefinition } from "eve/connections";
|
|
2
2
|
import { type KeycardConnectionOptions } from "./config.js";
|
|
3
|
+
/**
|
|
4
|
+
* NONE OF THESE DEFINITIONS CARRY A `displayName`, and adding one back breaks
|
|
5
|
+
* every connection that uses them.
|
|
6
|
+
*
|
|
7
|
+
* eve validates an authored connection's `auth` against a closed key list —
|
|
8
|
+
* `completeAuthorization`, `evict`, `getToken`, `principalType`,
|
|
9
|
+
* `startAuthorization`, `vercelConnect` — and `displayName` is not in it, so a
|
|
10
|
+
* definition carrying one fails the BUILD with
|
|
11
|
+
* `The "auth" field Unknown key "displayName"`. That is an inconsistency inside
|
|
12
|
+
* eve rather than a rule: its `normalizeAuthorizationSpec` accepts and forwards
|
|
13
|
+
* the field, and only the authored-module key check disagrees. Until the two
|
|
14
|
+
* agree, a package whose whole purpose is to be dropped into `auth:` has to
|
|
15
|
+
* keep off the key.
|
|
16
|
+
*
|
|
17
|
+
* Nothing is lost. The only consumer of a definition-level `displayName` is
|
|
18
|
+
* eve's `stampChallengeDisplayName`, which resolves
|
|
19
|
+
* `definition.displayName ?? challenge.displayName` — so a name supplied on the
|
|
20
|
+
* challenge still reaches the sign-in prompt (see {@link interactive}), and a
|
|
21
|
+
* non-interactive definition has no challenge to name in the first place. Tools
|
|
22
|
+
* name a provider through `ToolAuthOptions.displayName` at the call site.
|
|
23
|
+
*/
|
|
3
24
|
/** Options for {@link impersonate}. */
|
|
4
25
|
export interface KeycardImpersonateOptions extends KeycardConnectionOptions {
|
|
5
26
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connections.d.ts","sourceRoot":"","sources":["../../src/connections.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,mBAAmB,EACnB,qCAAqC,EAEtC,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAsC,KAAK,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAKhG,uCAAuC;AACvC,MAAM,WAAW,yBAA0B,SAAQ,wBAAwB;IACzE;;;OAGG;IACH,cAAc,EAAE,MAAM,GAAG,CAAC,CAAC,SAAS,EAAE,mBAAmB,KAAK,MAAM,CAAC,CAAC;CACvE;AAED;;;;;;GAMG;AACH,wBAAgB,MAAM,CACpB,OAAO,EAAE,wBAAwB,GAChC,qCAAqC,
|
|
1
|
+
{"version":3,"file":"connections.d.ts","sourceRoot":"","sources":["../../src/connections.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,mBAAmB,EACnB,qCAAqC,EAEtC,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAsC,KAAK,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAKhG;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,uCAAuC;AACvC,MAAM,WAAW,yBAA0B,SAAQ,wBAAwB;IACzE;;;OAGG;IACH,cAAc,EAAE,MAAM,GAAG,CAAC,CAAC,SAAS,EAAE,mBAAmB,KAAK,MAAM,CAAC,CAAC;CACvE;AAED;;;;;;GAMG;AACH,wBAAgB,MAAM,CACpB,OAAO,EAAE,wBAAwB,GAChC,qCAAqC,CAkBvC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,UAAU,CACxB,OAAO,EAAE,wBAAwB,GAChC,qCAAqC,CAkDvC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CACzB,OAAO,EAAE,yBAAyB,GACjC,qCAAqC,CAsCvC"}
|
package/dist/esm/connections.js
CHANGED
|
@@ -14,7 +14,6 @@ export function asSelf(options) {
|
|
|
14
14
|
const config = resolveConnectionConfig(options, "asSelf");
|
|
15
15
|
return {
|
|
16
16
|
principalType: "app",
|
|
17
|
-
displayName: config.connectionName,
|
|
18
17
|
async getToken() {
|
|
19
18
|
const request = {
|
|
20
19
|
resource: config.resource,
|
|
@@ -44,7 +43,6 @@ export function onBehalfOf(options) {
|
|
|
44
43
|
const config = resolveConnectionConfig(options, "onBehalfOf");
|
|
45
44
|
return {
|
|
46
45
|
principalType: "user",
|
|
47
|
-
displayName: config.connectionName,
|
|
48
46
|
async getToken({ principal }) {
|
|
49
47
|
requireUser(principal, config.connectionName);
|
|
50
48
|
const subjectToken = readSubjectToken(principal, config.subjectTokens);
|
|
@@ -103,7 +101,6 @@ export function impersonate(options) {
|
|
|
103
101
|
}
|
|
104
102
|
return {
|
|
105
103
|
principalType: typeof identifier === "function" ? "user" : "app",
|
|
106
|
-
displayName: config.connectionName,
|
|
107
104
|
async getToken({ principal }) {
|
|
108
105
|
let userIdentifier;
|
|
109
106
|
if (typeof identifier === "function") {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connections.js","sourceRoot":"","sources":["../../src/connections.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,8BAA8B,EAC9B,SAAS,GAIV,MAAM,kBAAkB,CAAC;AAO1B,OAAO,EAAE,SAAS,EAAE,uBAAuB,EAAiC,MAAM,aAAa,CAAC;AAChG,OAAO,EAAE,wBAAwB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"connections.js","sourceRoot":"","sources":["../../src/connections.ts"],"names":[],"mappings":"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"}
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -19,7 +19,7 @@ export type { KeycardAuthOptions, SubjectTokenRetention } from "./auth.js";
|
|
|
19
19
|
export { asSelf, impersonate, onBehalfOf } from "./connections.js";
|
|
20
20
|
export type { KeycardImpersonateOptions } from "./connections.js";
|
|
21
21
|
export { interactive, memoryAuthorizedTokenStore } from "./interactive.js";
|
|
22
|
-
export type { AuthorizedToken, AuthorizedTokenStore, KeycardInteractiveOptions, KeycardResumeState, WebAppFlow, } from "./interactive.js";
|
|
22
|
+
export type { AuthorizedToken, AuthorizedTokenStore, KeycardInteractiveOptions, KeycardResumeState, RegisterAttemptClientOptions, RegisteredClient, WebAppFlow, } from "./interactive.js";
|
|
23
23
|
export type { KeycardConnectionOptions } from "./config.js";
|
|
24
24
|
export { AuthorizationFailedError, AuthorizationRequiredError, FailureReason, RouteRejectedError, } from "./errors.js";
|
|
25
25
|
export { decodeClaims, subjectTokenExpired } from "./expiry.js";
|
package/dist/esm/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,YAAY,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAE3E,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnE,YAAY,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAC;AAElE,OAAO,EAAE,WAAW,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAC3E,YAAY,EACV,eAAe,EACf,oBAAoB,EACpB,yBAAyB,EACzB,kBAAkB,EAClB,UAAU,GACX,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAE5D,OAAO,EACL,wBAAwB,EACxB,0BAA0B,EAC1B,aAAa,EACb,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEhE,OAAO,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAC;AAC7D,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAE3D,OAAO,EACL,wBAAwB,EACxB,uBAAuB,EACvB,uBAAuB,GACxB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,YAAY,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C;;;GAGG;AACH,eAAO,MAAM,OAAO;;;;;EAKlB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,YAAY,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAE3E,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnE,YAAY,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAC;AAElE,OAAO,EAAE,WAAW,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAC3E,YAAY,EACV,eAAe,EACf,oBAAoB,EACpB,yBAAyB,EACzB,kBAAkB,EAClB,4BAA4B,EAC5B,gBAAgB,EAChB,UAAU,GACX,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAE5D,OAAO,EACL,wBAAwB,EACxB,0BAA0B,EAC1B,aAAa,EACb,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEhE,OAAO,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAC;AAC7D,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAE3D,OAAO,EACL,wBAAwB,EACxB,uBAAuB,EACvB,uBAAuB,GACxB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,YAAY,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C;;;GAGG;AACH,eAAO,MAAM,OAAO;;;;;EAKlB,CAAC"}
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAGxC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGnE,OAAO,EAAE,WAAW,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAGxC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGnE,OAAO,EAAE,WAAW,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAa3E,OAAO,EACL,wBAAwB,EACxB,0BAA0B,EAC1B,aAAa,EACb,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEhE,OAAO,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAC;AAG7D,OAAO,EACL,wBAAwB,EACxB,uBAAuB,EACvB,uBAAuB,GACxB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAGpD,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C;;;GAGG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC;IACnC,MAAM;IACN,WAAW;IACX,WAAW;IACX,UAAU;CACX,CAAC,CAAC"}
|
|
@@ -5,12 +5,19 @@ import type { InteractiveAuthorizationDefinition, JsonValue } from "eve/connecti
|
|
|
5
5
|
*
|
|
6
6
|
* Every field is JSON, so the value satisfies eve's `JsonValue` bound and
|
|
7
7
|
* survives the durable step boundary the park crosses.
|
|
8
|
+
*
|
|
9
|
+
* `clientId` is journaled because it is not necessarily the same value across
|
|
10
|
+
* attempts: under per-attempt registration each authorization runs as its own
|
|
11
|
+
* client, and the code can only be redeemed by the client the authorization
|
|
12
|
+
* request was made with. Nothing secret is journaled — registered clients are
|
|
13
|
+
* public and PKCE-bound; see {@link interactive}.
|
|
8
14
|
*/
|
|
9
15
|
export interface KeycardResumeState {
|
|
10
16
|
readonly state: string;
|
|
11
17
|
readonly codeVerifier: string;
|
|
12
18
|
readonly resources: readonly string[];
|
|
13
19
|
readonly callbackUrl: string;
|
|
20
|
+
readonly clientId: string;
|
|
14
21
|
readonly [key: string]: JsonValue;
|
|
15
22
|
}
|
|
16
23
|
/** A token this package minted for one principal, plus its advisory expiry. */
|
|
@@ -33,20 +40,69 @@ export interface AuthorizedTokenStore {
|
|
|
33
40
|
set(key: string, token: AuthorizedToken): void;
|
|
34
41
|
delete(key: string): void;
|
|
35
42
|
}
|
|
36
|
-
/**
|
|
43
|
+
/** What one authorization attempt needs its own OAuth client for. */
|
|
44
|
+
export interface RegisterAttemptClientOptions {
|
|
45
|
+
/** eve's callback URL for this attempt. The client's only redirect URI. */
|
|
46
|
+
readonly redirectUri: string;
|
|
47
|
+
/** Name the zone shows on the consent screen. */
|
|
48
|
+
readonly clientName?: string;
|
|
49
|
+
readonly scopes?: readonly string[];
|
|
50
|
+
}
|
|
51
|
+
/** A client the authorization server issued for one attempt. */
|
|
52
|
+
export interface RegisteredClient {
|
|
53
|
+
readonly clientId: string;
|
|
54
|
+
/**
|
|
55
|
+
* Only ever set by a server that ignored the public-client registration
|
|
56
|
+
* request. {@link interactive} refuses such a client rather than journaling
|
|
57
|
+
* a secret into eve's durable state.
|
|
58
|
+
*/
|
|
59
|
+
readonly clientSecret?: string;
|
|
60
|
+
}
|
|
61
|
+
/** The web-flow calls this adapter makes, as one seam for tests. */
|
|
37
62
|
export interface WebAppFlow {
|
|
38
63
|
begin(options: BeginAuthorizationOptions): Promise<AuthorizationRedirect>;
|
|
39
64
|
complete(options: CompleteAuthorizationOptions): Promise<TokenResponse>;
|
|
65
|
+
/**
|
|
66
|
+
* Registers the client for one attempt (RFC 7591). Required when no static
|
|
67
|
+
* `clientId` is configured, and unused when one is.
|
|
68
|
+
*/
|
|
69
|
+
register?(options: RegisterAttemptClientOptions): Promise<RegisteredClient>;
|
|
40
70
|
}
|
|
41
71
|
export interface KeycardInteractiveOptions {
|
|
42
72
|
/** The resource URL the authorization is scoped to. */
|
|
43
73
|
resource: string;
|
|
44
74
|
/** Keycard zone URL (issuer). Required unless `flow` is given. */
|
|
45
75
|
zoneUrl?: string;
|
|
46
|
-
/**
|
|
76
|
+
/**
|
|
77
|
+
* OAuth client the browser flow runs as.
|
|
78
|
+
*
|
|
79
|
+
* OMIT THIS unless the client's registered redirect URIs already cover eve's
|
|
80
|
+
* callback. eve mints a fresh callback URL per attempt — the route is
|
|
81
|
+
* `/eve/v1/connections/:name/callback/:attemptId/:token` — while RFC 9700
|
|
82
|
+
* requires the authorization server to match `redirect_uri` by exact string
|
|
83
|
+
* comparison. A statically registered client therefore cannot name the URL
|
|
84
|
+
* the next attempt will use, and the request is rejected. Leaving this unset
|
|
85
|
+
* registers the client per attempt instead, which is the only arrangement
|
|
86
|
+
* that satisfies both.
|
|
87
|
+
*
|
|
88
|
+
* A Keycard application `identifier` is NOT a client id. Zones identify
|
|
89
|
+
* clients by Client ID Metadata Document — an HTTPS URL with a path that
|
|
90
|
+
* serves the client's metadata — so a value like `urn:app:my-agent` fails
|
|
91
|
+
* with `Unsupported client identifier prefix: urn`.
|
|
92
|
+
*/
|
|
47
93
|
clientId?: string;
|
|
48
|
-
/** Client secret, for a confidential client. Public clients omit it. */
|
|
94
|
+
/** Client secret, for a confidential static client. Public clients omit it. */
|
|
49
95
|
clientSecret?: string;
|
|
96
|
+
/**
|
|
97
|
+
* Name shown on the zone's consent screen for a per-attempt client.
|
|
98
|
+
* Defaults to `connectionName`.
|
|
99
|
+
*/
|
|
100
|
+
clientName?: string;
|
|
101
|
+
/**
|
|
102
|
+
* Initial access token (RFC 7591 §3.1) for a zone whose registration
|
|
103
|
+
* endpoint is authenticated. Unset for an open registration endpoint.
|
|
104
|
+
*/
|
|
105
|
+
initialAccessToken?: string;
|
|
50
106
|
/** Scopes requested in the authorization request. */
|
|
51
107
|
requestScopes?: string | readonly string[];
|
|
52
108
|
/** Extra resources authorized alongside `resource`. */
|
|
@@ -81,8 +137,25 @@ export interface KeycardInteractiveOptions {
|
|
|
81
137
|
* rather than an endless loop: it settles each parked authorization once, and
|
|
82
138
|
* a `Required` thrown after a completed authorization ends the tool call.
|
|
83
139
|
*
|
|
140
|
+
* THE CLIENT IS REGISTERED PER ATTEMPT unless `clientId` says otherwise, and
|
|
141
|
+
* that is not an optimization — it is what makes the flow work at all. eve
|
|
142
|
+
* mints a fresh callback URL for every attempt, carrying the attempt id and a
|
|
143
|
+
* run token in its path, while RFC 9700 requires the authorization server to
|
|
144
|
+
* match `redirect_uri` against the client's registered list by exact string
|
|
145
|
+
* comparison. No fixed registration can name a URL that is generated later, so
|
|
146
|
+
* a static client and a dynamic callback cannot both hold. Registering the
|
|
147
|
+
* client alongside the callback it belongs to resolves it: each attempt gets a
|
|
148
|
+
* public, PKCE-bound client whose one redirect URI is the one URL that attempt
|
|
149
|
+
* will return to.
|
|
150
|
+
*
|
|
151
|
+
* Each attempt therefore leaves a client record in the zone. They are public,
|
|
152
|
+
* hold no secret, and are bound to a callback URL that is single-use, but they
|
|
153
|
+
* do accumulate; a server that returns `registration_client_uri` and
|
|
154
|
+
* `registration_access_token` allows RFC 7592 deletion once a grant settles.
|
|
155
|
+
*
|
|
84
156
|
* Discovery is memoized per definition, so the first authorization pays the
|
|
85
|
-
* metadata round trip and later ones do not.
|
|
157
|
+
* metadata round trip and later ones do not. Registration is not memoized —
|
|
158
|
+
* the redirect URI it binds is different every time.
|
|
86
159
|
*/
|
|
87
160
|
export declare function interactive(options: KeycardInteractiveOptions): InteractiveAuthorizationDefinition<KeycardResumeState>;
|
|
88
161
|
/** A process-local store that drops entries at their advisory expiry. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interactive.d.ts","sourceRoot":"","sources":["../../src/interactive.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"interactive.d.ts","sourceRoot":"","sources":["../../src/interactive.ts"],"names":[],"mappings":"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"}
|
package/dist/esm/interactive.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AuthProviderConfigurationError, AuthorizationDeniedError, beginAuthorization, completeAuthorization, fetchAuthorizationServerMetadata, StateMismatchError, } from "@keycardai/oauth";
|
|
1
|
+
import { AuthProviderConfigurationError, AuthorizationDeniedError, beginAuthorization, completeAuthorization, fetchAuthorizationServerMetadata, registerClient, StateMismatchError, } from "@keycardai/oauth";
|
|
2
2
|
import { expiresAt } from "./config.js";
|
|
3
3
|
import { AuthorizationFailedError, AuthorizationRequiredError, FailureReason, } from "./errors.js";
|
|
4
4
|
import { principalKey } from "./subjectTokens.js";
|
|
@@ -25,25 +25,98 @@ import { principalKey } from "./subjectTokens.js";
|
|
|
25
25
|
* rather than an endless loop: it settles each parked authorization once, and
|
|
26
26
|
* a `Required` thrown after a completed authorization ends the tool call.
|
|
27
27
|
*
|
|
28
|
+
* THE CLIENT IS REGISTERED PER ATTEMPT unless `clientId` says otherwise, and
|
|
29
|
+
* that is not an optimization — it is what makes the flow work at all. eve
|
|
30
|
+
* mints a fresh callback URL for every attempt, carrying the attempt id and a
|
|
31
|
+
* run token in its path, while RFC 9700 requires the authorization server to
|
|
32
|
+
* match `redirect_uri` against the client's registered list by exact string
|
|
33
|
+
* comparison. No fixed registration can name a URL that is generated later, so
|
|
34
|
+
* a static client and a dynamic callback cannot both hold. Registering the
|
|
35
|
+
* client alongside the callback it belongs to resolves it: each attempt gets a
|
|
36
|
+
* public, PKCE-bound client whose one redirect URI is the one URL that attempt
|
|
37
|
+
* will return to.
|
|
38
|
+
*
|
|
39
|
+
* Each attempt therefore leaves a client record in the zone. They are public,
|
|
40
|
+
* hold no secret, and are bound to a callback URL that is single-use, but they
|
|
41
|
+
* do accumulate; a server that returns `registration_client_uri` and
|
|
42
|
+
* `registration_access_token` allows RFC 7592 deletion once a grant settles.
|
|
43
|
+
*
|
|
28
44
|
* Discovery is memoized per definition, so the first authorization pays the
|
|
29
|
-
* metadata round trip and later ones do not.
|
|
45
|
+
* metadata round trip and later ones do not. Registration is not memoized —
|
|
46
|
+
* the redirect URI it binds is different every time.
|
|
30
47
|
*/
|
|
31
48
|
export function interactive(options) {
|
|
32
49
|
if (!options.resource || !options.resource.trim()) {
|
|
33
50
|
throw new AuthProviderConfigurationError("interactive requires a resource URL");
|
|
34
51
|
}
|
|
35
|
-
if (!options.flow &&
|
|
36
|
-
throw new AuthProviderConfigurationError("interactive requires zoneUrl
|
|
52
|
+
if (!options.flow && !options.zoneUrl) {
|
|
53
|
+
throw new AuthProviderConfigurationError("interactive requires zoneUrl, or an injected flow");
|
|
37
54
|
}
|
|
38
55
|
const connectionName = options.connectionName ?? options.resource;
|
|
39
56
|
const tokens = options.tokens ?? memoryAuthorizedTokenStore();
|
|
40
|
-
const flow = options.flow ??
|
|
41
|
-
|
|
57
|
+
const flow = options.flow ??
|
|
58
|
+
zoneWebAppFlow(options.zoneUrl, {
|
|
59
|
+
...(options.initialAccessToken !== undefined
|
|
60
|
+
? { initialAccessToken: options.initialAccessToken }
|
|
61
|
+
: {}),
|
|
62
|
+
});
|
|
63
|
+
const staticClientId = options.clientId ?? "";
|
|
64
|
+
const clientName = options.clientName ?? connectionName;
|
|
42
65
|
const resources = [options.resource, ...(options.additionalResources ?? [])];
|
|
43
66
|
const scopes = splitScopes(options.requestScopes);
|
|
67
|
+
if (!staticClientId && !flow.register) {
|
|
68
|
+
throw new AuthProviderConfigurationError("interactive was given no clientId, so it registers a client per attempt, but the " +
|
|
69
|
+
"injected flow has no register()");
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* The client this attempt runs as: the configured one, or a fresh public
|
|
73
|
+
* client whose single redirect URI is this attempt's callback.
|
|
74
|
+
*/
|
|
75
|
+
const clientForAttempt = async (callbackUrl) => {
|
|
76
|
+
if (staticClientId)
|
|
77
|
+
return staticClientId;
|
|
78
|
+
let registered;
|
|
79
|
+
try {
|
|
80
|
+
registered = await flow.register({
|
|
81
|
+
redirectUri: callbackUrl,
|
|
82
|
+
clientName,
|
|
83
|
+
...(scopes.length > 0 ? { scopes } : {}),
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
catch (cause) {
|
|
87
|
+
throw new AuthorizationFailedError(connectionName, {
|
|
88
|
+
message: cause instanceof Error
|
|
89
|
+
? `Registering the OAuth client for this authorization failed: ${cause.message}`
|
|
90
|
+
: "Registering the OAuth client for this authorization failed",
|
|
91
|
+
reason: FailureReason.ACQUISITION_FAILED,
|
|
92
|
+
retryable: true,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
if (registered.clientSecret) {
|
|
96
|
+
throw new AuthorizationFailedError(connectionName, {
|
|
97
|
+
message: "The authorization server issued a confidential client for an authorization " +
|
|
98
|
+
"registered as public. Redeeming it would mean journaling a client secret into " +
|
|
99
|
+
"eve's durable resume state, so the attempt was abandoned instead. Configure a " +
|
|
100
|
+
"static clientId for this connection.",
|
|
101
|
+
reason: FailureReason.ACQUISITION_FAILED,
|
|
102
|
+
retryable: false,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
return registered.clientId;
|
|
106
|
+
};
|
|
44
107
|
return {
|
|
45
108
|
principalType: "user",
|
|
46
|
-
|
|
109
|
+
/**
|
|
110
|
+
* NO definition-level `displayName`. eve validates an authored connection's
|
|
111
|
+
* `auth` against a closed key list (`completeAuthorization`, `evict`,
|
|
112
|
+
* `getToken`, `principalType`, `startAuthorization`, `vercelConnect`) that
|
|
113
|
+
* omits it, so setting it here fails the BUILD with
|
|
114
|
+
* `The "auth" field Unknown key "displayName"` for every interactive
|
|
115
|
+
* connection. The name still reaches the sign-in prompt: it rides on the
|
|
116
|
+
* challenge below, and eve's `stampChallengeDisplayName` resolves
|
|
117
|
+
* `definition.displayName ?? challenge.displayName`. The definition-level
|
|
118
|
+
* field was only ever a precedence override of a value already carried.
|
|
119
|
+
*/
|
|
47
120
|
async getToken({ principal }) {
|
|
48
121
|
const key = storeKey(principal, connectionName);
|
|
49
122
|
const held = tokens.get(key);
|
|
@@ -54,8 +127,9 @@ export function interactive(options) {
|
|
|
54
127
|
},
|
|
55
128
|
async startAuthorization({ principal, callbackUrl }) {
|
|
56
129
|
requireUser(principal, connectionName);
|
|
130
|
+
const attemptClientId = await clientForAttempt(callbackUrl);
|
|
57
131
|
const redirect = await flow.begin({
|
|
58
|
-
clientId,
|
|
132
|
+
clientId: attemptClientId,
|
|
59
133
|
redirectUri: callbackUrl,
|
|
60
134
|
resources,
|
|
61
135
|
...(scopes.length > 0 ? { scopes } : {}),
|
|
@@ -67,6 +141,7 @@ export function interactive(options) {
|
|
|
67
141
|
codeVerifier: redirect.codeVerifier,
|
|
68
142
|
resources: redirect.resources,
|
|
69
143
|
callbackUrl,
|
|
144
|
+
clientId: attemptClientId,
|
|
70
145
|
},
|
|
71
146
|
};
|
|
72
147
|
},
|
|
@@ -86,9 +161,15 @@ export function interactive(options) {
|
|
|
86
161
|
callbackParams: { ...callback.params },
|
|
87
162
|
state: resume.state,
|
|
88
163
|
codeVerifier: resume.codeVerifier,
|
|
89
|
-
|
|
164
|
+
// The attempt's own client. Falls back to the configured one for a
|
|
165
|
+
// resume journaled before this field existed.
|
|
166
|
+
clientId: resume.clientId || staticClientId,
|
|
90
167
|
redirectUri: resume.callbackUrl || callbackUrl,
|
|
91
|
-
|
|
168
|
+
// Only a static client can be confidential; a per-attempt client is
|
|
169
|
+
// always public, so there is no secret to send.
|
|
170
|
+
...(staticClientId && options.clientSecret
|
|
171
|
+
? { clientSecret: options.clientSecret }
|
|
172
|
+
: {}),
|
|
92
173
|
});
|
|
93
174
|
}
|
|
94
175
|
catch (cause) {
|
|
@@ -142,7 +223,7 @@ export function memoryAuthorizedTokenStore() {
|
|
|
142
223
|
};
|
|
143
224
|
}
|
|
144
225
|
/** The default flow: the zone's web-app endpoints, with discovery memoized. */
|
|
145
|
-
function zoneWebAppFlow(issuer) {
|
|
226
|
+
function zoneWebAppFlow(issuer, options = {}) {
|
|
146
227
|
let metadata;
|
|
147
228
|
const discover = () => {
|
|
148
229
|
if (!metadata)
|
|
@@ -150,11 +231,39 @@ function zoneWebAppFlow(issuer) {
|
|
|
150
231
|
return metadata;
|
|
151
232
|
};
|
|
152
233
|
return {
|
|
153
|
-
async begin(
|
|
154
|
-
return beginAuthorization(issuer, { ...
|
|
234
|
+
async begin(beginOptions) {
|
|
235
|
+
return beginAuthorization(issuer, { ...beginOptions, metadata: await discover() });
|
|
236
|
+
},
|
|
237
|
+
async complete(completeOptions) {
|
|
238
|
+
return completeAuthorization(issuer, { ...completeOptions, metadata: await discover() });
|
|
155
239
|
},
|
|
156
|
-
|
|
157
|
-
|
|
240
|
+
/**
|
|
241
|
+
* One public, PKCE-bound client per authorization, holding the single
|
|
242
|
+
* redirect URI that attempt will actually come back to.
|
|
243
|
+
*
|
|
244
|
+
* `token_endpoint_auth_method: "none"` is what keeps the resume state free
|
|
245
|
+
* of credentials: a public client has no secret to journal, and the code is
|
|
246
|
+
* bound to the PKCE verifier instead. `refresh_token` is requested so a
|
|
247
|
+
* long-lived grant can be renewed without sending the user back through the
|
|
248
|
+
* browser.
|
|
249
|
+
*/
|
|
250
|
+
async register({ redirectUri, clientName, scopes }) {
|
|
251
|
+
const registered = await registerClient(issuer, {
|
|
252
|
+
...(clientName !== undefined ? { clientName } : {}),
|
|
253
|
+
redirectUris: [redirectUri],
|
|
254
|
+
grantTypes: ["authorization_code", "refresh_token"],
|
|
255
|
+
responseTypes: ["code"],
|
|
256
|
+
tokenEndpointAuthMethod: "none",
|
|
257
|
+
...(scopes && scopes.length > 0 ? { scope: scopes.join(" ") } : {}),
|
|
258
|
+
}, options.initialAccessToken !== undefined
|
|
259
|
+
? { initialAccessToken: options.initialAccessToken }
|
|
260
|
+
: undefined);
|
|
261
|
+
return {
|
|
262
|
+
clientId: registered.clientId,
|
|
263
|
+
...(registered.clientSecret !== undefined
|
|
264
|
+
? { clientSecret: registered.clientSecret }
|
|
265
|
+
: {}),
|
|
266
|
+
};
|
|
158
267
|
},
|
|
159
268
|
};
|
|
160
269
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interactive.js","sourceRoot":"","sources":["../../src/interactive.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,8BAA8B,EAC9B,wBAAwB,EACxB,kBAAkB,EAClB,qBAAqB,EACrB,gCAAgC,EAChC,kBAAkB,GAMnB,MAAM,kBAAkB,CAAC;AAQ1B,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EACL,wBAAwB,EACxB,0BAA0B,EAC1B,aAAa,GACd,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"interactive.js","sourceRoot":"","sources":["../../src/interactive.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,14 +1,19 @@
|
|
|
1
|
+
import type { ToolAuthOptions } from "eve/tools";
|
|
1
2
|
/**
|
|
2
3
|
* The part of eve's tool context this helper needs.
|
|
3
4
|
*
|
|
4
5
|
* Declared structurally rather than imported so nothing here loads eve at
|
|
5
6
|
* runtime. `ctx.requireAuth` never returns: it aborts the tool call and hands
|
|
6
7
|
* the connection's authorization strategy back to the runtime.
|
|
8
|
+
*
|
|
9
|
+
* The options are eve's own `ToolAuthOptions` — imported as a type, which is
|
|
10
|
+
* erased, so the structural property still holds. Taking the type from eve
|
|
11
|
+
* rather than restating it is deliberate: the previous hand-written shape
|
|
12
|
+
* accepted a `reason` field that eve does not have, and a call passing one
|
|
13
|
+
* failed to typecheck at the call site rather than here.
|
|
7
14
|
*/
|
|
8
15
|
export interface RequireAuthContext<Provider> {
|
|
9
|
-
requireAuth(provider: Provider, options?:
|
|
10
|
-
readonly reason?: string;
|
|
11
|
-
}): never;
|
|
16
|
+
requireAuth(provider: Provider, options?: ToolAuthOptions): never;
|
|
12
17
|
}
|
|
13
18
|
/**
|
|
14
19
|
* Maps a provider's rejection of the current credential onto
|
|
@@ -29,7 +34,5 @@ export interface RequireAuthContext<Provider> {
|
|
|
29
34
|
*/
|
|
30
35
|
export declare function requireAuthOnUnauthorized<Provider>(response: {
|
|
31
36
|
readonly status: number;
|
|
32
|
-
}, ctx: RequireAuthContext<Provider>, provider: Provider, options?:
|
|
33
|
-
readonly reason?: string;
|
|
34
|
-
}): void;
|
|
37
|
+
}, ctx: RequireAuthContext<Provider>, provider: Provider, options?: ToolAuthOptions): void;
|
|
35
38
|
//# sourceMappingURL=requireAuth.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"requireAuth.d.ts","sourceRoot":"","sources":["../../src/requireAuth.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"requireAuth.d.ts","sourceRoot":"","sources":["../../src/requireAuth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjD;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,kBAAkB,CAAC,QAAQ;IAC1C,WAAW,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,KAAK,CAAC;CACnE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAChD,QAAQ,EAAE;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EACrC,GAAG,EAAE,kBAAkB,CAAC,QAAQ,CAAC,EACjC,QAAQ,EAAE,QAAQ,EAClB,OAAO,CAAC,EAAE,eAAe,GACxB,IAAI,CAGN"}
|
package/dist/esm/requireAuth.js
CHANGED
|
@@ -18,9 +18,6 @@
|
|
|
18
18
|
export function requireAuthOnUnauthorized(response, ctx, provider, options) {
|
|
19
19
|
if (response.status !== 401 && response.status !== 403)
|
|
20
20
|
return;
|
|
21
|
-
ctx.requireAuth(provider,
|
|
22
|
-
reason: options?.reason ??
|
|
23
|
-
`The provider rejected the connection credential with ${response.status}.`,
|
|
24
|
-
});
|
|
21
|
+
ctx.requireAuth(provider, options);
|
|
25
22
|
}
|
|
26
23
|
//# sourceMappingURL=requireAuth.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"requireAuth.js","sourceRoot":"","sources":["../../src/requireAuth.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"requireAuth.js","sourceRoot":"","sources":["../../src/requireAuth.ts"],"names":[],"mappings":"AAmBA;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,yBAAyB,CACvC,QAAqC,EACrC,GAAiC,EACjC,QAAkB,EAClB,OAAyB;IAEzB,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG;QAAE,OAAO;IAC/D,GAAG,CAAC,WAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AACrC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@keycardai/eve",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "[Preview] Keycard auth adapters for eve agents: a zone token verifier for the channel auth walk, Keycard-backed connection auth, and interactive authorization over the zone's web flow",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -30,15 +30,15 @@
|
|
|
30
30
|
}
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@keycardai/oauth": "0.
|
|
33
|
+
"@keycardai/oauth": "0.24.1"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
|
-
"eve": ">=0.
|
|
36
|
+
"eve": ">=0.54.3 <0.55.0"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@jest/globals": "^30.0.4",
|
|
40
40
|
"@types/node": "^25.6.0",
|
|
41
|
-
"eve": "0.
|
|
41
|
+
"eve": "0.54.3",
|
|
42
42
|
"jest": "^30.0.4",
|
|
43
43
|
"ts-jest": "^29.4.7",
|
|
44
44
|
"typescript": "^5.8.3"
|