@absolutejs/auth 0.56.12 → 0.56.14
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 +14 -0
- package/dist/agents/config.d.ts +5 -0
- package/dist/agents/index.d.ts +1 -0
- package/dist/agents/index.js +132 -8
- package/dist/agents/index.js.map +8 -7
- package/dist/agents/oauthGuide.d.ts +18 -0
- package/dist/agents/oidcAdapter.d.ts +11 -3
- package/dist/agents/routes.d.ts +1 -66
- package/dist/index.d.ts +4 -22
- package/dist/index.js +172 -24
- package/dist/index.js.map +13 -12
- package/dist/oidc/config.d.ts +5 -1
- package/dist/oidc/index.d.ts +1 -1
- package/dist/oidc/index.js +23 -1
- package/dist/oidc/index.js.map +3 -3
- package/dist/oidc/keys.d.ts +22 -7
- package/dist/server.js +167 -24
- package/dist/server.js.map +13 -12
- package/docs/AGENT-AUTH.md +7 -0
- package/package.json +1 -1
package/dist/oidc/keys.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
type SigningKeyIdentity = {
|
|
1
|
+
export type SigningKeyIdentity = {
|
|
2
2
|
kid: string;
|
|
3
3
|
publicJwk: JsonWebKey;
|
|
4
4
|
};
|
|
@@ -12,10 +12,10 @@ export type SigningKey = SigningKeyIdentity & ({
|
|
|
12
12
|
privateJwk?: never;
|
|
13
13
|
sign: (input: Uint8Array) => Promise<Uint8Array>;
|
|
14
14
|
});
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
declare const generateSigningKey: () => Promise<SigningKey>;
|
|
16
|
+
declare const jwkThumbprint: (jwk: JsonWebKey) => Promise<string>;
|
|
17
|
+
declare const signJwt: (payload: Record<string, unknown>, signing: SigningKey, typ?: string) => Promise<string>;
|
|
18
|
+
declare const toPublicJwk: (key: SigningKeyIdentity) => {
|
|
19
19
|
alg: string;
|
|
20
20
|
crv: string | undefined;
|
|
21
21
|
kid: string;
|
|
@@ -24,7 +24,7 @@ export declare const toPublicJwk: (key: SigningKey) => {
|
|
|
24
24
|
x: string | undefined;
|
|
25
25
|
y: string | undefined;
|
|
26
26
|
};
|
|
27
|
-
|
|
27
|
+
declare const verifyJwt: (token: string, publicJwk: JsonWebKey) => Promise<{
|
|
28
28
|
header: {
|
|
29
29
|
[k: string]: any;
|
|
30
30
|
};
|
|
@@ -32,4 +32,19 @@ export declare const verifyJwt: (token: string, publicJwk: JsonWebKey) => Promis
|
|
|
32
32
|
[k: string]: any;
|
|
33
33
|
};
|
|
34
34
|
} | undefined>;
|
|
35
|
-
|
|
35
|
+
/** Resolves the active signing identity followed by still-valid previous
|
|
36
|
+
* public identities. Duplicate key IDs fail closed because a JWT `kid` must
|
|
37
|
+
* identify exactly one verification key during an overlap window. */
|
|
38
|
+
declare const signingVerificationKeys: (active: SigningKeyIdentity, previous?: readonly SigningKeyIdentity[]) => SigningKeyIdentity[];
|
|
39
|
+
/** Verifies an Absolute Auth JWT against the exact public identity named by
|
|
40
|
+
* its protected `kid` header. This keeps already-issued tokens valid while a
|
|
41
|
+
* previous public key remains in the configured overlap window. */
|
|
42
|
+
declare const verifyJwtWithKeys: (token: string, keys: readonly SigningKeyIdentity[]) => Promise<{
|
|
43
|
+
header: {
|
|
44
|
+
[k: string]: any;
|
|
45
|
+
};
|
|
46
|
+
payload: {
|
|
47
|
+
[k: string]: any;
|
|
48
|
+
};
|
|
49
|
+
} | undefined>;
|
|
50
|
+
export { generateSigningKey, jwkThumbprint, signingVerificationKeys, signJwt, toPublicJwk, verifyJwt, verifyJwtWithKeys };
|
package/dist/server.js
CHANGED
|
@@ -3206,6 +3206,95 @@ var agentAuthContextPlugin = (config) => new Elysia2({
|
|
|
3206
3206
|
}
|
|
3207
3207
|
})).as("global");
|
|
3208
3208
|
|
|
3209
|
+
// src/agents/oauthGuide.ts
|
|
3210
|
+
var DEFAULT_GUIDE_ROUTE = "/auth.md";
|
|
3211
|
+
var secureUrl = (value, label) => {
|
|
3212
|
+
const url = new URL(value);
|
|
3213
|
+
const loopback = url.protocol === "http:" && (url.hostname === "localhost" || url.hostname === "127.0.0.1");
|
|
3214
|
+
if (url.protocol !== "https:" && !loopback)
|
|
3215
|
+
throw new Error(`${label} must use HTTPS outside loopback development`);
|
|
3216
|
+
if (url.username || url.password || url.hash)
|
|
3217
|
+
throw new Error(`${label} cannot contain credentials or a fragment`);
|
|
3218
|
+
return url.toString();
|
|
3219
|
+
};
|
|
3220
|
+
var agentOAuthGuideRoute = (config) => config.route ?? DEFAULT_GUIDE_ROUTE;
|
|
3221
|
+
var agentOAuthGuideUrl = (config) => new URL(agentOAuthGuideRoute(config), secureUrl(config.authorizationServer, "OAuth authorization server")).toString();
|
|
3222
|
+
var normalizedResources = (config) => {
|
|
3223
|
+
if (config.resources.length === 0)
|
|
3224
|
+
throw new Error("Agent OAuth guide requires at least one resource");
|
|
3225
|
+
const resources = config.resources.map((resource) => ({
|
|
3226
|
+
metadataUrl: secureUrl(resource.metadataUrl, "Protected-resource metadata URL"),
|
|
3227
|
+
name: resource.name.trim(),
|
|
3228
|
+
resource: secureUrl(resource.resource, "OAuth protected resource"),
|
|
3229
|
+
scopes: [
|
|
3230
|
+
...new Set(resource.scopes.map((scope) => scope.trim()))
|
|
3231
|
+
].filter(Boolean)
|
|
3232
|
+
}));
|
|
3233
|
+
if (resources.some(({ name, scopes }) => !name || scopes.length === 0))
|
|
3234
|
+
throw new Error("Every agent OAuth guide resource requires a name and at least one scope");
|
|
3235
|
+
if (new Set(resources.map(({ resource }) => resource)).size !== resources.length)
|
|
3236
|
+
throw new Error("Agent OAuth guide resources must be unique");
|
|
3237
|
+
return resources;
|
|
3238
|
+
};
|
|
3239
|
+
var resourceSections = (resources) => resources.map((resource) => `### ${resource.name}
|
|
3240
|
+
|
|
3241
|
+
- Protected resource: \`${resource.resource}\`
|
|
3242
|
+
- Metadata: ${resource.metadataUrl}
|
|
3243
|
+
- Allowed scopes: ${resource.scopes.map((scope) => `\`${scope}\``).join(", ")}
|
|
3244
|
+
`).join(`
|
|
3245
|
+
`);
|
|
3246
|
+
var generateAgentOAuthGuide = (config) => {
|
|
3247
|
+
if (!config.serviceName.trim())
|
|
3248
|
+
throw new Error("Agent OAuth guide requires a service name");
|
|
3249
|
+
const authorizationServer = secureUrl(config.authorizationServer, "OAuth authorization server");
|
|
3250
|
+
const resources = normalizedResources(config);
|
|
3251
|
+
const authorizationMetadata = new URL("/.well-known/oauth-authorization-server", authorizationServer).toString();
|
|
3252
|
+
return `# OAuth access for ${config.serviceName.trim()}
|
|
3253
|
+
|
|
3254
|
+
This guide is the agent-readable companion to the service's standards-based
|
|
3255
|
+
OAuth metadata. Discovery metadata is authoritative. Do not infer endpoints,
|
|
3256
|
+
scopes, audiences, or capabilities that are not advertised.
|
|
3257
|
+
|
|
3258
|
+
## 1. Discover
|
|
3259
|
+
|
|
3260
|
+
Fetch the protected-resource metadata for the exact interface you intend to
|
|
3261
|
+
use, then fetch the authorization-server metadata at
|
|
3262
|
+
${authorizationMetadata}.
|
|
3263
|
+
|
|
3264
|
+
${resourceSections(resources)}
|
|
3265
|
+
## 2. Register the OAuth client
|
|
3266
|
+
|
|
3267
|
+
Use an existing registered client or the advertised \`registration_endpoint\`.
|
|
3268
|
+
Request only scopes listed for the selected protected resource. Never register
|
|
3269
|
+
redirect URIs, grant types, or authentication methods the metadata rejects.
|
|
3270
|
+
|
|
3271
|
+
## 3. Obtain user delegation
|
|
3272
|
+
|
|
3273
|
+
For an interactive user, use authorization code with PKCE. For a device or
|
|
3274
|
+
headless client, use the device authorization grant only when
|
|
3275
|
+
\`device_authorization_endpoint\` is advertised. Send the selected protected
|
|
3276
|
+
resource as the OAuth \`resource\` value and show the exact requested scopes to
|
|
3277
|
+
the user before consent.
|
|
3278
|
+
|
|
3279
|
+
## 4. Call the selected interface
|
|
3280
|
+
|
|
3281
|
+
Present the access token in the Authorization header. The token must name the
|
|
3282
|
+
selected resource as its audience and contain the required scope. A token for
|
|
3283
|
+
one resource or transport is not authority for another.
|
|
3284
|
+
|
|
3285
|
+
## Safety
|
|
3286
|
+
|
|
3287
|
+
- Never ask a user to send a password, passkey response, MFA code, device code,
|
|
3288
|
+
authorization code, client secret, refresh token, or access token to the
|
|
3289
|
+
agent or place one in model context.
|
|
3290
|
+
- Stop on issuer, signature, audience, expiry, delegation, or scope failure.
|
|
3291
|
+
- Treat consent denial, revocation, and disabled interfaces as final until the
|
|
3292
|
+
user explicitly starts a new authorization flow.
|
|
3293
|
+
- Discovery is not authorization, and this guide grants no capability by
|
|
3294
|
+
itself.
|
|
3295
|
+
`;
|
|
3296
|
+
};
|
|
3297
|
+
|
|
3209
3298
|
// src/agents/registration.ts
|
|
3210
3299
|
init_constants();
|
|
3211
3300
|
init_crypto();
|
|
@@ -3289,6 +3378,26 @@ var verifyJwt = async (token, publicJwk) => {
|
|
|
3289
3378
|
payload
|
|
3290
3379
|
};
|
|
3291
3380
|
};
|
|
3381
|
+
var signingVerificationKeys = (active, previous = []) => {
|
|
3382
|
+
const keys = [active, ...previous];
|
|
3383
|
+
const keyIds = new Set(keys.map(({ kid }) => kid));
|
|
3384
|
+
if (keyIds.size !== keys.length)
|
|
3385
|
+
throw new Error("OIDC signing key IDs must be unique");
|
|
3386
|
+
return keys;
|
|
3387
|
+
};
|
|
3388
|
+
var verifyJwtWithKeys = async (token, keys) => {
|
|
3389
|
+
const [headerSegment] = token.split(".");
|
|
3390
|
+
if (!headerSegment)
|
|
3391
|
+
return;
|
|
3392
|
+
const header = decodeSegment(headerSegment);
|
|
3393
|
+
const kid = header?.kid;
|
|
3394
|
+
if (typeof kid !== "string" || kid.length === 0)
|
|
3395
|
+
return;
|
|
3396
|
+
const key = keys.find((candidate) => candidate.kid === kid);
|
|
3397
|
+
if (!key)
|
|
3398
|
+
return;
|
|
3399
|
+
return verifyJwt(token, key.publicJwk);
|
|
3400
|
+
};
|
|
3292
3401
|
|
|
3293
3402
|
// src/agents/registration.ts
|
|
3294
3403
|
var AGENT_CLAIM_GRANT_TYPE = "urn:workos:agent-auth:grant-type:claim";
|
|
@@ -3297,7 +3406,7 @@ var AGENT_IDENTITY_ASSERTION_TYPE = "urn:ietf:params:oauth:token-type:id-jag";
|
|
|
3297
3406
|
var DEFAULT_IDENTITY_ROUTE = "/agent/identity";
|
|
3298
3407
|
var DEFAULT_CLAIM_ROUTE = "/agent/identity/claim";
|
|
3299
3408
|
var DEFAULT_COMPLETE_ROUTE = "/agent/identity/claim/complete";
|
|
3300
|
-
var
|
|
3409
|
+
var DEFAULT_GUIDE_ROUTE2 = "/auth.md";
|
|
3301
3410
|
var DEFAULT_CLAIM_TTL_MS = 24 * 60 * MILLISECONDS_IN_A_MINUTE;
|
|
3302
3411
|
var DEFAULT_ATTEMPT_TTL_MS = 10 * MILLISECONDS_IN_A_MINUTE;
|
|
3303
3412
|
var DEFAULT_ASSERTION_TTL_MS = 60 * MILLISECONDS_IN_A_MINUTE;
|
|
@@ -3332,7 +3441,7 @@ var agentRegistrationEndpoints = (config) => {
|
|
|
3332
3441
|
return {
|
|
3333
3442
|
claimEndpoint: new URL(registration.claimRoute ?? DEFAULT_CLAIM_ROUTE, base).toString(),
|
|
3334
3443
|
completeEndpoint: new URL(registration.completeRoute ?? DEFAULT_COMPLETE_ROUTE, base).toString(),
|
|
3335
|
-
guide: new URL(registration.guideRoute ??
|
|
3444
|
+
guide: new URL(registration.guideRoute ?? DEFAULT_GUIDE_ROUTE2, base).toString(),
|
|
3336
3445
|
identityEndpoint: new URL(registration.identityRoute ?? DEFAULT_IDENTITY_ROUTE, base).toString(),
|
|
3337
3446
|
tokenEndpoint: new URL(`${oidcRoute}/token`, base).toString()
|
|
3338
3447
|
};
|
|
@@ -3960,7 +4069,18 @@ var agentAuthRoutes = (config) => {
|
|
|
3960
4069
|
if (config === undefined)
|
|
3961
4070
|
return plugin.as("global");
|
|
3962
4071
|
if (config.agentRegistration === undefined) {
|
|
3963
|
-
|
|
4072
|
+
plugin.get(config.metadataRoute ?? DEFAULT_AGENT_RESOURCE_METADATA_ROUTE, () => agentProtectedResourceMetadata(config));
|
|
4073
|
+
const { oauthGuide } = config;
|
|
4074
|
+
if (oauthGuide === undefined)
|
|
4075
|
+
return plugin.as("global");
|
|
4076
|
+
const guide = generateAgentOAuthGuide(oauthGuide);
|
|
4077
|
+
plugin.get(agentOAuthGuideRoute(oauthGuide), () => new Response(guide, {
|
|
4078
|
+
headers: {
|
|
4079
|
+
"cache-control": "public, max-age=300",
|
|
4080
|
+
"content-type": "text/markdown; charset=utf-8"
|
|
4081
|
+
}
|
|
4082
|
+
}));
|
|
4083
|
+
return plugin.as("global");
|
|
3964
4084
|
}
|
|
3965
4085
|
const registration = config.agentRegistration;
|
|
3966
4086
|
const identityRoute = registration.identityRoute ?? "/agent/identity";
|
|
@@ -6086,7 +6206,7 @@ var exchangeToken = async ({
|
|
|
6086
6206
|
requestedScopes,
|
|
6087
6207
|
subjectToken
|
|
6088
6208
|
}) => {
|
|
6089
|
-
const verified = await
|
|
6209
|
+
const verified = await verifyJwtWithKeys(subjectToken, signingVerificationKeys(config.signingKey, config.previousSigningKeys));
|
|
6090
6210
|
const payload = verified?.payload;
|
|
6091
6211
|
if (payload === undefined || typeof payload.sub !== "string" || typeof payload.exp !== "number" || payload.exp <= nowSeconds(now)) {
|
|
6092
6212
|
return { error: "invalid_grant", ok: false };
|
|
@@ -6207,7 +6327,7 @@ var introspectToken = async ({
|
|
|
6207
6327
|
token
|
|
6208
6328
|
}) => {
|
|
6209
6329
|
if (hint !== "refresh_token") {
|
|
6210
|
-
const verified = await
|
|
6330
|
+
const verified = await verifyJwtWithKeys(token, signingVerificationKeys(config.signingKey, config.previousSigningKeys));
|
|
6211
6331
|
const payload = verified?.payload;
|
|
6212
6332
|
if (payload !== undefined && typeof payload.sub === "string" && typeof payload.exp === "number" && payload.exp > nowSeconds(now)) {
|
|
6213
6333
|
return {
|
|
@@ -7123,7 +7243,7 @@ var verifyIdTokenHint = async ({
|
|
|
7123
7243
|
config,
|
|
7124
7244
|
idTokenHint
|
|
7125
7245
|
}) => {
|
|
7126
|
-
const verified = await
|
|
7246
|
+
const verified = await verifyJwtWithKeys(idTokenHint, signingVerificationKeys(config.signingKey, config.previousSigningKeys));
|
|
7127
7247
|
const payload = verified?.payload;
|
|
7128
7248
|
if (payload === undefined || typeof payload.sub !== "string" || typeof payload.aud !== "string" || payload.iss !== config.issuer) {
|
|
7129
7249
|
return;
|
|
@@ -7353,7 +7473,7 @@ var fetchUserInfo = async ({
|
|
|
7353
7473
|
ok: false
|
|
7354
7474
|
};
|
|
7355
7475
|
}
|
|
7356
|
-
const verified = await
|
|
7476
|
+
const verified = await verifyJwtWithKeys(token, signingVerificationKeys(config.signingKey, config.previousSigningKeys));
|
|
7357
7477
|
if (verified === undefined) {
|
|
7358
7478
|
return {
|
|
7359
7479
|
body: { error: "invalid_token" },
|
|
@@ -8694,7 +8814,9 @@ var oidcProviderRoutes = (config) => {
|
|
|
8694
8814
|
headers: t15.Object({
|
|
8695
8815
|
authorization: t15.Optional(t15.String())
|
|
8696
8816
|
})
|
|
8697
|
-
}).get(jwksRoute, () => ({
|
|
8817
|
+
}).get(jwksRoute, () => ({
|
|
8818
|
+
keys: signingVerificationKeys(signingKey, config.previousSigningKeys).map(toPublicJwk)
|
|
8819
|
+
})).get("/.well-known/openid-configuration", () => discovery).get("/.well-known/oauth-authorization-server", () => discovery);
|
|
8698
8820
|
};
|
|
8699
8821
|
|
|
8700
8822
|
// src/organizations/routes.ts
|
|
@@ -26741,7 +26863,7 @@ var createPostgresScimTokenStore = (db) => ({
|
|
|
26741
26863
|
});
|
|
26742
26864
|
// src/agents/registrationClient.ts
|
|
26743
26865
|
var isObject2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
26744
|
-
var
|
|
26866
|
+
var secureUrl2 = (value, allowLocalhost) => {
|
|
26745
26867
|
if (typeof value !== "string")
|
|
26746
26868
|
return;
|
|
26747
26869
|
try {
|
|
@@ -26831,32 +26953,32 @@ var discoverAgentRegistration = async (resource, options = {}) => {
|
|
|
26831
26953
|
const request = options.request ?? fetch;
|
|
26832
26954
|
const maxBytes = options.maxResponseBytes ?? 256 * 1024;
|
|
26833
26955
|
const allowLocalhost = options.allowInsecureLocalhost === true;
|
|
26834
|
-
const resourceUrl =
|
|
26956
|
+
const resourceUrl = secureUrl2(resource, allowLocalhost);
|
|
26835
26957
|
if (resourceUrl === undefined)
|
|
26836
26958
|
throw new Error("Resource URL must use HTTPS");
|
|
26837
26959
|
const resourceMetadataUrl = new URL("/.well-known/oauth-protected-resource", resourceUrl).toString();
|
|
26838
26960
|
const prm = await requestJson(request, resourceMetadataUrl, {}, maxBytes);
|
|
26839
|
-
const advertisedResource =
|
|
26961
|
+
const advertisedResource = secureUrl2(prm.body.resource, allowLocalhost);
|
|
26840
26962
|
if (advertisedResource === undefined || advertisedResource !== resourceUrl) {
|
|
26841
26963
|
throw new Error("Protected resource metadata identity mismatch");
|
|
26842
26964
|
}
|
|
26843
|
-
const authorizationServer =
|
|
26965
|
+
const authorizationServer = secureUrl2(stringArray(prm.body.authorization_servers)[0], allowLocalhost);
|
|
26844
26966
|
if (authorizationServer === undefined) {
|
|
26845
26967
|
throw new Error("No secure authorization server is advertised");
|
|
26846
26968
|
}
|
|
26847
26969
|
const asUrl = new URL("/.well-known/oauth-authorization-server", authorizationServer).toString();
|
|
26848
26970
|
const metadata = await requestJson(request, asUrl, {}, maxBytes);
|
|
26849
|
-
if (
|
|
26971
|
+
if (secureUrl2(metadata.body.issuer, allowLocalhost) !== authorizationServer) {
|
|
26850
26972
|
throw new Error("Authorization server issuer mismatch");
|
|
26851
26973
|
}
|
|
26852
|
-
const tokenEndpoint =
|
|
26974
|
+
const tokenEndpoint = secureUrl2(metadata.body.token_endpoint, allowLocalhost);
|
|
26853
26975
|
const agentAuth = metadata.body.agent_auth;
|
|
26854
26976
|
if (tokenEndpoint === undefined || !isObject2(agentAuth)) {
|
|
26855
26977
|
throw new Error("Authorization server does not advertise agent registration");
|
|
26856
26978
|
}
|
|
26857
|
-
const identityEndpoint =
|
|
26858
|
-
const claimEndpoint =
|
|
26859
|
-
const skill =
|
|
26979
|
+
const identityEndpoint = secureUrl2(agentAuth.identity_endpoint, allowLocalhost);
|
|
26980
|
+
const claimEndpoint = secureUrl2(agentAuth.claim_endpoint, allowLocalhost);
|
|
26981
|
+
const skill = secureUrl2(agentAuth.skill, allowLocalhost);
|
|
26860
26982
|
const assertionMetadata = agentAuth.identity_assertion;
|
|
26861
26983
|
if (identityEndpoint === undefined || claimEndpoint === undefined || skill === undefined || !isObject2(assertionMetadata)) {
|
|
26862
26984
|
throw new Error("Agent registration metadata is incomplete");
|
|
@@ -27033,6 +27155,7 @@ var createOidcAgentCredentialVerifier = ({
|
|
|
27033
27155
|
isUsedDpopJti,
|
|
27034
27156
|
maxDpopAgeMs,
|
|
27035
27157
|
publicJwk,
|
|
27158
|
+
publicKeys,
|
|
27036
27159
|
requireDpop = false,
|
|
27037
27160
|
resource
|
|
27038
27161
|
}) => {
|
|
@@ -27044,13 +27167,14 @@ var createOidcAgentCredentialVerifier = ({
|
|
|
27044
27167
|
const token = authorization.slice(authorization.indexOf(" ") + 1).trim();
|
|
27045
27168
|
if (token.length === 0)
|
|
27046
27169
|
return;
|
|
27047
|
-
const verified = await verifyJwt(token, publicJwk);
|
|
27170
|
+
const verified = publicKeys ? await verifyJwtWithKeys(token, publicKeys) : await verifyJwt(token, publicJwk);
|
|
27048
27171
|
const payload = verified?.payload;
|
|
27049
27172
|
if (payload === undefined || payload.iss !== issuer || typeof payload.exp !== "number" || payload.exp <= Math.floor(Date.now() / MS_PER_SECOND7) || !readAudience(payload.aud).includes(resource) || typeof payload.client_id !== "string") {
|
|
27050
27173
|
return;
|
|
27051
27174
|
}
|
|
27052
27175
|
const confirmation = payload.cnf;
|
|
27053
|
-
const
|
|
27176
|
+
const boundJktValue = typeof confirmation === "object" && confirmation !== null ? Reflect.get(confirmation, "jkt") : undefined;
|
|
27177
|
+
const boundJkt = typeof boundJktValue === "string" ? boundJktValue : undefined;
|
|
27054
27178
|
if (boundJkt !== undefined || requireDpop) {
|
|
27055
27179
|
if (!authorization.startsWith("DPoP "))
|
|
27056
27180
|
return;
|
|
@@ -27614,7 +27738,7 @@ var createPostgresApiKeyStore = (db) => ({
|
|
|
27614
27738
|
}
|
|
27615
27739
|
});
|
|
27616
27740
|
// src/oidc/clientIdMetadata.ts
|
|
27617
|
-
var
|
|
27741
|
+
var secureUrl3 = (value) => {
|
|
27618
27742
|
try {
|
|
27619
27743
|
return new URL(value).protocol === "https:";
|
|
27620
27744
|
} catch {
|
|
@@ -27625,7 +27749,7 @@ var validateClientIdMetadataDocument = (document, expectedClientId) => {
|
|
|
27625
27749
|
const errors = [];
|
|
27626
27750
|
if (document.client_id !== expectedClientId)
|
|
27627
27751
|
errors.push("client_id does not match the metadata document URL");
|
|
27628
|
-
if (!
|
|
27752
|
+
if (!secureUrl3(document.client_id))
|
|
27629
27753
|
errors.push("client_id must use HTTPS");
|
|
27630
27754
|
if (!Array.isArray(document.redirect_uris) || document.redirect_uris.length === 0)
|
|
27631
27755
|
errors.push("redirect_uris is required");
|
|
@@ -27645,7 +27769,7 @@ var validateClientIdMetadataDocument = (document, expectedClientId) => {
|
|
|
27645
27769
|
["tos_uri", document.tos_uri],
|
|
27646
27770
|
["jwks_uri", document.jwks_uri]
|
|
27647
27771
|
]) {
|
|
27648
|
-
if (value !== undefined && !
|
|
27772
|
+
if (value !== undefined && !secureUrl3(value))
|
|
27649
27773
|
errors.push(`${name2} must use HTTPS`);
|
|
27650
27774
|
}
|
|
27651
27775
|
return errors;
|
|
@@ -27668,7 +27792,7 @@ var createClientIdMetadataResolver = ({
|
|
|
27668
27792
|
}) => {
|
|
27669
27793
|
const cache = new Map;
|
|
27670
27794
|
return async (clientId) => {
|
|
27671
|
-
if (!
|
|
27795
|
+
if (!secureUrl3(clientId) || !await allow(clientId))
|
|
27672
27796
|
return;
|
|
27673
27797
|
const cached = cache.get(clientId);
|
|
27674
27798
|
if (cached !== undefined && cached.expiresAt > now())
|
|
@@ -30347,6 +30471,22 @@ var buildAuthApplications = async (configuration) => {
|
|
|
30347
30471
|
tokenTtlMs: registration2.tokenTtlMs
|
|
30348
30472
|
});
|
|
30349
30473
|
}
|
|
30474
|
+
if (agentAuth?.oauthGuide !== undefined) {
|
|
30475
|
+
if (oidc === undefined)
|
|
30476
|
+
throw new Error("agentAuth.oauthGuide requires the OIDC provider");
|
|
30477
|
+
if (agentAuth.authorizationServer !== oidc.issuer)
|
|
30478
|
+
throw new Error("agentAuth.authorizationServer must equal oidc.issuer");
|
|
30479
|
+
if (agentAuth.oauthGuide.authorizationServer !== agentAuth.authorizationServer)
|
|
30480
|
+
throw new Error("agentAuth.oauthGuide.authorizationServer must equal agentAuth.authorizationServer");
|
|
30481
|
+
const unknownGuideScopes = agentAuth.oauthGuide.resources.flatMap(({ scopes }) => scopes).filter((scope) => !agentAuth.scopes.includes(scope));
|
|
30482
|
+
if (unknownGuideScopes.length > 0)
|
|
30483
|
+
throw new Error(`Agent OAuth guide uses undeclared scopes: ${[
|
|
30484
|
+
...new Set(unknownGuideScopes)
|
|
30485
|
+
].join(", ")}`);
|
|
30486
|
+
if (agentAuth.agentRegistration !== undefined && (agentAuth.agentRegistration.guideRoute ?? "/auth.md") === (agentAuth.oauthGuide.route ?? "/auth.md"))
|
|
30487
|
+
throw new Error("Agent OAuth and registration guides cannot use the same route");
|
|
30488
|
+
generateAgentOAuthGuide(agentAuth.oauthGuide);
|
|
30489
|
+
}
|
|
30350
30490
|
if (tracing !== undefined)
|
|
30351
30491
|
await initTracing(tracing);
|
|
30352
30492
|
const clientProviders = await buildClientProviders(providersConfiguration, createOAuth2Client, customProviders);
|
|
@@ -30368,6 +30508,9 @@ var buildAuthApplications = async (configuration) => {
|
|
|
30368
30508
|
...oidc,
|
|
30369
30509
|
additionalDiscoveryMetadata: {
|
|
30370
30510
|
...oidc.additionalDiscoveryMetadata,
|
|
30511
|
+
...resolvedAgentAuth?.oauthGuide === undefined ? {} : {
|
|
30512
|
+
service_documentation: agentOAuthGuideUrl(resolvedAgentAuth.oauthGuide)
|
|
30513
|
+
},
|
|
30371
30514
|
...resolvedAgentAuth?.agentRegistration === undefined ? {} : {
|
|
30372
30515
|
agent_auth: agentRegistrationDiscoveryMetadata(resolvedAgentAuth)
|
|
30373
30516
|
}
|
|
@@ -30587,5 +30730,5 @@ export {
|
|
|
30587
30730
|
auth2 as auth
|
|
30588
30731
|
};
|
|
30589
30732
|
|
|
30590
|
-
//# debugId=
|
|
30733
|
+
//# debugId=E2F70FC52266FF6C64756E2164756E21
|
|
30591
30734
|
//# sourceMappingURL=server.js.map
|