@keycardai/eve 0.1.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/LICENSE +9 -0
- package/README.md +223 -0
- package/dist/esm/auth.d.ts +62 -0
- package/dist/esm/auth.d.ts.map +1 -0
- package/dist/esm/auth.js +165 -0
- package/dist/esm/auth.js.map +1 -0
- package/dist/esm/config.d.ts +50 -0
- package/dist/esm/config.d.ts.map +1 -0
- package/dist/esm/config.js +83 -0
- package/dist/esm/config.js.map +1 -0
- package/dist/esm/connections.d.ts +48 -0
- package/dist/esm/connections.d.ts.map +1 -0
- package/dist/esm/connections.js +167 -0
- package/dist/esm/connections.js.map +1 -0
- package/dist/esm/errors.d.ts +78 -0
- package/dist/esm/errors.d.ts.map +1 -0
- package/dist/esm/errors.js +93 -0
- package/dist/esm/errors.js.map +1 -0
- package/dist/esm/expiry.d.ts +20 -0
- package/dist/esm/expiry.d.ts.map +1 -0
- package/dist/esm/expiry.js +49 -0
- package/dist/esm/expiry.js.map +1 -0
- package/dist/esm/index.d.ts +44 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +37 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/interactive.d.ts +90 -0
- package/dist/esm/interactive.d.ts.map +1 -0
- package/dist/esm/interactive.js +190 -0
- package/dist/esm/interactive.js.map +1 -0
- package/dist/esm/package.json +1 -0
- package/dist/esm/requireAuth.d.ts +35 -0
- package/dist/esm/requireAuth.d.ts.map +1 -0
- package/dist/esm/requireAuth.js +26 -0
- package/dist/esm/requireAuth.js.map +1 -0
- package/dist/esm/subjectTokens.d.ts +50 -0
- package/dist/esm/subjectTokens.d.ts.map +1 -0
- package/dist/esm/subjectTokens.js +73 -0
- package/dist/esm/subjectTokens.js.map +1 -0
- package/dist/esm/testing/index.d.ts +10 -0
- package/dist/esm/testing/index.d.ts.map +1 -0
- package/dist/esm/testing/index.js +9 -0
- package/dist/esm/testing/index.js.map +1 -0
- package/dist/esm/testing/testUtils.d.ts +51 -0
- package/dist/esm/testing/testUtils.d.ts.map +1 -0
- package/dist/esm/testing/testUtils.js +90 -0
- package/dist/esm/testing/testUtils.js.map +1 -0
- package/dist/esm/zoneClient.d.ts +42 -0
- package/dist/esm/zoneClient.d.ts.map +1 -0
- package/dist/esm/zoneClient.js +45 -0
- package/dist/esm/zoneClient.js.map +1 -0
- package/package.json +53 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { ConnectionPrincipal, NonInteractiveAuthorizationDefinition } from "eve/connections";
|
|
2
|
+
import { type KeycardConnectionOptions } from "./config.js";
|
|
3
|
+
/** Options for {@link impersonate}. */
|
|
4
|
+
export interface KeycardImpersonateOptions extends KeycardConnectionOptions {
|
|
5
|
+
/**
|
|
6
|
+
* The user the agent acts for. A function receives the connection principal,
|
|
7
|
+
* so a session-scoped identifier can be read from the turn's current auth.
|
|
8
|
+
*/
|
|
9
|
+
userIdentifier: string | ((principal: ConnectionPrincipal) => string);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Connection auth that runs client credentials under the agent's own identity.
|
|
13
|
+
*
|
|
14
|
+
* App-scoped: eve resolves `{ type: "app" }` and never asks the session for a
|
|
15
|
+
* user, so this works on schedules and subagent turns. No exchange and no
|
|
16
|
+
* impersonation, so nothing about the caller reaches the zone.
|
|
17
|
+
*/
|
|
18
|
+
export declare function asSelf(options: KeycardConnectionOptions): NonInteractiveAuthorizationDefinition;
|
|
19
|
+
/**
|
|
20
|
+
* Connection auth that exchanges the caller's token for a resource token.
|
|
21
|
+
*
|
|
22
|
+
* User-scoped, so eve resolves the principal from the active turn's
|
|
23
|
+
* `ctx.session.auth.current` and fails with `principal_required` before this
|
|
24
|
+
* runs when there is no authenticated user. The subject token exchanged is the
|
|
25
|
+
* one `keycardAuth` verified for that same principal.
|
|
26
|
+
*
|
|
27
|
+
* Nothing here falls back to the agent's authority. A run without a user
|
|
28
|
+
* principal, a turn whose subject token was never retained, and an expired
|
|
29
|
+
* subject token all fail, each with its own reason: `principal_required`,
|
|
30
|
+
* `subject_token_unavailable`, and `subject_token_expired`. The last one is
|
|
31
|
+
* the sign-in signal, decided by a decode-only expiry check so an already
|
|
32
|
+
* dead token never costs an exchange round trip.
|
|
33
|
+
*/
|
|
34
|
+
export declare function onBehalfOf(options: KeycardConnectionOptions): NonInteractiveAuthorizationDefinition;
|
|
35
|
+
/**
|
|
36
|
+
* Connection auth that acts for a named user the agent holds no token for.
|
|
37
|
+
*
|
|
38
|
+
* Uses the zone's substitute-user exchange, authenticated by the application
|
|
39
|
+
* credential: no subject token is involved, so this is the pattern for
|
|
40
|
+
* back-office and batch work rather than for a user's own request.
|
|
41
|
+
*
|
|
42
|
+
* The principal type follows the identifier. A function needs the turn's
|
|
43
|
+
* current user, so the connection is user-scoped and inherits eve's
|
|
44
|
+
* `principal_required` rejection; a fixed identifier needs no caller, so the
|
|
45
|
+
* connection is app-scoped and runs on schedules.
|
|
46
|
+
*/
|
|
47
|
+
export declare function impersonate(options: KeycardImpersonateOptions): NonInteractiveAuthorizationDefinition;
|
|
48
|
+
//# sourceMappingURL=connections.d.ts.map
|
|
@@ -0,0 +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,CAmBvC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,UAAU,CACxB,OAAO,EAAE,wBAAwB,GAChC,qCAAqC,CAmDvC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CACzB,OAAO,EAAE,yBAAyB,GACjC,qCAAqC,CAuCvC"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { AuthProviderConfigurationError, TokenType, } from "@keycardai/oauth";
|
|
2
|
+
import { expiresAt, resolveConnectionConfig } from "./config.js";
|
|
3
|
+
import { AuthorizationFailedError, FailureReason } from "./errors.js";
|
|
4
|
+
import { subjectTokenExpired } from "./expiry.js";
|
|
5
|
+
import { principalKey, readSubjectToken } from "./subjectTokens.js";
|
|
6
|
+
/**
|
|
7
|
+
* Connection auth that runs client credentials under the agent's own identity.
|
|
8
|
+
*
|
|
9
|
+
* App-scoped: eve resolves `{ type: "app" }` and never asks the session for a
|
|
10
|
+
* user, so this works on schedules and subagent turns. No exchange and no
|
|
11
|
+
* impersonation, so nothing about the caller reaches the zone.
|
|
12
|
+
*/
|
|
13
|
+
export function asSelf(options) {
|
|
14
|
+
const config = resolveConnectionConfig(options, "asSelf");
|
|
15
|
+
return {
|
|
16
|
+
principalType: "app",
|
|
17
|
+
displayName: config.connectionName,
|
|
18
|
+
async getToken() {
|
|
19
|
+
const request = {
|
|
20
|
+
resource: config.resource,
|
|
21
|
+
...(config.scope ? { scope: config.scope } : {}),
|
|
22
|
+
...(await config.clientAuthFields()),
|
|
23
|
+
};
|
|
24
|
+
return tokenResult(await acquire(config.connectionName, () => config.zoneClient().clientCredentialsGrant(request)));
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Connection auth that exchanges the caller's token for a resource token.
|
|
30
|
+
*
|
|
31
|
+
* User-scoped, so eve resolves the principal from the active turn's
|
|
32
|
+
* `ctx.session.auth.current` and fails with `principal_required` before this
|
|
33
|
+
* runs when there is no authenticated user. The subject token exchanged is the
|
|
34
|
+
* one `keycardAuth` verified for that same principal.
|
|
35
|
+
*
|
|
36
|
+
* Nothing here falls back to the agent's authority. A run without a user
|
|
37
|
+
* principal, a turn whose subject token was never retained, and an expired
|
|
38
|
+
* subject token all fail, each with its own reason: `principal_required`,
|
|
39
|
+
* `subject_token_unavailable`, and `subject_token_expired`. The last one is
|
|
40
|
+
* the sign-in signal, decided by a decode-only expiry check so an already
|
|
41
|
+
* dead token never costs an exchange round trip.
|
|
42
|
+
*/
|
|
43
|
+
export function onBehalfOf(options) {
|
|
44
|
+
const config = resolveConnectionConfig(options, "onBehalfOf");
|
|
45
|
+
return {
|
|
46
|
+
principalType: "user",
|
|
47
|
+
displayName: config.connectionName,
|
|
48
|
+
async getToken({ principal }) {
|
|
49
|
+
requireUser(principal, config.connectionName);
|
|
50
|
+
const subjectToken = readSubjectToken(principal, config.subjectTokens);
|
|
51
|
+
if (!subjectToken) {
|
|
52
|
+
throw new AuthorizationFailedError(config.connectionName, {
|
|
53
|
+
message: "No Keycard subject token is retained for this turn's principal. Add " +
|
|
54
|
+
"keycardAuth() to the channel's auth array, or use retainSubjectToken: " +
|
|
55
|
+
'"attributes" when connections run outside the process that authenticated ' +
|
|
56
|
+
"the request.",
|
|
57
|
+
reason: FailureReason.SUBJECT_TOKEN_UNAVAILABLE,
|
|
58
|
+
retryable: false,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
if (subjectTokenExpired(subjectToken)) {
|
|
62
|
+
config.subjectTokens.delete(principalKey(principal));
|
|
63
|
+
throw new AuthorizationFailedError(config.connectionName, {
|
|
64
|
+
message: "The Keycard subject token for this turn has expired. Sign in again to continue.",
|
|
65
|
+
reason: FailureReason.SUBJECT_TOKEN_EXPIRED,
|
|
66
|
+
retryable: false,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
let request;
|
|
70
|
+
if (config.credential) {
|
|
71
|
+
request = await config.credential.prepareTokenExchangeRequest(subjectToken, config.resource);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
request = {
|
|
75
|
+
subjectToken,
|
|
76
|
+
resource: config.resource,
|
|
77
|
+
subjectTokenType: TokenType.ACCESS_TOKEN,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
if (config.scope)
|
|
81
|
+
request = { ...request, scope: config.scope };
|
|
82
|
+
return tokenResult(await acquire(config.connectionName, () => config.zoneClient().exchangeToken(request)));
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Connection auth that acts for a named user the agent holds no token for.
|
|
88
|
+
*
|
|
89
|
+
* Uses the zone's substitute-user exchange, authenticated by the application
|
|
90
|
+
* credential: no subject token is involved, so this is the pattern for
|
|
91
|
+
* back-office and batch work rather than for a user's own request.
|
|
92
|
+
*
|
|
93
|
+
* The principal type follows the identifier. A function needs the turn's
|
|
94
|
+
* current user, so the connection is user-scoped and inherits eve's
|
|
95
|
+
* `principal_required` rejection; a fixed identifier needs no caller, so the
|
|
96
|
+
* connection is app-scoped and runs on schedules.
|
|
97
|
+
*/
|
|
98
|
+
export function impersonate(options) {
|
|
99
|
+
const config = resolveConnectionConfig(options, "impersonate");
|
|
100
|
+
const identifier = options.userIdentifier;
|
|
101
|
+
if (typeof identifier === "string" && !identifier.trim()) {
|
|
102
|
+
throw new AuthProviderConfigurationError("impersonate requires a non-empty user identifier");
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
principalType: typeof identifier === "function" ? "user" : "app",
|
|
106
|
+
displayName: config.connectionName,
|
|
107
|
+
async getToken({ principal }) {
|
|
108
|
+
let userIdentifier;
|
|
109
|
+
if (typeof identifier === "function") {
|
|
110
|
+
requireUser(principal, config.connectionName);
|
|
111
|
+
userIdentifier = identifier(principal);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
userIdentifier = identifier;
|
|
115
|
+
}
|
|
116
|
+
if (!userIdentifier || !userIdentifier.trim()) {
|
|
117
|
+
throw new AuthorizationFailedError(config.connectionName, {
|
|
118
|
+
message: "impersonate resolved an empty user identifier for this turn.",
|
|
119
|
+
reason: FailureReason.PRINCIPAL_REQUIRED,
|
|
120
|
+
retryable: false,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
return tokenResult(await acquire(config.connectionName, () => config.zoneClient().impersonate({
|
|
124
|
+
userIdentifier,
|
|
125
|
+
resource: config.resource,
|
|
126
|
+
...(config.scope ? { scope: config.scope } : {}),
|
|
127
|
+
})));
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* eve rejects a user-scoped connection with no current user before `getToken`
|
|
133
|
+
* runs. This repeats the check with eve's own reason so a factory driven
|
|
134
|
+
* directly, or resolved under an app principal, fails the same way instead of
|
|
135
|
+
* acquiring under the agent's authority.
|
|
136
|
+
*/
|
|
137
|
+
function requireUser(principal, connectionName) {
|
|
138
|
+
if (principal.type === "user")
|
|
139
|
+
return;
|
|
140
|
+
throw new AuthorizationFailedError(connectionName, {
|
|
141
|
+
message: "This connection acts for a user, and the current turn has no authenticated " +
|
|
142
|
+
"user principal.",
|
|
143
|
+
reason: FailureReason.PRINCIPAL_REQUIRED,
|
|
144
|
+
retryable: false,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
/** Wraps a zone failure as an eve authorization failure for this connection. */
|
|
148
|
+
async function acquire(connectionName, request) {
|
|
149
|
+
try {
|
|
150
|
+
return await request();
|
|
151
|
+
}
|
|
152
|
+
catch (cause) {
|
|
153
|
+
throw new AuthorizationFailedError(connectionName, {
|
|
154
|
+
message: cause instanceof Error ? cause.message : "Token acquisition failed",
|
|
155
|
+
reason: FailureReason.ACQUISITION_FAILED,
|
|
156
|
+
retryable: false,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
function tokenResult(response) {
|
|
161
|
+
const expiry = expiresAt(response.expiresIn);
|
|
162
|
+
return {
|
|
163
|
+
token: response.accessToken,
|
|
164
|
+
...(expiry !== undefined ? { expiresAt: expiry } : {}),
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=connections.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connections.js","sourceRoot":"","sources":["../../src/connections.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Errors this package raises into eve's own error channels.
|
|
3
|
+
*
|
|
4
|
+
* eve narrows connection authorization errors by `error.name` rather than by
|
|
5
|
+
* `instanceof` (see `isConnectionAuthorizationRequiredError` in
|
|
6
|
+
* `eve/connections`), and its `routeAuth` walk recognizes a rejection by the
|
|
7
|
+
* `response` property carrying a `Response`. Both contracts are structural, so
|
|
8
|
+
* this package satisfies them without importing eve at runtime: nothing here
|
|
9
|
+
* loads eve code, which is what keeps the package usable from a Node 22
|
|
10
|
+
* toolchain even though eve itself requires Node 24.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Signals that the user must complete an authorization flow.
|
|
14
|
+
*
|
|
15
|
+
* Thrown from an interactive connection's `getToken`. eve emits
|
|
16
|
+
* `authorization.required`, runs `startAuthorization`, and durably parks the
|
|
17
|
+
* turn on its own callback webhook.
|
|
18
|
+
*/
|
|
19
|
+
export declare class AuthorizationRequiredError extends Error {
|
|
20
|
+
readonly connectionName: string;
|
|
21
|
+
constructor(connectionName: string, options?: {
|
|
22
|
+
message?: string;
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Signals that authorization failed.
|
|
27
|
+
*
|
|
28
|
+
* `reason` is the stable machine-readable code eve surfaces on the
|
|
29
|
+
* `authorization.completed` event and on the failed tool result. `retryable`
|
|
30
|
+
* is `false` for the cases a fresh consent page cannot fix, so eve stops
|
|
31
|
+
* re-prompting: a run with no user principal, an expired subject token, or a
|
|
32
|
+
* denied grant.
|
|
33
|
+
*/
|
|
34
|
+
export declare class AuthorizationFailedError extends Error {
|
|
35
|
+
readonly connectionName: string;
|
|
36
|
+
readonly reason?: string;
|
|
37
|
+
readonly retryable: boolean;
|
|
38
|
+
constructor(connectionName: string, options?: {
|
|
39
|
+
message?: string;
|
|
40
|
+
reason?: string;
|
|
41
|
+
retryable?: boolean;
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
/** Reasons {@link AuthorizationFailedError} carries out of this package. */
|
|
45
|
+
export declare const FailureReason: Readonly<{
|
|
46
|
+
/**
|
|
47
|
+
* eve's own reason for a user-scoped connection running without an
|
|
48
|
+
* authenticated user. Raised here too, so a factory used outside eve's
|
|
49
|
+
* principal resolution fails the same way instead of falling back to the
|
|
50
|
+
* agent's authority.
|
|
51
|
+
*/
|
|
52
|
+
readonly PRINCIPAL_REQUIRED: "principal_required";
|
|
53
|
+
/** The retained subject token is a JWT whose `exp` has passed. */
|
|
54
|
+
readonly SUBJECT_TOKEN_EXPIRED: "subject_token_expired";
|
|
55
|
+
/** No subject token was retained for the principal of this turn. */
|
|
56
|
+
readonly SUBJECT_TOKEN_UNAVAILABLE: "subject_token_unavailable";
|
|
57
|
+
/** The zone refused to issue a token for the connection's resource. */
|
|
58
|
+
readonly ACQUISITION_FAILED: "acquisition_failed";
|
|
59
|
+
/** The user denied consent, or the provider returned an OAuth error. */
|
|
60
|
+
readonly ACCESS_DENIED: "access_denied";
|
|
61
|
+
/** The callback did not carry the state journaled at the begin step. */
|
|
62
|
+
readonly INVALID_CALLBACK: "invalid_callback";
|
|
63
|
+
}>;
|
|
64
|
+
/**
|
|
65
|
+
* Rejects a route in eve's ordered auth walk with a structured 401.
|
|
66
|
+
*
|
|
67
|
+
* `routeAuth` returns the `response` of a thrown error that carries one, so
|
|
68
|
+
* the walk stops here instead of continuing to a later, more permissive entry.
|
|
69
|
+
*/
|
|
70
|
+
export declare class RouteRejectedError extends Error {
|
|
71
|
+
readonly response: Response;
|
|
72
|
+
constructor(options?: {
|
|
73
|
+
message?: string;
|
|
74
|
+
code?: string;
|
|
75
|
+
error?: string;
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AASH;;;;;;GAMG;AACH,qBAAa,0BAA2B,SAAQ,KAAK;IACnD,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;gBAEpB,cAAc,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE;CAKnE;AAED;;;;;;;;GAQG;AACH,qBAAa,wBAAyB,SAAQ,KAAK;IACjD,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;gBAG1B,cAAc,EAAE,MAAM,EACtB,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE;CAQvE;AAED,4EAA4E;AAC5E,eAAO,MAAM,aAAa;IACxB;;;;;OAKG;;IAEH,kEAAkE;;IAElE,oEAAoE;;IAEpE,uEAAuE;;IAEvE,wEAAwE;;IAExE,wEAAwE;;EAE/D,CAAC;AAEZ;;;;;GAKG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;gBAEhB,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;CAkB1E"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Errors this package raises into eve's own error channels.
|
|
3
|
+
*
|
|
4
|
+
* eve narrows connection authorization errors by `error.name` rather than by
|
|
5
|
+
* `instanceof` (see `isConnectionAuthorizationRequiredError` in
|
|
6
|
+
* `eve/connections`), and its `routeAuth` walk recognizes a rejection by the
|
|
7
|
+
* `response` property carrying a `Response`. Both contracts are structural, so
|
|
8
|
+
* this package satisfies them without importing eve at runtime: nothing here
|
|
9
|
+
* loads eve code, which is what keeps the package usable from a Node 22
|
|
10
|
+
* toolchain even though eve itself requires Node 24.
|
|
11
|
+
*/
|
|
12
|
+
/** eve's name for the authorization-required error. */
|
|
13
|
+
const AUTHORIZATION_REQUIRED_NAME = "ConnectionAuthorizationRequiredError";
|
|
14
|
+
/** eve's name for the authorization-failed error. */
|
|
15
|
+
const AUTHORIZATION_FAILED_NAME = "ConnectionAuthorizationFailedError";
|
|
16
|
+
/** eve's name for a route rejection carrying its own 401 response. */
|
|
17
|
+
const UNAUTHENTICATED_NAME = "UnauthenticatedError";
|
|
18
|
+
/**
|
|
19
|
+
* Signals that the user must complete an authorization flow.
|
|
20
|
+
*
|
|
21
|
+
* Thrown from an interactive connection's `getToken`. eve emits
|
|
22
|
+
* `authorization.required`, runs `startAuthorization`, and durably parks the
|
|
23
|
+
* turn on its own callback webhook.
|
|
24
|
+
*/
|
|
25
|
+
export class AuthorizationRequiredError extends Error {
|
|
26
|
+
constructor(connectionName, options) {
|
|
27
|
+
super(options?.message ?? `Connection "${connectionName}" requires authorization.`);
|
|
28
|
+
this.name = AUTHORIZATION_REQUIRED_NAME;
|
|
29
|
+
this.connectionName = connectionName;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Signals that authorization failed.
|
|
34
|
+
*
|
|
35
|
+
* `reason` is the stable machine-readable code eve surfaces on the
|
|
36
|
+
* `authorization.completed` event and on the failed tool result. `retryable`
|
|
37
|
+
* is `false` for the cases a fresh consent page cannot fix, so eve stops
|
|
38
|
+
* re-prompting: a run with no user principal, an expired subject token, or a
|
|
39
|
+
* denied grant.
|
|
40
|
+
*/
|
|
41
|
+
export class AuthorizationFailedError extends Error {
|
|
42
|
+
constructor(connectionName, options) {
|
|
43
|
+
super(options?.message ?? `Connection "${connectionName}" authorization failed.`);
|
|
44
|
+
this.name = AUTHORIZATION_FAILED_NAME;
|
|
45
|
+
this.connectionName = connectionName;
|
|
46
|
+
this.reason = options?.reason;
|
|
47
|
+
this.retryable = options?.retryable ?? true;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/** Reasons {@link AuthorizationFailedError} carries out of this package. */
|
|
51
|
+
export const FailureReason = Object.freeze({
|
|
52
|
+
/**
|
|
53
|
+
* eve's own reason for a user-scoped connection running without an
|
|
54
|
+
* authenticated user. Raised here too, so a factory used outside eve's
|
|
55
|
+
* principal resolution fails the same way instead of falling back to the
|
|
56
|
+
* agent's authority.
|
|
57
|
+
*/
|
|
58
|
+
PRINCIPAL_REQUIRED: "principal_required",
|
|
59
|
+
/** The retained subject token is a JWT whose `exp` has passed. */
|
|
60
|
+
SUBJECT_TOKEN_EXPIRED: "subject_token_expired",
|
|
61
|
+
/** No subject token was retained for the principal of this turn. */
|
|
62
|
+
SUBJECT_TOKEN_UNAVAILABLE: "subject_token_unavailable",
|
|
63
|
+
/** The zone refused to issue a token for the connection's resource. */
|
|
64
|
+
ACQUISITION_FAILED: "acquisition_failed",
|
|
65
|
+
/** The user denied consent, or the provider returned an OAuth error. */
|
|
66
|
+
ACCESS_DENIED: "access_denied",
|
|
67
|
+
/** The callback did not carry the state journaled at the begin step. */
|
|
68
|
+
INVALID_CALLBACK: "invalid_callback",
|
|
69
|
+
});
|
|
70
|
+
/**
|
|
71
|
+
* Rejects a route in eve's ordered auth walk with a structured 401.
|
|
72
|
+
*
|
|
73
|
+
* `routeAuth` returns the `response` of a thrown error that carries one, so
|
|
74
|
+
* the walk stops here instead of continuing to a later, more permissive entry.
|
|
75
|
+
*/
|
|
76
|
+
export class RouteRejectedError extends Error {
|
|
77
|
+
constructor(options) {
|
|
78
|
+
super(options?.message ?? "Authorization is required for this route.");
|
|
79
|
+
this.name = UNAUTHENTICATED_NAME;
|
|
80
|
+
const challenge = options?.error
|
|
81
|
+
? `Bearer error="${options.error}"`
|
|
82
|
+
: "Bearer";
|
|
83
|
+
this.response = Response.json({
|
|
84
|
+
code: options?.code ?? "unauthorized",
|
|
85
|
+
error: options?.message ?? "Authorization is required for this route.",
|
|
86
|
+
ok: false,
|
|
87
|
+
}, {
|
|
88
|
+
status: 401,
|
|
89
|
+
headers: { "cache-control": "no-store", "www-authenticate": challenge },
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,uDAAuD;AACvD,MAAM,2BAA2B,GAAG,sCAAsC,CAAC;AAC3E,qDAAqD;AACrD,MAAM,yBAAyB,GAAG,oCAAoC,CAAC;AACvE,sEAAsE;AACtE,MAAM,oBAAoB,GAAG,sBAAsB,CAAC;AAEpD;;;;;;GAMG;AACH,MAAM,OAAO,0BAA2B,SAAQ,KAAK;IAGnD,YAAY,cAAsB,EAAE,OAA8B;QAChE,KAAK,CAAC,OAAO,EAAE,OAAO,IAAI,eAAe,cAAc,2BAA2B,CAAC,CAAC;QACpF,IAAI,CAAC,IAAI,GAAG,2BAA2B,CAAC;QACxC,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;IACvC,CAAC;CACF;AAED;;;;;;;;GAQG;AACH,MAAM,OAAO,wBAAyB,SAAQ,KAAK;IAKjD,YACE,cAAsB,EACtB,OAAoE;QAEpE,KAAK,CAAC,OAAO,EAAE,OAAO,IAAI,eAAe,cAAc,yBAAyB,CAAC,CAAC;QAClF,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;QACtC,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;QACrC,IAAI,CAAC,MAAM,GAAG,OAAO,EAAE,MAAM,CAAC;QAC9B,IAAI,CAAC,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,IAAI,CAAC;IAC9C,CAAC;CACF;AAED,4EAA4E;AAC5E,MAAM,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC;IACzC;;;;;OAKG;IACH,kBAAkB,EAAE,oBAAoB;IACxC,kEAAkE;IAClE,qBAAqB,EAAE,uBAAuB;IAC9C,oEAAoE;IACpE,yBAAyB,EAAE,2BAA2B;IACtD,uEAAuE;IACvE,kBAAkB,EAAE,oBAAoB;IACxC,wEAAwE;IACxE,aAAa,EAAE,eAAe;IAC9B,wEAAwE;IACxE,gBAAgB,EAAE,kBAAkB;CAC5B,CAAC,CAAC;AAEZ;;;;;GAKG;AACH,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAG3C,YAAY,OAA6D;QACvE,KAAK,CAAC,OAAO,EAAE,OAAO,IAAI,2CAA2C,CAAC,CAAC;QACvE,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;QACjC,MAAM,SAAS,GAAG,OAAO,EAAE,KAAK;YAC9B,CAAC,CAAC,iBAAiB,OAAO,CAAC,KAAK,GAAG;YACnC,CAAC,CAAC,QAAQ,CAAC;QACb,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAC3B;YACE,IAAI,EAAE,OAAO,EAAE,IAAI,IAAI,cAAc;YACrC,KAAK,EAAE,OAAO,EAAE,OAAO,IAAI,2CAA2C;YACtE,EAAE,EAAE,KAAK;SACV,EACD;YACE,MAAM,EAAE,GAAG;YACX,OAAO,EAAE,EAAE,eAAe,EAAE,UAAU,EAAE,kBAAkB,EAAE,SAAS,EAAE;SACxE,CACF,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a JWT subject token is already expired.
|
|
3
|
+
*
|
|
4
|
+
* Decode-only, no signature verification: the zone remains the authority on
|
|
5
|
+
* validity. This check exists to route an expiry to a channel sign-in instead
|
|
6
|
+
* of a consent page that cannot fix it, and to skip an exchange round trip
|
|
7
|
+
* that is guaranteed to fail. Opaque or malformed tokens, and tokens with no
|
|
8
|
+
* `exp`, return false and are left for the zone to judge.
|
|
9
|
+
*/
|
|
10
|
+
export declare function subjectTokenExpired(token: string): boolean;
|
|
11
|
+
/**
|
|
12
|
+
* The unverified claims of a JWT, or null when the value is not a JWT.
|
|
13
|
+
*
|
|
14
|
+
* Used for the expiry check above and for the issuer peek that decides whether
|
|
15
|
+
* an inbound bearer is a caller this package recognizes. Never a substitute
|
|
16
|
+
* for verification: every claim a decision depends on is re-read from the
|
|
17
|
+
* verified claims.
|
|
18
|
+
*/
|
|
19
|
+
export declare function decodeClaims(token: string): Record<string, unknown> | null;
|
|
20
|
+
//# sourceMappingURL=expiry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expiry.d.ts","sourceRoot":"","sources":["../../src/expiry.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAK1D;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAa1E"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a JWT subject token is already expired.
|
|
3
|
+
*
|
|
4
|
+
* Decode-only, no signature verification: the zone remains the authority on
|
|
5
|
+
* validity. This check exists to route an expiry to a channel sign-in instead
|
|
6
|
+
* of a consent page that cannot fix it, and to skip an exchange round trip
|
|
7
|
+
* that is guaranteed to fail. Opaque or malformed tokens, and tokens with no
|
|
8
|
+
* `exp`, return false and are left for the zone to judge.
|
|
9
|
+
*/
|
|
10
|
+
export function subjectTokenExpired(token) {
|
|
11
|
+
const claims = decodeClaims(token);
|
|
12
|
+
if (claims === null)
|
|
13
|
+
return false;
|
|
14
|
+
const exp = claims.exp;
|
|
15
|
+
return typeof exp === "number" && Number.isFinite(exp) && exp <= Date.now() / 1000;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The unverified claims of a JWT, or null when the value is not a JWT.
|
|
19
|
+
*
|
|
20
|
+
* Used for the expiry check above and for the issuer peek that decides whether
|
|
21
|
+
* an inbound bearer is a caller this package recognizes. Never a substitute
|
|
22
|
+
* for verification: every claim a decision depends on is re-read from the
|
|
23
|
+
* verified claims.
|
|
24
|
+
*/
|
|
25
|
+
export function decodeClaims(token) {
|
|
26
|
+
const parts = token.split(".");
|
|
27
|
+
if (parts.length !== 3)
|
|
28
|
+
return null;
|
|
29
|
+
let payload;
|
|
30
|
+
try {
|
|
31
|
+
payload = JSON.parse(decodeSegment(parts[1]));
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
if (typeof payload !== "object" || payload === null || Array.isArray(payload)) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
return payload;
|
|
40
|
+
}
|
|
41
|
+
/** Decode one base64url JWT segment to its UTF-8 text. */
|
|
42
|
+
function decodeSegment(segment) {
|
|
43
|
+
const base64 = segment.replace(/-/g, "+").replace(/_/g, "/");
|
|
44
|
+
const padded = base64 + "=".repeat((4 - (base64.length % 4)) % 4);
|
|
45
|
+
const binary = atob(padded);
|
|
46
|
+
const bytes = Uint8Array.from(binary, (character) => character.charCodeAt(0));
|
|
47
|
+
return new TextDecoder().decode(bytes);
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=expiry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expiry.js","sourceRoot":"","sources":["../../src/expiry.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IACnC,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAClC,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC;IACvB,OAAO,OAAO,GAAG,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AACrF,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACpC,IAAI,OAAgB,CAAC;IACrB,IAAI,CAAC;QACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC;IACjD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9E,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,OAAkC,CAAC;AAC5C,CAAC;AAED,0DAA0D;AAC1D,SAAS,aAAa,CAAC,OAAe;IACpC,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC7D,MAAM,MAAM,GAAG,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAClE,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5B,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9E,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keycard auth for eve agents.
|
|
3
|
+
*
|
|
4
|
+
* Three adapters, each plugging into an eve primitive rather than wrapping it:
|
|
5
|
+
*
|
|
6
|
+
* - {@link keycardAuth} is an `AuthFn` for a channel's ordered `auth` array.
|
|
7
|
+
* It verifies a zone-issued bearer and projects the claims onto eve's
|
|
8
|
+
* `SessionAuthContext`.
|
|
9
|
+
* - {@link Keycard.asSelf}, {@link Keycard.onBehalfOf}, and
|
|
10
|
+
* {@link Keycard.impersonate} are connection auth definitions: eve resolves
|
|
11
|
+
* the principal from the turn, calls `getToken` at the tool boundary, and
|
|
12
|
+
* attaches the bearer itself, so no credential reaches the model.
|
|
13
|
+
* - {@link Keycard.interactive} is the interactive form. eve emits
|
|
14
|
+
* `authorization.required`, parks the turn durably on its own callback, and
|
|
15
|
+
* settles it once.
|
|
16
|
+
*/
|
|
17
|
+
export { keycardAuth } from "./auth.js";
|
|
18
|
+
export type { KeycardAuthOptions, SubjectTokenRetention } from "./auth.js";
|
|
19
|
+
export { asSelf, impersonate, onBehalfOf } from "./connections.js";
|
|
20
|
+
export type { KeycardImpersonateOptions } from "./connections.js";
|
|
21
|
+
export { interactive, memoryAuthorizedTokenStore } from "./interactive.js";
|
|
22
|
+
export type { AuthorizedToken, AuthorizedTokenStore, KeycardInteractiveOptions, KeycardResumeState, WebAppFlow, } from "./interactive.js";
|
|
23
|
+
export type { KeycardConnectionOptions } from "./config.js";
|
|
24
|
+
export { AuthorizationFailedError, AuthorizationRequiredError, FailureReason, RouteRejectedError, } from "./errors.js";
|
|
25
|
+
export { decodeClaims, subjectTokenExpired } from "./expiry.js";
|
|
26
|
+
export { requireAuthOnUnauthorized } from "./requireAuth.js";
|
|
27
|
+
export type { RequireAuthContext } from "./requireAuth.js";
|
|
28
|
+
export { defaultSubjectTokenStore, memorySubjectTokenStore, SUBJECT_TOKEN_ATTRIBUTE, } from "./subjectTokens.js";
|
|
29
|
+
export type { SubjectTokenStore } from "./subjectTokens.js";
|
|
30
|
+
export { KeycardZoneClient } from "./zoneClient.js";
|
|
31
|
+
export type { ZoneClient } from "./zoneClient.js";
|
|
32
|
+
import { asSelf, impersonate, onBehalfOf } from "./connections.js";
|
|
33
|
+
import { interactive } from "./interactive.js";
|
|
34
|
+
/**
|
|
35
|
+
* The connection auth factories, grouped for the common
|
|
36
|
+
* `auth: Keycard.onBehalfOf({ ... })` call site.
|
|
37
|
+
*/
|
|
38
|
+
export declare const Keycard: Readonly<{
|
|
39
|
+
asSelf: typeof asSelf;
|
|
40
|
+
impersonate: typeof impersonate;
|
|
41
|
+
interactive: typeof interactive;
|
|
42
|
+
onBehalfOf: typeof onBehalfOf;
|
|
43
|
+
}>;
|
|
44
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keycard auth for eve agents.
|
|
3
|
+
*
|
|
4
|
+
* Three adapters, each plugging into an eve primitive rather than wrapping it:
|
|
5
|
+
*
|
|
6
|
+
* - {@link keycardAuth} is an `AuthFn` for a channel's ordered `auth` array.
|
|
7
|
+
* It verifies a zone-issued bearer and projects the claims onto eve's
|
|
8
|
+
* `SessionAuthContext`.
|
|
9
|
+
* - {@link Keycard.asSelf}, {@link Keycard.onBehalfOf}, and
|
|
10
|
+
* {@link Keycard.impersonate} are connection auth definitions: eve resolves
|
|
11
|
+
* the principal from the turn, calls `getToken` at the tool boundary, and
|
|
12
|
+
* attaches the bearer itself, so no credential reaches the model.
|
|
13
|
+
* - {@link Keycard.interactive} is the interactive form. eve emits
|
|
14
|
+
* `authorization.required`, parks the turn durably on its own callback, and
|
|
15
|
+
* settles it once.
|
|
16
|
+
*/
|
|
17
|
+
export { keycardAuth } from "./auth.js";
|
|
18
|
+
export { asSelf, impersonate, onBehalfOf } from "./connections.js";
|
|
19
|
+
export { interactive, memoryAuthorizedTokenStore } from "./interactive.js";
|
|
20
|
+
export { AuthorizationFailedError, AuthorizationRequiredError, FailureReason, RouteRejectedError, } from "./errors.js";
|
|
21
|
+
export { decodeClaims, subjectTokenExpired } from "./expiry.js";
|
|
22
|
+
export { requireAuthOnUnauthorized } from "./requireAuth.js";
|
|
23
|
+
export { defaultSubjectTokenStore, memorySubjectTokenStore, SUBJECT_TOKEN_ATTRIBUTE, } from "./subjectTokens.js";
|
|
24
|
+
export { KeycardZoneClient } from "./zoneClient.js";
|
|
25
|
+
import { asSelf, impersonate, onBehalfOf } from "./connections.js";
|
|
26
|
+
import { interactive } from "./interactive.js";
|
|
27
|
+
/**
|
|
28
|
+
* The connection auth factories, grouped for the common
|
|
29
|
+
* `auth: Keycard.onBehalfOf({ ... })` call site.
|
|
30
|
+
*/
|
|
31
|
+
export const Keycard = Object.freeze({
|
|
32
|
+
asSelf,
|
|
33
|
+
impersonate,
|
|
34
|
+
interactive,
|
|
35
|
+
onBehalfOf,
|
|
36
|
+
});
|
|
37
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +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;AAW3E,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"}
|