@substrat-run/vertical-auth 0.24.5 → 0.25.1
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/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/instance-auth.d.ts +26 -0
- package/dist/instance-auth.d.ts.map +1 -1
- package/dist/instance-auth.js +25 -0
- package/dist/instance-auth.js.map +1 -1
- package/dist/oidc-rp-provider.d.ts +7 -0
- package/dist/oidc-rp-provider.d.ts.map +1 -1
- package/dist/oidc-rp-provider.js +23 -7
- package/dist/oidc-rp-provider.js.map +1 -1
- package/dist/oidc.d.ts +31 -0
- package/dist/oidc.d.ts.map +1 -1
- package/dist/oidc.js +165 -10
- package/dist/oidc.js.map +1 -1
- package/dist/provider.d.ts +27 -1
- package/dist/provider.d.ts.map +1 -1
- package/package.json +6 -6
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
export type { AuthProvider, AuthSubject } from './provider.js';
|
|
2
|
-
export { oidcAuthProvider, type OidcConfig } from './oidc.js';
|
|
1
|
+
export type { AuthProvider, AuthSubject, ResolveOptions } from './provider.js';
|
|
2
|
+
export { oidcAuthProvider, type DelegationOption, type OidcConfig } from './oidc.js';
|
|
3
3
|
export { oidcRpAuthProvider, type OidcRpConfig } from './oidc-rp-provider.js';
|
|
4
4
|
export { IdentityDO, doAuthProvider, type IdentityDoEnv, type IdentityStub } from './identity-do.js';
|
|
5
5
|
export { resolveCookieDomain } from './cookie-domain.js';
|
|
6
6
|
export { FIRST_SIGN_IN_WINDOW_MS, OWNER_CLAIM_TTL_MS, type OwnerSeat, type OwnerTransfer } from './owner-seat.js';
|
|
7
7
|
export { OWNER_CLAIM_LABEL, UNATTRIBUTED_PLATFORM_ACTOR, invitePath, mintOwnerClaimLink, ownerClaimPath, sha256Hex, type OwnerClaimMintDirectory, type OwnerClaimMintHost, } from './owner-claim-link.js';
|
|
8
|
-
export { AUTH_CONFIG_KEY, AuthConfigError, authChoice, authorizationServersOf, instanceAuthFor, parseAuthChoice, selectAuthProvider, type AuthChoice, type InstanceAuth, } from './instance-auth.js';
|
|
8
|
+
export { AUTH_CONFIG_KEY, AuthConfigError, authChoice, authorizationServersOf, instanceAuthFor, parseAuthChoice, selectAuthProvider, type AuthChoice, type DelegationWiring, type InstanceAuth, type InstanceDelegation, } from './instance-auth.js';
|
|
9
9
|
export { observePlace, placesReporter, reportScopeMembers, resetPlacesMemo, unbindMember, type PlaceReportResult, type PlacesReporter, } from './places.js';
|
|
10
10
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC/
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,KAAK,gBAAgB,EAAE,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AACrF,OAAO,EAAE,kBAAkB,EAAE,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrG,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,KAAK,SAAS,EAAE,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAClH,OAAO,EACL,iBAAiB,EACjB,2BAA2B,EAC3B,UAAU,EACV,kBAAkB,EAClB,cAAc,EACd,SAAS,EACT,KAAK,uBAAuB,EAC5B,KAAK,kBAAkB,GACxB,MAAM,uBAAuB,CAAC;AAO/B,OAAO,EACL,eAAe,EACf,eAAe,EACf,UAAU,EACV,sBAAsB,EACtB,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,KAAK,UAAU,EACf,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,kBAAkB,GACxB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,YAAY,EACZ,cAAc,EACd,kBAAkB,EAClB,eAAe,EACf,YAAY,EACZ,KAAK,iBAAiB,EACtB,KAAK,cAAc,GACpB,MAAM,aAAa,CAAC"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAA0C,MAAM,WAAW,CAAC;AACrF,OAAO,EAAE,kBAAkB,EAAqB,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAE,UAAU,EAAE,cAAc,EAAyC,MAAM,kBAAkB,CAAC;AACrG,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,uBAAuB,EAAE,kBAAkB,EAAsC,MAAM,iBAAiB,CAAC;AAClH,OAAO,EACL,iBAAiB,EACjB,2BAA2B,EAC3B,UAAU,EACV,kBAAkB,EAClB,cAAc,EACd,SAAS,GAGV,MAAM,uBAAuB,CAAC;AAC/B,4IAA4I;AAC5I,kFAAkF;AAClF,wFAAwF;AACxF,yFAAyF;AACzF,yFAAyF;AACzF,gCAAgC;AAChC,OAAO,EACL,eAAe,EACf,eAAe,EACf,UAAU,EACV,sBAAsB,EACtB,eAAe,EACf,eAAe,EACf,kBAAkB,GAKnB,MAAM,oBAAoB,CAAC;AAC5B,yFAAyF;AACzF,OAAO,EACL,YAAY,EACZ,cAAc,EACd,kBAAkB,EAClB,eAAe,EACf,YAAY,GAGb,MAAM,aAAa,CAAC"}
|
package/dist/instance-auth.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z, type EnvVarSpec } from '@substrat-run/contracts';
|
|
2
|
+
import { type DelegationOption } from './oidc.js';
|
|
2
3
|
import type { IdentityStub } from './identity-do.js';
|
|
3
4
|
import type { AuthProvider } from './provider.js';
|
|
4
5
|
/**
|
|
@@ -77,7 +78,26 @@ export declare function instanceAuthFor(opts: {
|
|
|
77
78
|
envSpec: EnvVarSpec[];
|
|
78
79
|
/** The worker's own environment — the binding layer under the delivered map. */
|
|
79
80
|
env: Record<string, unknown>;
|
|
81
|
+
/** Accept delegated bearers from these actors (#1824) — see `InstanceDelegation`. */
|
|
82
|
+
delegation?: InstanceDelegation;
|
|
80
83
|
}): Promise<InstanceAuth>;
|
|
84
|
+
/** What a delegation's actor list may be read from (#1824): this scope's delivered configuration. */
|
|
85
|
+
export interface DelegationWiring {
|
|
86
|
+
/** The parsed `substrat:auth` choice, or null — the issuer the actors' client ids belong to. */
|
|
87
|
+
readonly identity: AuthChoice | null;
|
|
88
|
+
/** The whole delivered map. */
|
|
89
|
+
readonly config: Readonly<Record<string, string>>;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* The delegation opt-in a vertical hands `instanceAuthFor` (#1824). An actor's client id is
|
|
93
|
+
* per team auth server, so one serving script answering many installs has no single list:
|
|
94
|
+
* `actors` may instead be read from each install's delivered wiring, as a function.
|
|
95
|
+
*/
|
|
96
|
+
export interface InstanceDelegation {
|
|
97
|
+
actors: readonly string[] | ((wiring: DelegationWiring) => readonly string[]);
|
|
98
|
+
/** See `DelegationOption.maxLifetimeSeconds`. */
|
|
99
|
+
maxLifetimeSeconds?: number;
|
|
100
|
+
}
|
|
81
101
|
/** The delivered `substrat:auth` entry, parsed leniently: anything unusable is null. */
|
|
82
102
|
export declare function parseAuthChoice(raw: string | undefined): AuthChoice | null;
|
|
83
103
|
/**
|
|
@@ -126,6 +146,12 @@ export declare function selectAuthProvider(opts: {
|
|
|
126
146
|
* choice only — the deployment default's issuer is the operator's own.
|
|
127
147
|
*/
|
|
128
148
|
sharedIssuer?: boolean;
|
|
149
|
+
/**
|
|
150
|
+
* Accept delegated bearers from these actors at this app's MCP endpoint (#1824). Applies to
|
|
151
|
+
* the delivered choice on a shared issuer only: a team auth server is the issuer that mints
|
|
152
|
+
* them. Absent, every bearer carrying `act` is refused.
|
|
153
|
+
*/
|
|
154
|
+
delegation?: DelegationOption;
|
|
129
155
|
platformBaseDomains?: readonly string[];
|
|
130
156
|
}): AuthProvider;
|
|
131
157
|
//# sourceMappingURL=instance-auth.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instance-auth.d.ts","sourceRoot":"","sources":["../src/instance-auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4E,CAAC,EAAE,KAAK,UAAU,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"instance-auth.d.ts","sourceRoot":"","sources":["../src/instance-auth.ts"],"names":[],"mappings":"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"}
|
package/dist/instance-auth.js
CHANGED
|
@@ -72,10 +72,34 @@ export async function instanceAuthFor(opts) {
|
|
|
72
72
|
sessionSecret: wiring.sessionSecret,
|
|
73
73
|
settings,
|
|
74
74
|
sharedIssuer: wiring.config[SHARED_ISSUER_CONFIG_KEY] === 'true',
|
|
75
|
+
...(opts.delegation ? { delegation: resolveDelegation(opts.delegation, { identity, config: wiring.config }) } : {}),
|
|
75
76
|
platformBaseDomains: parsePlatformBaseDomains(typeof opts.env.PLATFORM_BASE_DOMAINS === 'string' ? opts.env.PLATFORM_BASE_DOMAINS : undefined),
|
|
76
77
|
}),
|
|
77
78
|
};
|
|
78
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* The verifier's `DelegationOption` for this install. Fails CLOSED: a resolver that throws,
|
|
82
|
+
* or answers anything but a list of non-empty strings, yields no actors, which admits no
|
|
83
|
+
* delegated token — and leaves every other sign-in as it was.
|
|
84
|
+
*/
|
|
85
|
+
function resolveDelegation(delegation, wiring) {
|
|
86
|
+
let actors;
|
|
87
|
+
try {
|
|
88
|
+
actors = typeof delegation.actors === 'function' ? delegation.actors(wiring) : delegation.actors;
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
// The error's name only: its message may quote the delivered configuration it was reading.
|
|
92
|
+
console.warn('vertical-auth: delegation.actors threw, so no delegated bearer is admitted', {
|
|
93
|
+
error: err instanceof Error ? err.name : typeof err,
|
|
94
|
+
});
|
|
95
|
+
actors = [];
|
|
96
|
+
}
|
|
97
|
+
const listed = Array.isArray(actors) && actors.every((a) => typeof a === 'string' && a.length > 0);
|
|
98
|
+
return {
|
|
99
|
+
actors: listed ? [...actors] : [],
|
|
100
|
+
...(delegation.maxLifetimeSeconds === undefined ? {} : { maxLifetimeSeconds: delegation.maxLifetimeSeconds }),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
79
103
|
/** The delivered `substrat:auth` entry, parsed leniently: anything unusable is null. */
|
|
80
104
|
export function parseAuthChoice(raw) {
|
|
81
105
|
if (!raw)
|
|
@@ -152,6 +176,7 @@ export function selectAuthProvider(opts) {
|
|
|
152
176
|
...(identity.audience ? { audience: identity.audience } : {}),
|
|
153
177
|
...(identity.cookieDomain ? { cookieDomain: identity.cookieDomain } : {}),
|
|
154
178
|
...(opts.sharedIssuer ? { sharedIssuer: true } : {}),
|
|
179
|
+
...(opts.delegation ? { delegation: opts.delegation } : {}),
|
|
155
180
|
platformBaseDomains: opts.platformBaseDomains,
|
|
156
181
|
});
|
|
157
182
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instance-auth.js","sourceRoot":"","sources":["../src/instance-auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,oBAAoB,EAAE,CAAC,EAAmB,MAAM,yBAAyB,CAAC;AACvI,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,gBAAgB,
|
|
1
|
+
{"version":3,"file":"instance-auth.js","sourceRoot":"","sources":["../src/instance-auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AuthProvider } from './provider.js';
|
|
2
|
+
import { type DelegationOption } from './oidc.js';
|
|
2
3
|
/**
|
|
3
4
|
* Standard OIDC as a full RELYING PARTY `AuthProvider` — the browser-login counterpart
|
|
4
5
|
* of `oidcAuthProvider` (which only verifies presented bearer tokens). `handle` owns the
|
|
@@ -30,6 +31,12 @@ export interface OidcRpConfig {
|
|
|
30
31
|
* issuer happened to sign. Unset, the bearer path is exactly what it was.
|
|
31
32
|
*/
|
|
32
33
|
sharedIssuer?: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Accept delegated bearers from these actors at this app's MCP endpoint (#1824) — see
|
|
36
|
+
* `OidcConfig.delegation`. Takes effect only with `sharedIssuer`: a team auth server is the
|
|
37
|
+
* issuer that mints them. Absent, a bearer carrying `act` is refused.
|
|
38
|
+
*/
|
|
39
|
+
delegation?: DelegationOption;
|
|
33
40
|
/**
|
|
34
41
|
* Share the login across every surface under this parent domain (`acme.se` covers
|
|
35
42
|
* `crm.` and `eka.` alike) — the session cookie is set with `Domain=…` instead of
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oidc-rp-provider.d.ts","sourceRoot":"","sources":["../src/oidc-rp-provider.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"oidc-rp-provider.d.ts","sourceRoot":"","sources":["../src/oidc-rp-provider.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,YAAY,EAA+B,MAAM,eAAe,CAAC;AAC/E,OAAO,EAAoB,KAAK,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAGpE;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,YAAY;IAC3B,iFAAiF;IACjF,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,0FAA0F;IAC1F,aAAa,EAAE,MAAM,CAAC;IACtB,gGAAgG;IAChG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;OAIG;IACH,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,mBAAmB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACzC;AA0HD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,YAAY,GAAG,YAAY,CAqHlE"}
|
package/dist/oidc-rp-provider.js
CHANGED
|
@@ -74,21 +74,36 @@ function redirectWith(location, cookies) {
|
|
|
74
74
|
headers.append('set-cookie', c);
|
|
75
75
|
return new Response(null, { status: 302, headers });
|
|
76
76
|
}
|
|
77
|
-
// Bearer verifiers cached per issuer+audience(+own client, on a shared issuer)
|
|
78
|
-
// fetch survives across requests in an isolate even though the provider object
|
|
79
|
-
// per-request. The client is part of the key because two apps on one team
|
|
80
|
-
// share an issuer and must never share a verifier that admits the other's
|
|
77
|
+
// Bearer verifiers cached per issuer+audience(+own client, on a shared issuer)(+delegation)
|
|
78
|
+
// so the JWKS fetch survives across requests in an isolate even though the provider object
|
|
79
|
+
// itself is per-request. The client is part of the key because two apps on one team
|
|
80
|
+
// auth-server share an issuer and must never share a verifier that admits the other's
|
|
81
|
+
// tokens; the delegation is, because a verifier built with it admits tokens one built
|
|
82
|
+
// without it refuses (#1824).
|
|
81
83
|
const bearerCache = new Map();
|
|
82
84
|
function bearerVerifier(cfg) {
|
|
83
85
|
// A delivered `audience` still wins over it; `oidcAuthProvider` is where that is decided.
|
|
84
86
|
const own = cfg.sharedIssuer ? cfg.clientId : undefined;
|
|
85
|
-
const
|
|
87
|
+
const delegation = cfg.delegation
|
|
88
|
+
? {
|
|
89
|
+
actors: [...cfg.delegation.actors],
|
|
90
|
+
...(cfg.delegation.maxLifetimeSeconds === undefined ? {} : { maxLifetimeSeconds: cfg.delegation.maxLifetimeSeconds }),
|
|
91
|
+
}
|
|
92
|
+
: undefined;
|
|
93
|
+
const key = JSON.stringify([
|
|
94
|
+
cfg.issuer,
|
|
95
|
+
cfg.audience ?? '',
|
|
96
|
+
own ?? '',
|
|
97
|
+
// NaN would stringify as null and collide with "no bound", so the bound is keyed as text.
|
|
98
|
+
delegation ? [[...delegation.actors].sort(), String(delegation.maxLifetimeSeconds)] : null,
|
|
99
|
+
]);
|
|
86
100
|
let p = bearerCache.get(key);
|
|
87
101
|
if (!p) {
|
|
88
102
|
p = oidcAuthProvider({
|
|
89
103
|
issuer: cfg.issuer,
|
|
90
104
|
...(cfg.audience ? { audience: cfg.audience } : {}),
|
|
91
105
|
...(own ? { clientId: own, resourceOf: (origin) => mcpResourceOf(origin) } : {}),
|
|
106
|
+
...(delegation ? { delegation } : {}),
|
|
92
107
|
});
|
|
93
108
|
bearerCache.set(key, p);
|
|
94
109
|
}
|
|
@@ -181,7 +196,7 @@ export function oidcRpAuthProvider(cfg) {
|
|
|
181
196
|
// here — accounts live at the issuer. JSON, never a fall-through to the SPA.
|
|
182
197
|
return Response.json({ error: 'this instance authenticates at its OIDC issuer', issuer: cfg.issuer }, { status: 404 });
|
|
183
198
|
}
|
|
184
|
-
async function resolve(headers, url) {
|
|
199
|
+
async function resolve(headers, url, options) {
|
|
185
200
|
const envelope = await verifySessionEnvelope(env, readCookie(headers.get('cookie'), SESSION_COOKIE));
|
|
186
201
|
if (envelope) {
|
|
187
202
|
const session = envelope.user;
|
|
@@ -197,7 +212,8 @@ export function oidcRpAuthProvider(cfg) {
|
|
|
197
212
|
}
|
|
198
213
|
// No cookie session — an API client presenting the issuer's own token directly. On a
|
|
199
214
|
// shared issuer it must be one minted for THIS app (#1683); `url` names our resource.
|
|
200
|
-
|
|
215
|
+
// `options` carries the MCP endpoint's channel, which only a bearer can use (#1824).
|
|
216
|
+
return bearerVerifier(cfg).resolve(headers, url, options);
|
|
201
217
|
}
|
|
202
218
|
return { handle, resolve };
|
|
203
219
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oidc-rp-provider.js","sourceRoot":"","sources":["../src/oidc-rp-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,aAAa,EACb,eAAe,EACf,qBAAqB,EACrB,UAAU,EACV,QAAQ,EACR,cAAc,EACd,WAAW,EACX,kBAAkB,EAClB,WAAW,EACX,eAAe,EACf,oBAAoB,EACpB,oBAAoB,EACpB,cAAc,EACd,WAAW,GAEZ,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAExD,OAAO,EAAE,gBAAgB,
|
|
1
|
+
{"version":3,"file":"oidc-rp-provider.js","sourceRoot":"","sources":["../src/oidc-rp-provider.ts"],"names":[],"mappings":"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"}
|
package/dist/oidc.d.ts
CHANGED
|
@@ -33,10 +33,41 @@ export interface OidcConfig {
|
|
|
33
33
|
* this app's own too.
|
|
34
34
|
*/
|
|
35
35
|
resourceOf?: (origin: string) => string;
|
|
36
|
+
/**
|
|
37
|
+
* Accept DELEGATED tokens (#1824, RFC 8693 `act`) for this app's MCP endpoint, from these
|
|
38
|
+
* actors only. Absent, every token carrying `act` is refused, whatever else it says: a
|
|
39
|
+
* host that has not opted in must never take another app's call for the user's own. Needs
|
|
40
|
+
* `resourceOf` (a shared issuer), and admits a delegated token only through the MCP
|
|
41
|
+
* endpoint's channel (`ResolveOptions.delegated`) — see `delegationOf`.
|
|
42
|
+
*/
|
|
43
|
+
delegation?: DelegationOption;
|
|
36
44
|
/** Override the JWKS URI (skip discovery) — e.g. a self-hosted issuer. */
|
|
37
45
|
jwksUri?: string;
|
|
38
46
|
/** Inject the key resolver directly — tests / a static JWKS. Defaults to the issuer's remote JWKS. */
|
|
39
47
|
keys?: JWTVerifyGetKey;
|
|
40
48
|
}
|
|
49
|
+
/** Which apps this one lets act for its users (#1824). */
|
|
50
|
+
export interface DelegationOption {
|
|
51
|
+
/**
|
|
52
|
+
* The actors' client ids at the issuer — the `sub` of a delegated token's `act`, and its
|
|
53
|
+
* authorized party. An empty list admits nobody.
|
|
54
|
+
*/
|
|
55
|
+
actors: readonly string[];
|
|
56
|
+
/**
|
|
57
|
+
* The longest lifetime (`exp − iat`, in seconds) a delegated token may have. It can only
|
|
58
|
+
* be LOWERED: anything above `DELEGATED_TOKEN_MAX_LIFETIME_SECONDS` counts as that, and a
|
|
59
|
+
* value that is not a positive number admits no token at all.
|
|
60
|
+
*/
|
|
61
|
+
maxLifetimeSeconds?: number;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* The longest a delegated token may live, in seconds: the lifetime the team auth-server's
|
|
65
|
+
* exchange mints (`EXCHANGED_TOKEN_TTL_SECONDS` in `demos/auth-server/src/token-exchange.ts`
|
|
66
|
+
* — keep the two equal). A delegated token is re-minted, never refreshed, so a longer one is
|
|
67
|
+
* not one this platform issued.
|
|
68
|
+
*/
|
|
69
|
+
export declare const DELEGATED_TOKEN_MAX_LIFETIME_SECONDS = 300;
|
|
70
|
+
/** How far ahead of this clock a delegated token's `iat` may be, in seconds. */
|
|
71
|
+
export declare const DELEGATED_TOKEN_CLOCK_SKEW_SECONDS = 30;
|
|
41
72
|
export declare function oidcAuthProvider(cfg: OidcConfig): AuthProvider;
|
|
42
73
|
//# sourceMappingURL=oidc.d.ts.map
|
package/dist/oidc.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oidc.d.ts","sourceRoot":"","sources":["../src/oidc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkD,KAAK,eAAe,EAAE,MAAM,MAAM,CAAC;AAE5F,OAAO,KAAK,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"oidc.d.ts","sourceRoot":"","sources":["../src/oidc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkD,KAAK,eAAe,EAAE,MAAM,MAAM,CAAC;AAE5F,OAAO,KAAK,EAAE,YAAY,EAA+B,MAAM,eAAe,CAAC;AAE/E;;;;;;;;;GASG;AACH,MAAM,WAAW,UAAU;IACzB;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,sEAAsE;IACtE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;IACxC;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,0EAA0E;IAC1E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sGAAsG;IACtG,IAAI,CAAC,EAAE,eAAe,CAAC;CACxB;AAED,0DAA0D;AAC1D,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;GAKG;AACH,eAAO,MAAM,oCAAoC,MAAM,CAAC;AAExD,gFAAgF;AAChF,eAAO,MAAM,kCAAkC,KAAK,CAAC;AAiMrD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,UAAU,GAAG,YAAY,CA4G9D"}
|
package/dist/oidc.js
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import { jwtVerify, createRemoteJWKSet } from 'jose';
|
|
2
2
|
import { discoverIssuer, isAllowedEndpoint, issuerRefusal } from '@substrat-run/oidc-rp/discovery';
|
|
3
|
+
/**
|
|
4
|
+
* The longest a delegated token may live, in seconds: the lifetime the team auth-server's
|
|
5
|
+
* exchange mints (`EXCHANGED_TOKEN_TTL_SECONDS` in `demos/auth-server/src/token-exchange.ts`
|
|
6
|
+
* — keep the two equal). A delegated token is re-minted, never refreshed, so a longer one is
|
|
7
|
+
* not one this platform issued.
|
|
8
|
+
*/
|
|
9
|
+
export const DELEGATED_TOKEN_MAX_LIFETIME_SECONDS = 300;
|
|
10
|
+
/** How far ahead of this clock a delegated token's `iat` may be, in seconds. */
|
|
11
|
+
export const DELEGATED_TOKEN_CLOCK_SKEW_SECONDS = 30;
|
|
3
12
|
function bearerFrom(headers) {
|
|
4
13
|
const auth = headers.get('authorization');
|
|
5
14
|
if (auth?.toLowerCase().startsWith('bearer '))
|
|
@@ -46,26 +55,150 @@ function ownResources(headers, url, resourceOf) {
|
|
|
46
55
|
*
|
|
47
56
|
* 1. **`aud` names this app's own MCP resource.** An access token for this app's
|
|
48
57
|
* endpoint. Its `azp` is the MCP *client's* id, never ours, so this has to come first.
|
|
49
|
-
* 2. **An authorized party that is us
|
|
50
|
-
*
|
|
51
|
-
* whatever its `aud`. When one is present
|
|
52
|
-
* refused, even with our id in `aud` (OIDC
|
|
58
|
+
* 2. **An authorized party that is us** — unless `aud` names ANOTHER app's MCP resource.
|
|
59
|
+
* When `azp` or `client_id` is present, every one present must equal our client id —
|
|
60
|
+
* and then the token was issued to our client, whatever its `aud`. When one is present
|
|
61
|
+
* and is someone else, that is the answer: refused, even with our id in `aud` (OIDC
|
|
62
|
+
* Core §3.1.3.7, item 5). The exception (#1824): a token for another app's MCP endpoint
|
|
63
|
+
* is that endpoint's, even when our client is the one it was issued to — as the MCP
|
|
64
|
+
* client, or as the actor of a delegation — so it is refused here, where it would
|
|
65
|
+
* otherwise stand for the user at our own API with no limit on what it may do.
|
|
53
66
|
* 3. **No authorized party, and `aud` is exactly our client id.** Our own `id_token`:
|
|
54
67
|
* Better Auth, like most issuers, puts no `azp` on one. A multi-valued `aud` with no
|
|
55
68
|
* `azp` is refused — OIDC Core asks for `azp` exactly then, and without it nothing
|
|
56
69
|
* says which of the audiences the token was handed to.
|
|
57
70
|
*
|
|
58
71
|
* Everything else is refused, a token with neither `aud` nor an authorized party included.
|
|
72
|
+
* A token carrying `act` never reaches this: it is a delegation, judged by `delegationOf`.
|
|
59
73
|
*/
|
|
60
|
-
function isOwnToken(payload, clientId, resources) {
|
|
74
|
+
function isOwnToken(payload, clientId, resources, resourceOf) {
|
|
61
75
|
const aud = typeof payload.aud === 'string' ? [payload.aud] : Array.isArray(payload.aud) ? payload.aud : [];
|
|
62
76
|
if (resources.some((r) => aud.includes(r)))
|
|
63
77
|
return true;
|
|
78
|
+
if (resourceOf && aud.some((a) => isMcpResource(a, resourceOf)))
|
|
79
|
+
return false;
|
|
64
80
|
const parties = [payload['azp'], payload['client_id']].filter((v) => typeof v === 'string');
|
|
65
81
|
if (parties.length > 0)
|
|
66
82
|
return parties.every((p) => p === clientId);
|
|
67
83
|
return aud.length === 1 && aud[0] === clientId;
|
|
68
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* Whether `value` is the MCP resource identifier of SOME origin — `resourceOf`'s spelling,
|
|
87
|
+
* which is every `aud` the issuer mints for an endpoint the platform registered. A client id
|
|
88
|
+
* or a userinfo URL is not one.
|
|
89
|
+
*
|
|
90
|
+
* Compared loosely, because this only ever REFUSES (rule 2's exception): the origin as `URL`
|
|
91
|
+
* normalises it (host case, default port), the path percent-decoded, lower-cased, with
|
|
92
|
+
* repeated and trailing slashes dropped. A resource an operator registered by hand at
|
|
93
|
+
* another path is not recognised, since nothing here knows its spelling.
|
|
94
|
+
*/
|
|
95
|
+
function isMcpResource(value, resourceOf) {
|
|
96
|
+
try {
|
|
97
|
+
const url = new URL(value);
|
|
98
|
+
return comparablePath(url.pathname) === comparablePath(new URL(resourceOf(url.origin)).pathname);
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/** A URL path as `isMcpResource` compares it. */
|
|
105
|
+
function comparablePath(pathname) {
|
|
106
|
+
let path = pathname;
|
|
107
|
+
try {
|
|
108
|
+
path = decodeURIComponent(path);
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
// A malformed escape is compared as written.
|
|
112
|
+
}
|
|
113
|
+
return path.toLowerCase().replace(/\/{2,}/g, '/').replace(/\/+$/, '') || '/';
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* The delegation a token carrying `act` stands for, or null when it is not one this app
|
|
117
|
+
* takes (#1824). The shape is what the team auth-server's second exchange mints
|
|
118
|
+
* (`demos/auth-server/src/token-exchange.ts`): the user as `sub`, the actor's client as
|
|
119
|
+
* `act.sub` and as the authorized party, one MCP resource as `aud`, and the delegated
|
|
120
|
+
* permission keys as `scope`.
|
|
121
|
+
*
|
|
122
|
+
* Every condition is required, and each refuses on its own:
|
|
123
|
+
*
|
|
124
|
+
* - **The host opted in** (`cfg.delegation`) **and names this actor.** Without the option
|
|
125
|
+
* nothing with `act` is admitted, so a host that has not upgraded is never exposed.
|
|
126
|
+
* - **One actor, of this issuer.** `act` is an object whose `iss` is the token's own and
|
|
127
|
+
* whose `sub` is a string, with no nested `act`: a chain of actors is not something any
|
|
128
|
+
* exchange here mints, and nothing reads past the first.
|
|
129
|
+
* - **Issued to that actor.** Every present `azp` / `client_id` equals `act.sub`, and at
|
|
130
|
+
* least one is present.
|
|
131
|
+
* - **Through the MCP endpoint's own channel.** The caller passed `options.delegated` — the
|
|
132
|
+
* resource `mcpChannelOf(c)` reports, which only the MCP mount's own handler can see —
|
|
133
|
+
* `aud` is exactly one value equal to it, and that resource is on the request's own
|
|
134
|
+
* origin. Unlike a user's MCP token (`isOwnToken` rule 1, which any route admits), a
|
|
135
|
+
* delegated token stands for the user only where a ceiling is applied to it, so a caller
|
|
136
|
+
* that passes no channel — every REST route, a stray handler, an older vertical-host that
|
|
137
|
+
* has none — never admits one. The resource is the channel's, not a spelling assumed
|
|
138
|
+
* here, so an endpoint mounted at another base path is judged by its own.
|
|
139
|
+
* - **A scope, and a short life.** `scope` is a non-empty space-separated list (the grammar
|
|
140
|
+
* the exchange writes, RFC 6749 §3.3). `iat` and `exp` are both present, `exp − iat` is
|
|
141
|
+
* at most the bound (`maxLifetimeSeconds`, never above the exchange's own lifetime), and
|
|
142
|
+
* `iat` is not later than `DELEGATED_TOKEN_CLOCK_SKEW_SECONDS` ahead of this clock — so no
|
|
143
|
+
* delegated token stays usable past a few minutes from now. `jwtVerify` has already
|
|
144
|
+
* refused a token whose `exp` has passed.
|
|
145
|
+
*/
|
|
146
|
+
function delegationOf(payload, delegation, channel, url, nowSeconds) {
|
|
147
|
+
const act = payload['act'];
|
|
148
|
+
if (act === null || typeof act !== 'object' || Array.isArray(act))
|
|
149
|
+
return null;
|
|
150
|
+
const { iss, sub: actor, act: prior } = act;
|
|
151
|
+
if (prior !== undefined || iss !== payload.iss)
|
|
152
|
+
return null;
|
|
153
|
+
if (typeof actor !== 'string' || !delegation.actors.includes(actor))
|
|
154
|
+
return null;
|
|
155
|
+
const parties = [payload['azp'], payload['client_id']].filter((p) => p !== undefined);
|
|
156
|
+
if (parties.length === 0 || !parties.every((p) => p === actor))
|
|
157
|
+
return null;
|
|
158
|
+
const aud = typeof payload.aud === 'string' ? payload.aud : Array.isArray(payload.aud) && payload.aud.length === 1 ? payload.aud[0] : null;
|
|
159
|
+
const resource = channel?.resource;
|
|
160
|
+
if (!aud || typeof resource !== 'string' || aud !== resource || !url)
|
|
161
|
+
return null;
|
|
162
|
+
try {
|
|
163
|
+
if (new URL(resource).origin !== new URL(url).origin)
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
const { exp, iat } = payload;
|
|
170
|
+
if (typeof exp !== 'number' || typeof iat !== 'number')
|
|
171
|
+
return null;
|
|
172
|
+
const asked = delegation.maxLifetimeSeconds;
|
|
173
|
+
const bound = asked === undefined ? DELEGATED_TOKEN_MAX_LIFETIME_SECONDS : Math.min(asked, DELEGATED_TOKEN_MAX_LIFETIME_SECONDS);
|
|
174
|
+
// Written as "not within", so a bound that is not a number (NaN) admits nothing.
|
|
175
|
+
if (!(bound > 0 && exp - iat <= bound))
|
|
176
|
+
return null;
|
|
177
|
+
if (!(iat <= nowSeconds + DELEGATED_TOKEN_CLOCK_SKEW_SECONDS))
|
|
178
|
+
return null;
|
|
179
|
+
const scope = typeof payload['scope'] === 'string' ? [...new Set(payload['scope'].split(' ').filter((s) => s.length > 0))] : [];
|
|
180
|
+
if (scope.length === 0)
|
|
181
|
+
return null;
|
|
182
|
+
return { actor, scope };
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* A delivered `audience` holds every bearer to it, a delegated one included: `jwtVerify`
|
|
186
|
+
* refuses a token whose `aud` does not name it before `delegationOf` runs, and a delegated
|
|
187
|
+
* token's one `aud` must be the channel's resource. So at an MCP endpoint whose resource is
|
|
188
|
+
* not the audience, the opt-in is off. That fails closed, and would be silent without this
|
|
189
|
+
* line. Once per isolate for each issuer and audience; it names the field, never the value,
|
|
190
|
+
* like the actor resolver's warning, since the value is delivered configuration.
|
|
191
|
+
*/
|
|
192
|
+
const audienceWarned = new Set();
|
|
193
|
+
function warnAudienceRefusesDelegation(issuer, audience) {
|
|
194
|
+
const key = JSON.stringify([issuer, audience]);
|
|
195
|
+
if (audienceWarned.has(key))
|
|
196
|
+
return;
|
|
197
|
+
audienceWarned.add(key);
|
|
198
|
+
console.warn("vertical-auth: the delivered audience is not this MCP endpoint's resource, so no delegated bearer is admitted here", {
|
|
199
|
+
field: 'audience',
|
|
200
|
+
});
|
|
201
|
+
}
|
|
69
202
|
export function oidcAuthProvider(cfg) {
|
|
70
203
|
let keysPromise;
|
|
71
204
|
const getKeys = async () => {
|
|
@@ -96,7 +229,11 @@ export function oidcAuthProvider(cfg) {
|
|
|
96
229
|
}
|
|
97
230
|
return keysPromise;
|
|
98
231
|
};
|
|
99
|
-
async function verify(token, headers, url) {
|
|
232
|
+
async function verify(token, headers, url, options) {
|
|
233
|
+
const channel = options?.delegated?.resource;
|
|
234
|
+
if (cfg.delegation && cfg.resourceOf && cfg.audience && typeof channel === 'string' && channel !== cfg.audience) {
|
|
235
|
+
warnAudienceRefusesDelegation(cfg.issuer, cfg.audience);
|
|
236
|
+
}
|
|
100
237
|
try {
|
|
101
238
|
const { payload } = await jwtVerify(token, await getKeys(), {
|
|
102
239
|
issuer: cfg.issuer,
|
|
@@ -104,9 +241,26 @@ export function oidcAuthProvider(cfg) {
|
|
|
104
241
|
});
|
|
105
242
|
if (!payload.sub)
|
|
106
243
|
return null;
|
|
107
|
-
|
|
244
|
+
// A delegation ASSERTION — the first step of the exchange, which a `substrat_delegation`
|
|
245
|
+
// claim with no `act` marks — is a bearer at no app, on every configuration: it is a
|
|
246
|
+
// credential for the exchange, and only the exchange takes it. `may_act` alone decides
|
|
247
|
+
// nothing here: RFC 8693 §4.4 lets any issuer put it on an ordinary subject token.
|
|
248
|
+
if (payload['substrat_delegation'] !== undefined && payload['act'] === undefined)
|
|
249
|
+
return null;
|
|
250
|
+
// A token carrying `act` is a delegation, on every configuration: admitted only through
|
|
251
|
+
// the opt-in, and never by the rules below, which would take it as the user's own.
|
|
252
|
+
let delegation;
|
|
253
|
+
if (payload['act'] !== undefined) {
|
|
254
|
+
// Host code, so the real clock is right here (jose reads the same one for `exp`).
|
|
255
|
+
const now = Math.floor(Date.now() / 1000);
|
|
256
|
+
const admitted = cfg.delegation && cfg.resourceOf ? delegationOf(payload, cfg.delegation, options?.delegated, url, now) : null;
|
|
257
|
+
if (!admitted)
|
|
258
|
+
return null;
|
|
259
|
+
delegation = admitted;
|
|
260
|
+
}
|
|
261
|
+
else if (!cfg.audience && cfg.clientId) {
|
|
108
262
|
const resources = cfg.resourceOf ? ownResources(headers, url, cfg.resourceOf) : [];
|
|
109
|
-
if (!isOwnToken(payload, cfg.clientId, resources))
|
|
263
|
+
if (!isOwnToken(payload, cfg.clientId, resources, cfg.resourceOf))
|
|
110
264
|
return null;
|
|
111
265
|
}
|
|
112
266
|
const meta = payload;
|
|
@@ -133,6 +287,7 @@ export function oidcAuthProvider(cfg) {
|
|
|
133
287
|
? (meta['user_metadata'].name)
|
|
134
288
|
: null,
|
|
135
289
|
...(typeof payload.exp === 'number' ? { expiresAt: new Date(payload.exp * 1000).toISOString() } : {}),
|
|
290
|
+
...(delegation ? { delegation } : {}),
|
|
136
291
|
};
|
|
137
292
|
}
|
|
138
293
|
catch {
|
|
@@ -147,9 +302,9 @@ export function oidcAuthProvider(cfg) {
|
|
|
147
302
|
note: 'authenticate at the issuer, then present the token as `Authorization: Bearer`',
|
|
148
303
|
});
|
|
149
304
|
},
|
|
150
|
-
async resolve(headers, url) {
|
|
305
|
+
async resolve(headers, url, options) {
|
|
151
306
|
const token = bearerFrom(headers);
|
|
152
|
-
return token ? verify(token, headers, url) : null;
|
|
307
|
+
return token ? verify(token, headers, url, options) : null;
|
|
153
308
|
},
|
|
154
309
|
};
|
|
155
310
|
}
|
package/dist/oidc.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oidc.js","sourceRoot":"","sources":["../src/oidc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAyC,MAAM,MAAM,CAAC;AAC5F,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"oidc.js","sourceRoot":"","sources":["../src/oidc.ts"],"names":[],"mappings":"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"}
|
package/dist/provider.d.ts
CHANGED
|
@@ -35,6 +35,32 @@ export interface AuthSubject {
|
|
|
35
35
|
* request on this subject's strength — a live-read socket (#938) — ends at it.
|
|
36
36
|
*/
|
|
37
37
|
expiresAt?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Present only when the credential is a DELEGATED token (#1824): another app, the actor,
|
|
40
|
+
* is acting for this user, and may do so only within `scope` — permission keys of this
|
|
41
|
+
* app, a ceiling over what the user may do rather than a grant. Absent means the user is
|
|
42
|
+
* acting directly. A provider admits a delegated token only when the host opted in
|
|
43
|
+
* (`OidcConfig.delegation`), so a caller that never reads this field never sees one.
|
|
44
|
+
*/
|
|
45
|
+
delegation?: {
|
|
46
|
+
actor: string;
|
|
47
|
+
scope: string[];
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/** Per-request facts a caller may hand `resolve`. Additive: a provider ignores what it does not use. */
|
|
51
|
+
export interface ResolveOptions {
|
|
52
|
+
/**
|
|
53
|
+
* This request is being served by an MCP endpoint that holds a delegated token to its scope,
|
|
54
|
+
* answering as `resource` (#1824) — `mcpChannelOf(c)` from `@substrat-run/vertical-host`,
|
|
55
|
+
* which only that endpoint's own handler can see. A delegated bearer is admitted only when
|
|
56
|
+
* this is passed, and only for exactly this resource. Absent or `null`, none is.
|
|
57
|
+
*
|
|
58
|
+
* A caller that serves its own MCP surface and passes a value here takes on the ceiling: the
|
|
59
|
+
* subject's `delegation.scope` is then that caller's to enforce.
|
|
60
|
+
*/
|
|
61
|
+
delegated?: {
|
|
62
|
+
readonly resource: string;
|
|
63
|
+
} | null;
|
|
38
64
|
}
|
|
39
65
|
export interface AuthProvider {
|
|
40
66
|
handle(request: Request): Promise<Response>;
|
|
@@ -43,6 +69,6 @@ export interface AuthProvider {
|
|
|
43
69
|
* provider that needs the origin (an OIDC bearer on a shared issuer holds an MCP token
|
|
44
70
|
* to this app's own resource, #1683) falls back to the `Host` header without it.
|
|
45
71
|
*/
|
|
46
|
-
resolve(headers: Headers, url?: string): Promise<AuthSubject | null>;
|
|
72
|
+
resolve(headers: Headers, url?: string, options?: ResolveOptions): Promise<AuthSubject | null>;
|
|
47
73
|
}
|
|
48
74
|
//# sourceMappingURL=provider.d.ts.map
|
package/dist/provider.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,WAAW;IAC1B,iFAAiF;IACjF,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB;;;;;;;;;;;OAWG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,WAAW;IAC1B,iFAAiF;IACjF,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB;;;;;;;;;;;OAWG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CACjD;AAED,wGAAwG;AACxG,MAAM,WAAW,cAAc;IAC7B;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE;QAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAClD;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC5C;;;;OAIG;IACH,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;CAChG"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@substrat-run/vertical-auth",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.1",
|
|
4
4
|
"description": "Pluggable auth for Substrat verticals — the AuthProvider contract, an OIDC provider (Supabase/Auth0/AuthHero/Keycloak), a full relying-party login flow, and a per-tenant identity Durable Object (Better Auth + sub→principal directory). Workers-targeted; the vertical worker bundles it.",
|
|
5
5
|
"license": "AGPL-3.0-only",
|
|
6
6
|
"repository": {
|
|
@@ -52,10 +52,10 @@
|
|
|
52
52
|
"better-auth": "^1.7.1",
|
|
53
53
|
"drizzle-orm": "^0.45.2",
|
|
54
54
|
"jose": "^6.2.3",
|
|
55
|
-
"@substrat-run/contracts": "^0.
|
|
56
|
-
"@substrat-run/kernel": "^0.
|
|
57
|
-
"@substrat-run/
|
|
58
|
-
"@substrat-run/
|
|
55
|
+
"@substrat-run/contracts": "^0.152.0",
|
|
56
|
+
"@substrat-run/kernel": "^0.152.0",
|
|
57
|
+
"@substrat-run/psl": "^0.2.5",
|
|
58
|
+
"@substrat-run/oidc-rp": "^0.13.0"
|
|
59
59
|
},
|
|
60
60
|
"peerDependencies": {
|
|
61
61
|
"hono": "^4.13.13"
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"better-sqlite3": "^13.0.3",
|
|
67
67
|
"hono": "^4.13.13",
|
|
68
68
|
"typescript": "^7.0.0",
|
|
69
|
-
"vitest": "^5.0.
|
|
69
|
+
"vitest": "^5.0.5"
|
|
70
70
|
},
|
|
71
71
|
"scripts": {
|
|
72
72
|
"build": "tsc -p tsconfig.json",
|