@absolutejs/auth 0.57.7 → 0.57.9

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.js CHANGED
@@ -367,17 +367,23 @@ var providers = defineProviders({
367
367
  },
368
368
  apple: {
369
369
  authorizationUrl: "https://appleid.apple.com/auth/authorize",
370
+ createAuthorizationURLSearchParams: {
371
+ response_mode: "form_post"
372
+ },
373
+ createClientSecret: (config) => createAppleClientSecret(config),
370
374
  isOIDC: true,
371
375
  isRefreshable: true,
372
- PKCEMethod: "S256",
373
- profileRequest: {
374
- authIn: "header",
375
- encoding: "application/json",
376
- method: "GET",
377
- url: "https://appleid.apple.com/auth/userinfo"
376
+ revocationRequest: {
377
+ authIn: "body",
378
+ encoding: "application/x-www-form-urlencoded",
379
+ tokenParamName: "token",
380
+ url: "https://appleid.apple.com/auth/revoke"
378
381
  },
379
382
  scopeRequired: false,
380
- subject: ["id"],
383
+ subject: ["sub"],
384
+ subjectBySource: {
385
+ idToken: ["sub"]
386
+ },
381
387
  subjectType: "string",
382
388
  tokenRequest: {
383
389
  authIn: "body",
@@ -446,6 +452,7 @@ var providers = defineProviders({
446
452
  token_type_hint: "refresh_token"
447
453
  }),
448
454
  encoding: "application/json",
455
+ inputSource: "refreshToken",
449
456
  tokenParamName: "token",
450
457
  url: (config) => `https://${config.domain}/oauth/revoke`
451
458
  },
@@ -1577,6 +1584,7 @@ var providers = defineProviders({
1577
1584
  token_type_hint: "refresh_token"
1578
1585
  }),
1579
1586
  encoding: "application/json",
1587
+ inputSource: "refreshToken",
1580
1588
  url: "https://www.reddit.com/api/v1/revoke_token"
1581
1589
  },
1582
1590
  scopeRequired: true,
@@ -1950,49 +1958,27 @@ var providers = defineProviders({
1950
1958
  authorizationUrl: "https://account.withings.com/oauth2_user/authorize2",
1951
1959
  isOIDC: false,
1952
1960
  isRefreshable: true,
1953
- profileRequest: {
1954
- authIn: "header",
1955
- body: async (config) => {
1956
- const props = await getWithingsProps(config);
1957
- if (props === undefined)
1958
- throw new Error("Failed to get Withings search properties");
1959
- const { nonce, hashedSignature } = props;
1960
- return [
1961
- ["action", "getuser"],
1962
- ["nonce", nonce],
1963
- ["client_id", config.clientId],
1964
- ["signature", hashedSignature]
1965
- ];
1966
- },
1967
- encoding: "application/x-www-form-urlencoded",
1968
- method: "POST",
1969
- url: "https://wbsapi.withings.net/v2/oauth2"
1970
- },
1971
1961
  refreshAccessTokenBody: {
1972
1962
  action: "requesttoken"
1973
1963
  },
1974
1964
  revocationRequest: {
1975
- authIn: "header",
1976
- body: async (config) => {
1977
- const props = await getWithingsProps(config);
1978
- if (!props)
1979
- throw new Error("Failed to get Withings props");
1980
- const { nonce, hashedSignature } = props;
1981
- return [
1982
- ["action", "revoke"],
1983
- ["client_id", config.clientId],
1984
- ["nonce", nonce],
1985
- ["signature", hashedSignature]
1986
- ];
1987
- },
1965
+ authIn: "body",
1966
+ body: (config) => getWithingsSignatureParams(config, "revoke"),
1988
1967
  encoding: "application/x-www-form-urlencoded",
1989
- method: "POST",
1990
- url: "https://wbsapi.withings.net/v2/oauth2"
1968
+ includeClientCredentials: false,
1969
+ inputSource: "subject",
1970
+ inputType: "number",
1971
+ tokenParamName: "userid",
1972
+ url: "https://wbsapi.withings.net/v2/oauth2",
1973
+ validateResponse: (value) => assertWithingsSuccess(value)
1991
1974
  },
1992
1975
  scopeDelimiter: ",",
1993
1976
  scopeRequired: true,
1994
1977
  subject: ["userid"],
1995
- subjectType: "string",
1978
+ subjectBySource: {
1979
+ tokenResponse: ["body", "userid"]
1980
+ },
1981
+ subjectType: "number",
1996
1982
  tokenRequest: {
1997
1983
  authIn: "body",
1998
1984
  encoding: "application/x-www-form-urlencoded",
@@ -2184,14 +2170,39 @@ var isPKCEProviderOption = (option) => {
2184
2170
  const provider = providers[option];
2185
2171
  return provider.PKCEMethod !== undefined;
2186
2172
  };
2187
- var isRefreshableOAuth2Client = (providerName, _client) => isRefreshableProviderOption(providerName);
2173
+ function isProfileOAuth2Client(providerOrClient, maybeClient) {
2174
+ const client = maybeClient ?? providerOrClient;
2175
+ if (maybeClient !== undefined && (typeof providerOrClient !== "string" || !isProfileProviderOption(providerOrClient))) {
2176
+ return false;
2177
+ }
2178
+ return typeof client === "object" && client !== null && "fetchUserProfile" in client && typeof client.fetchUserProfile === "function";
2179
+ }
2180
+ var isProfileProviderOption = (option) => {
2181
+ if (!isValidProviderOption(option))
2182
+ return false;
2183
+ const provider = providers[option];
2184
+ return provider.profileRequest !== undefined;
2185
+ };
2186
+ function isRefreshableOAuth2Client(providerOrClient, maybeClient) {
2187
+ const client = maybeClient ?? providerOrClient;
2188
+ if (maybeClient !== undefined && (typeof providerOrClient !== "string" || !isRefreshableProviderOption(providerOrClient))) {
2189
+ return false;
2190
+ }
2191
+ return typeof client === "object" && client !== null && "refreshAccessToken" in client && typeof client.refreshAccessToken === "function";
2192
+ }
2188
2193
  var isRefreshableProviderOption = (option) => {
2189
2194
  if (!isValidProviderOption(option))
2190
2195
  return false;
2191
2196
  const provider = providers[option];
2192
2197
  return provider.isRefreshable;
2193
2198
  };
2194
- var isRevocableOAuth2Client = (providerName, _client) => isRevocableProviderOption(providerName);
2199
+ function isRevocableOAuth2Client(providerOrClient, maybeClient) {
2200
+ const client = maybeClient ?? providerOrClient;
2201
+ if (maybeClient !== undefined && (typeof providerOrClient !== "string" || !isRevocableProviderOption(providerOrClient))) {
2202
+ return false;
2203
+ }
2204
+ return typeof client === "object" && client !== null && "resolveRevocationInput" in client && typeof client.resolveRevocationInput === "function" && "revokeToken" in client && typeof client.revokeToken === "function";
2205
+ }
2195
2206
  var isRevocableProviderOption = (option) => {
2196
2207
  if (!isValidProviderOption(option))
2197
2208
  return false;
@@ -2205,6 +2216,14 @@ var isScopeRequiredProviderOption = (option) => {
2205
2216
  return provider.scopeRequired;
2206
2217
  };
2207
2218
  var isValidProviderOption = (option) => Object.hasOwn(providers, option);
2219
+ var readPath = (value, path) => path.reduce((cursor, key) => cursor && typeof cursor === "object" ? Reflect.get(cursor, key) : undefined, value);
2220
+ var assertWithingsSuccess = (value) => {
2221
+ if (!isObject(value) || value.status !== 0) {
2222
+ const status = isObject(value) ? value.status : "invalid response";
2223
+ const detail = isObject(value) && typeof value.error === "string" ? `: ${value.error}` : "";
2224
+ throw new Error(`Withings request failed (${String(status)})${detail}`);
2225
+ }
2226
+ };
2208
2227
  var createOAuth2FetchError = async (response) => {
2209
2228
  const clone = response.clone();
2210
2229
  const prefix = `HTTP ${response.status} ${response.statusText} for ${response.url}`;
@@ -2238,16 +2257,27 @@ var createOAuth2Request = ({
2238
2257
  }
2239
2258
  oauthHeaders.set("Authorization", `Basic ${encodeBase64(`${clientId}:${clientSecret}`)}`);
2240
2259
  }
2260
+ if (body === undefined && authIn !== "body") {
2261
+ return new Request(url, {
2262
+ headers: oauthHeaders,
2263
+ method: "POST"
2264
+ });
2265
+ }
2241
2266
  if (encoding === "application/json") {
2242
2267
  oauthHeaders.set("Content-Type", "application/json");
2268
+ const jsonBody = body instanceof URLSearchParams ? Object.fromEntries(body.entries()) : { ...body };
2269
+ if (authIn === "body")
2270
+ jsonBody.client_id = clientId;
2271
+ if (authIn === "body" && clientSecret)
2272
+ jsonBody.client_secret = clientSecret;
2243
2273
  return new Request(url, {
2244
- body: JSON.stringify(body),
2274
+ body: JSON.stringify(jsonBody),
2245
2275
  headers: oauthHeaders,
2246
2276
  method: "POST"
2247
2277
  });
2248
2278
  }
2249
2279
  oauthHeaders.set("Content-Type", "application/x-www-form-urlencoded");
2250
- const entries = body instanceof URLSearchParams ? Array.from(body.entries()) : Object.entries(body).filter((entry) => typeof entry[1] === "string");
2280
+ const entries = body instanceof URLSearchParams ? Array.from(body.entries()) : Object.entries(body ?? {}).filter((entry) => typeof entry[1] === "string");
2251
2281
  const params = new URLSearchParams(entries);
2252
2282
  if (authIn === "body") {
2253
2283
  params.set("client_id", clientId);
@@ -2293,25 +2323,31 @@ var encodeBase64 = (input) => {
2293
2323
  }
2294
2324
  return btoa(raw);
2295
2325
  };
2296
- var getWithingsProps = async (config) => {
2326
+ var getWithingsSignatureParams = async (config, action) => {
2297
2327
  const timestamp = Math.floor(Date.now() / 1000);
2298
- const signature = `getnonce,${config.clientId},${timestamp}`;
2299
- const hashedSignature = await hmacSha256(signature, config.clientSecret);
2328
+ const nonceSignature = await hmacSha256(`getnonce,${config.clientId},${timestamp}`, config.clientSecret);
2300
2329
  const nonceUrl = new URL("https://wbsapi.withings.net/v2/signature");
2301
2330
  nonceUrl.searchParams.set("action", "getnonce");
2302
2331
  nonceUrl.searchParams.set("client_id", config.clientId);
2303
2332
  nonceUrl.searchParams.set("timestamp", timestamp.toString());
2304
- nonceUrl.searchParams.set("signature", hashedSignature);
2333
+ nonceUrl.searchParams.set("signature", nonceSignature);
2305
2334
  const nonceTarget = nonceUrl.toString();
2306
2335
  const nonceResponse = await fetch(nonceTarget, { method: "POST" });
2336
+ if (!nonceResponse.ok) {
2337
+ throw await createOAuth2FetchError(nonceResponse);
2338
+ }
2307
2339
  const nonceData = await nonceResponse.json();
2308
- if (nonceData.status === 0) {
2309
- return {
2310
- hashedSignature,
2311
- nonce: nonceData.body.nonce
2312
- };
2340
+ if (!isObject(nonceData) || nonceData.status !== 0 || !isObject(nonceData.body) || typeof nonceData.body.nonce !== "string" || nonceData.body.nonce.length === 0) {
2341
+ throw new Error("Withings returned an invalid nonce response");
2313
2342
  }
2314
- return;
2343
+ const { nonce } = nonceData.body;
2344
+ const signature = await hmacSha256(`${action},${config.clientId},${nonce}`, config.clientSecret);
2345
+ return {
2346
+ action,
2347
+ client_id: config.clientId,
2348
+ nonce,
2349
+ signature
2350
+ };
2315
2351
  };
2316
2352
  var hmacSha256 = async (message, secret) => {
2317
2353
  const encoder = new TextEncoder;
@@ -2319,15 +2355,53 @@ var hmacSha256 = async (message, secret) => {
2319
2355
  const sigBuffer = await crypto.subtle.sign("HMAC", key, encoder.encode(message));
2320
2356
  return Array.from(new Uint8Array(sigBuffer)).map((byte) => byte.toString(16).padStart(2, "0")).join("");
2321
2357
  };
2358
+ var parseOAuth2TokenResponse = (value, accessTokenPath) => {
2359
+ if (!isObject(value)) {
2360
+ throw new Error("OAuth token endpoint returned a non-object response");
2361
+ }
2362
+ const oauthError = Reflect.get(value, "error");
2363
+ if (typeof oauthError === "string" && oauthError.length > 0) {
2364
+ throw new Error(`OAuth token exchange failed: ${oauthError}`);
2365
+ }
2366
+ const response = { ...value };
2367
+ const nestedToken = accessTokenPath ? readPath(value, accessTokenPath) : undefined;
2368
+ if (typeof nestedToken === "string" && nestedToken.length > 0) {
2369
+ response.access_token = nestedToken;
2370
+ }
2371
+ if (typeof response.access_token !== "string" || response.access_token.length === 0) {
2372
+ throw new Error("OAuth token endpoint returned no access_token");
2373
+ }
2374
+ for (const key of ["refresh_token", "token_type", "scope", "id_token"]) {
2375
+ const field = response[key];
2376
+ if (field !== undefined && typeof field !== "string") {
2377
+ throw new Error(`OAuth token endpoint returned invalid ${key}: expected string`);
2378
+ }
2379
+ }
2380
+ const expiresIn = response.expires_in;
2381
+ if (typeof expiresIn === "string" && expiresIn.trim() !== "") {
2382
+ response.expires_in = Number(expiresIn);
2383
+ }
2384
+ if (response.expires_in !== undefined && (typeof response.expires_in !== "number" || !Number.isFinite(response.expires_in) || response.expires_in < 0)) {
2385
+ throw new Error("OAuth token endpoint returned invalid expires_in: expected a non-negative number");
2386
+ }
2387
+ return response;
2388
+ };
2389
+ var readIdentityKey = (value, key) => {
2390
+ if (Array.isArray(value)) {
2391
+ if (!/^\d+$/.test(key)) {
2392
+ throw new Error(`Invalid identity data shape: expected an array index, got ${key}`);
2393
+ }
2394
+ return value[Number(key)];
2395
+ }
2396
+ if (!isObject(value)) {
2397
+ throw new Error(`Invalid identity data shape: expected object, got ${typeof value}`);
2398
+ }
2399
+ return value[key];
2400
+ };
2322
2401
  var extractPropFromIdentity = (identity, keys, propType) => {
2323
2402
  let value = identity;
2324
2403
  for (const key of keys) {
2325
- if (Array.isArray(value))
2326
- value = value[Number(key)];
2327
- if (!isObject(value)) {
2328
- throw new Error(`Invalid identity data shape: expected object, got ${typeof value}`);
2329
- }
2330
- value = value[key];
2404
+ value = readIdentityKey(value, key);
2331
2405
  }
2332
2406
  if (propType !== undefined && !isExpectedType(value, propType)) {
2333
2407
  throw new Error(`Invalid identity data shape: expected ${propType}, got ${typeof value}`);
@@ -2362,6 +2436,13 @@ var normalizeProviderIdentity = ({
2362
2436
  const normalizedIdentity = structuredClone(identity);
2363
2437
  return setPropInIdentity(normalizedIdentity, canonicalKeys, subject);
2364
2438
  };
2439
+ var DAYS_IN_APPLE_CLIENT_SECRET_LIFETIME = 180;
2440
+ var HOURS_PER_DAY = 24;
2441
+ var MINUTES_PER_HOUR = 60;
2442
+ var SECONDS_PER_MINUTE = 60;
2443
+ var APPLE_CLIENT_SECRET_LIFETIME_SECONDS = SECONDS_PER_MINUTE * MINUTES_PER_HOUR * HOURS_PER_DAY * DAYS_IN_APPLE_CLIENT_SECRET_LIFETIME;
2444
+ var APPLE_ISSUER = "https://appleid.apple.com";
2445
+ var MILLISECONDS_PER_SECOND = 1000;
2365
2446
  var createS256CodeChallenge = async (codeVerifier) => {
2366
2447
  const data = new TextEncoder().encode(codeVerifier);
2367
2448
  const hashBuffer = await crypto.subtle.digest("SHA-256", data);
@@ -2374,20 +2455,40 @@ var createRandomBase64UrlGenerator = (length) => () => {
2374
2455
  var generateCodeVerifier = createRandomBase64UrlGenerator(NUM_GENERATOR_BYTES);
2375
2456
  var generateState = createRandomBase64UrlGenerator(NUM_GENERATOR_BYTES);
2376
2457
  var base64Url = (input) => encodeBase64(input).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
2458
+ var encodeJwtPart = (value) => base64Url(new TextEncoder().encode(JSON.stringify(value)));
2459
+ var createAppleClientSecret = async (credentials) => {
2460
+ const issuedAt = Math.floor(Date.now() / MILLISECONDS_PER_SECOND);
2461
+ const header = encodeJwtPart({
2462
+ alg: "ES256",
2463
+ kid: credentials.keyId,
2464
+ typ: "JWT"
2465
+ });
2466
+ const payload = encodeJwtPart({
2467
+ aud: APPLE_ISSUER,
2468
+ exp: issuedAt + APPLE_CLIENT_SECRET_LIFETIME_SECONDS,
2469
+ iat: issuedAt,
2470
+ iss: credentials.teamId,
2471
+ sub: credentials.clientId
2472
+ });
2473
+ const signingInput = `${header}.${payload}`;
2474
+ const privateKey = await crypto.subtle.importKey("pkcs8", Uint8Array.from(credentials.pkcs8PrivateKey), { name: "ECDSA", namedCurve: "P-256" }, false, ["sign"]);
2475
+ const signature = await crypto.subtle.sign({ hash: "SHA-256", name: "ECDSA" }, privateKey, new TextEncoder().encode(signingInput));
2476
+ return `${signingInput}.${base64Url(signature)}`;
2477
+ };
2377
2478
  var ALG_ES256 = "ES256";
2378
2479
  var ALG_RS256 = "RS256";
2379
2480
  var CLOCK_SKEW_SECONDS = 60;
2380
2481
  var DEFAULT_SCOPES = ["openid", "email", "profile"];
2381
2482
  var JWKS_REFETCH_COOLDOWN_MS = 60000;
2382
2483
  var JWT_SEGMENT_COUNT = 3;
2383
- var MILLISECONDS_PER_SECOND = 1000;
2484
+ var MILLISECONDS_PER_SECOND2 = 1000;
2384
2485
  var trimTrailingSlash = (value) => value.endsWith("/") ? value.slice(0, -1) : value;
2385
2486
  var fetchJson = async (url) => {
2386
2487
  const response = await fetch(url, {
2387
2488
  headers: { accept: "application/json" }
2388
2489
  });
2389
2490
  if (!response.ok) {
2390
- throw new Error(`Request to ${url} failed with status ${response.status}`);
2491
+ throw await createOAuth2FetchError(response);
2391
2492
  }
2392
2493
  return response.json();
2393
2494
  };
@@ -2418,11 +2519,14 @@ var verifySignature = (key, alg, signingInput, signature) => {
2418
2519
  var selectKey = (jwks, kid) => jwks.find((jwk) => kid === undefined || jwk.kid === kid);
2419
2520
  var assertClaims = (payload, expected) => {
2420
2521
  const aud = Reflect.get(payload, "aud");
2522
+ const azp = Reflect.get(payload, "azp");
2421
2523
  const exp = Reflect.get(payload, "exp");
2524
+ const iat = Reflect.get(payload, "iat");
2422
2525
  const iss = Reflect.get(payload, "iss");
2526
+ const nbf = Reflect.get(payload, "nbf");
2423
2527
  const sub = Reflect.get(payload, "sub");
2424
2528
  const audiences = Array.isArray(aud) ? aud : [aud];
2425
- const nowSeconds = Math.floor(Date.now() / MILLISECONDS_PER_SECOND);
2529
+ const nowSeconds = Math.floor(Date.now() / MILLISECONDS_PER_SECOND2);
2426
2530
  if (iss !== expected.issuer) {
2427
2531
  throw new Error('id_token "iss" does not match the provider issuer');
2428
2532
  }
@@ -2432,9 +2536,24 @@ var assertClaims = (payload, expected) => {
2432
2536
  if (!audiences.includes(expected.audience)) {
2433
2537
  throw new Error('id_token "aud" does not include the client id');
2434
2538
  }
2539
+ if (audiences.some((audience) => typeof audience !== "string") || typeof aud !== "string" && !Array.isArray(aud)) {
2540
+ throw new Error('id_token "aud" must be a string or string array');
2541
+ }
2542
+ if (audiences.length > 1 && (typeof azp !== "string" || azp !== expected.audience)) {
2543
+ throw new Error('id_token with multiple audiences requires matching "azp"');
2544
+ }
2435
2545
  if (typeof exp !== "number" || exp + CLOCK_SKEW_SECONDS < nowSeconds) {
2436
2546
  throw new Error("id_token has expired");
2437
2547
  }
2548
+ if (typeof iat !== "number") {
2549
+ throw new Error('id_token is missing numeric "iat"');
2550
+ }
2551
+ if (iat > nowSeconds + CLOCK_SKEW_SECONDS) {
2552
+ throw new Error('id_token "iat" is in the future');
2553
+ }
2554
+ if (nbf !== undefined && (typeof nbf !== "number" || nbf > nowSeconds + CLOCK_SKEW_SECONDS)) {
2555
+ throw new Error("id_token is not active yet");
2556
+ }
2438
2557
  if (expected.nonce !== undefined && Reflect.get(payload, "nonce") !== expected.nonce) {
2439
2558
  throw new Error('id_token "nonce" does not match');
2440
2559
  }
@@ -2561,9 +2680,9 @@ var createOIDCClient = async (config) => {
2561
2680
  method: "POST"
2562
2681
  });
2563
2682
  if (!response.ok) {
2564
- throw new Error(`OIDC token request failed with status ${response.status}`);
2683
+ throw await createOAuth2FetchError(response);
2565
2684
  }
2566
- const tokens = await response.json();
2685
+ const tokens = parseOAuth2TokenResponse(await response.json());
2567
2686
  return tokens;
2568
2687
  };
2569
2688
  const verifyToken = async (idToken, options) => {
@@ -2609,20 +2728,26 @@ var createOIDCClient = async (config) => {
2609
2728
  };
2610
2729
  var oidcProviderOptions = Object.keys(providers).filter(isOIDCProviderOption);
2611
2730
  var pkceProviderOptions = Object.keys(providers).filter(isPKCEProviderOption);
2731
+ var profileProviderOptions = Object.keys(providers).filter(isProfileProviderOption);
2612
2732
  var providerOptions = Object.keys(providers).filter(isValidProviderOption);
2613
2733
  var refreshableProviderOptions = Object.keys(providers).filter(isRefreshableProviderOption);
2614
2734
  var revocableProviderOptions = Object.keys(providers).filter(isRevocableProviderOption);
2615
2735
  var scopeRequiredProviderOptions = Object.keys(providers).filter(isScopeRequiredProviderOption);
2616
- var readPath = (value, path) => path.reduce((cursor, key) => cursor && typeof cursor === "object" ? Reflect.get(cursor, key) : undefined, value);
2617
2736
  var buildOAuth2Client = async (meta, config) => {
2618
2737
  const isConfigPropertyFunction = (cfgProp) => typeof cfgProp === "function";
2619
2738
  const resolveConfigProp = async (cfgProp) => {
2620
2739
  const result = isConfigPropertyFunction(cfgProp) ? cfgProp(config) : cfgProp;
2621
2740
  return result;
2622
2741
  };
2742
+ const resolveClientSecret = async () => {
2743
+ if (meta.createClientSecret) {
2744
+ return resolveConfigProp(meta.createClientSecret);
2745
+ }
2746
+ return hasClientSecret(config) ? config.clientSecret : undefined;
2747
+ };
2623
2748
  const authorizationUrl = await resolveConfigProp(meta.authorizationUrl);
2624
2749
  const tokenUrl = await resolveConfigProp(meta.tokenRequest.url);
2625
- return {
2750
+ const client = {
2626
2751
  async createAuthorizationUrl(opts) {
2627
2752
  const { state, scope = [], searchParams = [], codeVerifier } = opts;
2628
2753
  const url = new URL(authorizationUrl);
@@ -2643,7 +2768,7 @@ var buildOAuth2Client = async (meta, config) => {
2643
2768
  url.searchParams.set("code_challenge_method", meta.PKCEMethod);
2644
2769
  url.searchParams.set("code_challenge", codeChallenge);
2645
2770
  }
2646
- Object.entries(resolveConfigProp(meta.createAuthorizationURLSearchParams) ?? {}).forEach(([key, value]) => url.searchParams.set(key, value));
2771
+ Object.entries(await resolveConfigProp(meta.createAuthorizationURLSearchParams) ?? {}).forEach(([key, value]) => url.searchParams.set(key, value));
2647
2772
  searchParams.forEach(([key, value]) => url.searchParams.set(key, value));
2648
2773
  return url;
2649
2774
  },
@@ -2676,7 +2801,7 @@ var buildOAuth2Client = async (meta, config) => {
2676
2801
  if (authIn === "header") {
2677
2802
  profileHeaders.Authorization = `Bearer ${accessToken}`;
2678
2803
  } else if (authIn === "path") {
2679
- endpoint.pathname = `${endpoint.pathname.replace(/\/+$/, "")}/${accessToken}`;
2804
+ endpoint.pathname = `${endpoint.pathname.replace(/\/+$/, "")}/${encodeURIComponent(accessToken)}`;
2680
2805
  } else {
2681
2806
  endpoint.searchParams.append("access_token", accessToken);
2682
2807
  }
@@ -2697,9 +2822,8 @@ var buildOAuth2Client = async (meta, config) => {
2697
2822
  params.set("grant_type", "refresh_token");
2698
2823
  params.set("refresh_token", refreshToken);
2699
2824
  const { clientId } = config;
2700
- let clientSecretValue;
2701
- if (hasClientSecret(config)) {
2702
- clientSecretValue = config.clientSecret;
2825
+ const clientSecretValue = await resolveClientSecret();
2826
+ if (clientSecretValue) {
2703
2827
  params.set("client_id", clientId);
2704
2828
  params.set("client_secret", clientSecretValue);
2705
2829
  }
@@ -2714,60 +2838,99 @@ var buildOAuth2Client = async (meta, config) => {
2714
2838
  const response = await fetch(request);
2715
2839
  if (!response.ok)
2716
2840
  throw await createOAuth2FetchError(response);
2717
- return response.json();
2841
+ return parseOAuth2TokenResponse(await response.json());
2718
2842
  },
2719
- async revokeToken(token) {
2843
+ resolveRevocationInput(context) {
2720
2844
  const { revocationRequest } = meta;
2721
2845
  if (!revocationRequest) {
2722
2846
  throw new Error("Token revocation not defined for this provider");
2723
2847
  }
2724
- const { url, authIn, body, headers, tokenParamName } = revocationRequest;
2848
+ const inputSource = revocationRequest.inputSource ?? "accessToken";
2849
+ const input = context[inputSource];
2850
+ if (input === undefined) {
2851
+ throw new Error(`Revocation requires ${inputSource}, but it was not provided`);
2852
+ }
2853
+ const expectsNumber = revocationRequest.authIn !== "header" && revocationRequest.inputType === "number";
2854
+ if (expectsNumber && (typeof input !== "number" || !Number.isFinite(input))) {
2855
+ throw new TypeError("This provider requires a numeric revocation input");
2856
+ }
2857
+ if (!expectsNumber && typeof input !== "string") {
2858
+ throw new TypeError("This provider requires a string revocation input");
2859
+ }
2860
+ return input;
2861
+ },
2862
+ async revokeToken(input) {
2863
+ const { revocationRequest } = meta;
2864
+ if (!revocationRequest) {
2865
+ throw new Error("Token revocation not defined for this provider");
2866
+ }
2867
+ if (revocationRequest.authIn !== "header" && revocationRequest.inputType === "number" && (typeof input !== "number" || !Number.isFinite(input))) {
2868
+ throw new TypeError("This provider requires a numeric revocation input");
2869
+ }
2870
+ const {
2871
+ url,
2872
+ authIn,
2873
+ body,
2874
+ encoding,
2875
+ headers,
2876
+ includeClientCredentials = true,
2877
+ tokenParamName,
2878
+ validateResponse
2879
+ } = revocationRequest;
2725
2880
  const endpoint = await resolveConfigProp(url);
2726
2881
  const resolvedBody = await resolveConfigProp(body);
2727
- const revocationBody = new URLSearchParams(resolvedBody);
2882
+ const revocationBody = resolvedBody === undefined ? undefined : new URLSearchParams(resolvedBody);
2728
2883
  const revocationHeaders = new Headers(headers && await resolveConfigProp(headers));
2729
2884
  const { clientId } = config;
2730
- const clientSecret = hasClientSecret(config) ? config.clientSecret : undefined;
2885
+ const clientSecret = await resolveClientSecret();
2731
2886
  let request;
2732
2887
  if (authIn === "body") {
2733
- revocationBody.set(tokenParamName, token);
2734
- revocationBody.set("client_id", clientId);
2735
- if (clientSecret)
2736
- revocationBody.set("client_secret", clientSecret);
2888
+ const bodyWithToken = revocationBody ?? new URLSearchParams;
2889
+ bodyWithToken.set(tokenParamName, String(input));
2890
+ const hasAuthorizationHeader = revocationHeaders.has("Authorization");
2891
+ if (includeClientCredentials && !hasAuthorizationHeader)
2892
+ bodyWithToken.set("client_id", clientId);
2893
+ if (includeClientCredentials && !hasAuthorizationHeader && clientSecret)
2894
+ bodyWithToken.set("client_secret", clientSecret);
2737
2895
  request = createOAuth2Request({
2738
- authIn: "body",
2739
- body: revocationBody,
2896
+ authIn: hasAuthorizationHeader || !includeClientCredentials ? "query" : "body",
2897
+ body: bodyWithToken,
2740
2898
  clientId,
2741
2899
  clientSecret,
2742
- encoding: "application/x-www-form-urlencoded",
2900
+ encoding,
2743
2901
  headers: revocationHeaders,
2744
2902
  url: endpoint.toString()
2745
2903
  });
2746
2904
  } else if (authIn === "header") {
2747
- revocationHeaders.set("Authorization", `Bearer ${token}`);
2905
+ revocationHeaders.set("Authorization", `Bearer ${String(input)}`);
2748
2906
  request = createOAuth2Request({
2749
- authIn: "header",
2907
+ authIn: "query",
2750
2908
  body: revocationBody,
2751
2909
  clientId,
2752
- clientSecret,
2753
- encoding: "application/x-www-form-urlencoded",
2910
+ encoding,
2754
2911
  headers: revocationHeaders,
2755
2912
  url: endpoint.toString()
2756
2913
  });
2757
2914
  } else {
2915
+ const queryEndpoint = new URL(endpoint);
2916
+ queryEndpoint.searchParams.set(tokenParamName, String(input));
2758
2917
  request = createOAuth2Request({
2759
2918
  authIn: "query",
2760
2919
  body: revocationBody,
2761
2920
  clientId,
2762
- clientSecret,
2763
- encoding: "application/x-www-form-urlencoded",
2921
+ encoding,
2764
2922
  headers: revocationHeaders,
2765
- url: `${endpoint.toString()}?${tokenParamName}=${token}`
2923
+ url: queryEndpoint.toString()
2766
2924
  });
2767
2925
  }
2768
2926
  const response = await fetch(request);
2769
2927
  if (!response.ok)
2770
2928
  throw await createOAuth2FetchError(response);
2929
+ if (validateResponse) {
2930
+ await validateResponse(await response.json().catch(() => {
2931
+ return;
2932
+ }));
2933
+ }
2771
2934
  },
2772
2935
  async validateAuthorizationCode(opts) {
2773
2936
  const { code, codeVerifier } = opts;
@@ -2793,32 +2956,27 @@ var buildOAuth2Client = async (meta, config) => {
2793
2956
  authIn,
2794
2957
  body: payload,
2795
2958
  clientId: config.clientId,
2796
- clientSecret: hasClientSecret(config) ? config.clientSecret : undefined,
2959
+ clientSecret: await resolveClientSecret(),
2797
2960
  encoding,
2798
2961
  url: tokenUrl
2799
2962
  });
2800
2963
  const response = await fetch(request);
2801
2964
  if (!response.ok)
2802
2965
  throw await createOAuth2FetchError(response);
2803
- const tokenResponse = await response.json();
2804
- if (!tokenResponse || typeof tokenResponse !== "object") {
2805
- throw new Error("OAuth token endpoint returned a non-object response");
2806
- }
2807
- const oauthError = Reflect.get(tokenResponse, "error");
2808
- if (typeof oauthError === "string" && oauthError.length > 0) {
2809
- throw new Error(`OAuth token exchange failed: ${oauthError}`);
2810
- }
2811
- const nestedToken = meta.accessTokenPath ? readPath(tokenResponse, meta.accessTokenPath) : undefined;
2812
- if (typeof nestedToken === "string" && nestedToken.length > 0 && tokenResponse && typeof tokenResponse === "object") {
2813
- tokenResponse.access_token = nestedToken;
2814
- }
2815
- const accessToken = Reflect.get(tokenResponse, "access_token");
2816
- if (typeof accessToken !== "string" || accessToken.length === 0) {
2817
- throw new Error("OAuth token endpoint returned no access_token");
2818
- }
2819
- return tokenResponse;
2966
+ return parseOAuth2TokenResponse(await response.json(), meta.accessTokenPath);
2820
2967
  }
2821
2968
  };
2969
+ if (!meta.profileRequest) {
2970
+ Reflect.deleteProperty(client, "fetchUserProfile");
2971
+ }
2972
+ if (!meta.isRefreshable) {
2973
+ Reflect.deleteProperty(client, "refreshAccessToken");
2974
+ }
2975
+ if (!meta.revocationRequest) {
2976
+ Reflect.deleteProperty(client, "resolveRevocationInput");
2977
+ Reflect.deleteProperty(client, "revokeToken");
2978
+ }
2979
+ return client;
2822
2980
  };
2823
2981
  var createCustomOAuth2Client = (providerConfig, credentials) => buildOAuth2Client(providerConfig, credentials);
2824
2982
  var createOAuth2Client = (providerName, config) => buildOAuth2Client(providers[providerName], config);
@@ -4576,7 +4734,15 @@ var instantiateUserSession = async ({
4576
4734
  providerInstance,
4577
4735
  tokenResponse
4578
4736
  });
4579
- const { accessToken, refreshToken, userIdentity } = authorization;
4737
+ const {
4738
+ accessToken,
4739
+ oauthSubject: resolvedOAuthSubject,
4740
+ refreshToken,
4741
+ userIdentity
4742
+ } = authorization;
4743
+ const providerMeta = providerConfiguration ?? (isValidProviderOption(authProvider) ? providers[authProvider] : undefined);
4744
+ const extractedSubject = providerMeta ? extractPropFromIdentity(userIdentity, providerMeta.subject, providerMeta.subjectType) : Reflect.get(userIdentity, "sub");
4745
+ const oauthSubject = resolvedOAuthSubject ?? (typeof extractedSubject === "string" || typeof extractedSubject === "number" ? extractedSubject : undefined);
4580
4746
  const userSession = validateSession({ session, user_session_id });
4581
4747
  const userSessionId = getUserSessionId({
4582
4748
  cookieSecure,
@@ -4593,6 +4759,7 @@ var instantiateUserSession = async ({
4593
4759
  accessToken,
4594
4760
  authenticatedAt: Date.now(),
4595
4761
  expiresAt: Date.now() + sessionDurationMs,
4762
+ oauthSubject,
4596
4763
  refreshToken,
4597
4764
  user
4598
4765
  };
@@ -4602,6 +4769,7 @@ var instantiateUserSession = async ({
4602
4769
  if (existingUnregistered) {
4603
4770
  existingUnregistered.accessToken = accessToken;
4604
4771
  existingUnregistered.expiresAt = Date.now() + unregisteredSessionDurationMs;
4772
+ existingUnregistered.oauthSubject = oauthSubject;
4605
4773
  existingUnregistered.refreshToken = refreshToken;
4606
4774
  existingUnregistered.userIdentity = userIdentity;
4607
4775
  return response;
@@ -4609,6 +4777,7 @@ var instantiateUserSession = async ({
4609
4777
  unregisteredSession[userSessionId] = {
4610
4778
  accessToken,
4611
4779
  expiresAt: Date.now() + unregisteredSessionDurationMs,
4780
+ oauthSubject,
4612
4781
  refreshToken,
4613
4782
  userIdentity
4614
4783
  };
@@ -4657,6 +4826,9 @@ var resolveOAuthAuthorization = async ({
4657
4826
  accessToken = readOptionalString(withingsBody, "access_token") ?? accessToken;
4658
4827
  refreshToken = readOptionalString(withingsBody, "refresh_token") ?? refreshToken;
4659
4828
  } else {
4829
+ if (!isProfileOAuth2Client(providerInstance)) {
4830
+ throw new Error(`Provider "${authProvider}" returned no identity and has no profile endpoint`);
4831
+ }
4660
4832
  userIdentity = normalizeProviderIdentity({
4661
4833
  identity: await providerInstance.fetchUserProfile(accessToken),
4662
4834
  providerConfiguration: meta,
@@ -4664,9 +4836,14 @@ var resolveOAuthAuthorization = async ({
4664
4836
  });
4665
4837
  }
4666
4838
  const tokenType = Reflect.get(tokenResponse, "token_type");
4839
+ const oauthSubject = extractPropFromIdentity(userIdentity, meta.subject, meta.subjectType);
4840
+ if (typeof oauthSubject !== "string" && typeof oauthSubject !== "number") {
4841
+ throw new Error(`Provider "${authProvider}" returned an invalid OAuth subject`);
4842
+ }
4667
4843
  return {
4668
4844
  accessToken,
4669
4845
  expiresAt: resolveOAuthTokenExpiresAt(tokenResponse, now),
4846
+ oauthSubject,
4670
4847
  refreshToken,
4671
4848
  tokenType: typeof tokenType === "string" ? tokenType : undefined,
4672
4849
  userIdentity
@@ -6614,10 +6791,10 @@ var exchangeBackchannelAuth = async ({
6614
6791
  init_constants();
6615
6792
  var CLIENT_ASSERTION_TYPE = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer";
6616
6793
  var MAX_ASSERTION_LIFETIME_MINUTES = 5;
6617
- var SECONDS_PER_MINUTE = 60;
6618
- var MAX_ASSERTION_LIFETIME_MS = MAX_ASSERTION_LIFETIME_MINUTES * SECONDS_PER_MINUTE * MILLISECONDS_IN_A_SECOND;
6794
+ var SECONDS_PER_MINUTE2 = 60;
6795
+ var MAX_ASSERTION_LIFETIME_MS = MAX_ASSERTION_LIFETIME_MINUTES * SECONDS_PER_MINUTE2 * MILLISECONDS_IN_A_SECOND;
6619
6796
  var jwksCache = new Map;
6620
- var JWKS_CACHE_TTL_MS = SECONDS_PER_MINUTE * MILLISECONDS_IN_A_SECOND;
6797
+ var JWKS_CACHE_TTL_MS = SECONDS_PER_MINUTE2 * MILLISECONDS_IN_A_SECOND;
6621
6798
  var JWKS_FETCH_TIMEOUT_SECONDS = 5;
6622
6799
  var JWKS_FETCH_TIMEOUT_MS = JWKS_FETCH_TIMEOUT_SECONDS * MILLISECONDS_IN_A_SECOND;
6623
6800
  var fetchJwksUri = async (jwksUri) => {
@@ -10174,6 +10351,7 @@ var callback = ({
10174
10351
  // src/routes/profile.ts
10175
10352
  import { Elysia as Elysia29, t as t22 } from "elysia";
10176
10353
  var profile = ({
10354
+ authSessionStore,
10177
10355
  clientProviders,
10178
10356
  profileRoute = "/oauth2/profile",
10179
10357
  onProfileSuccess,
@@ -10188,9 +10366,6 @@ var profile = ({
10188
10366
  if (auth_provider.value === undefined) {
10189
10367
  return status("Unauthorized", "No auth provider found");
10190
10368
  }
10191
- if (!isValidProviderOption(auth_provider.value)) {
10192
- return status("Unauthorized", "Invalid provider");
10193
- }
10194
10369
  if (user_session_id.value === undefined) {
10195
10370
  return status("Unauthorized", "No user session found");
10196
10371
  }
@@ -10203,7 +10378,14 @@ var profile = ({
10203
10378
  return status("Unauthorized", resolvedProvider.error);
10204
10379
  }
10205
10380
  const { clientName, providerInstance } = resolvedProvider.entry;
10206
- const userSession = session[user_session_id.value];
10381
+ if (!isProfileOAuth2Client(providerInstance)) {
10382
+ return status("Not Implemented", "Provider does not expose a profile endpoint");
10383
+ }
10384
+ const userSession = await loadSessionFromSource({
10385
+ authSessionStore,
10386
+ session,
10387
+ userSessionId: user_session_id.value
10388
+ });
10207
10389
  if (userSession === undefined) {
10208
10390
  return status("Unauthorized", "No user session found");
10209
10391
  }
@@ -10255,9 +10437,6 @@ var refresh = ({
10255
10437
  if (auth_provider.value === undefined) {
10256
10438
  return status("Unauthorized", "No auth provider found");
10257
10439
  }
10258
- if (!isValidProviderOption(auth_provider.value)) {
10259
- return status("Bad Request", "Invalid provider");
10260
- }
10261
10440
  if (user_session_id.value === undefined) {
10262
10441
  return status("Unauthorized", "No user session found");
10263
10442
  }
@@ -10279,7 +10458,7 @@ var refresh = ({
10279
10458
  return status("Unauthorized", "No user session found");
10280
10459
  }
10281
10460
  const { refreshToken } = userSession;
10282
- if (!isRefreshableOAuth2Client(auth_provider.value, providerInstance)) {
10461
+ if (!isRefreshableOAuth2Client(providerInstance)) {
10283
10462
  return status("Not Implemented", "Provider is not refreshable");
10284
10463
  }
10285
10464
  if (refreshToken === undefined) {
@@ -10339,9 +10518,6 @@ var revoke = ({
10339
10518
  if (auth_provider.value === undefined) {
10340
10519
  return status("Unauthorized", "No auth provider found");
10341
10520
  }
10342
- if (!isValidProviderOption(auth_provider.value)) {
10343
- return status("Bad Request", "Invalid provider");
10344
- }
10345
10521
  if (user_session_id.value === undefined) {
10346
10522
  return status("Unauthorized", "No user session found");
10347
10523
  }
@@ -10354,7 +10530,7 @@ var revoke = ({
10354
10530
  return status("Unauthorized", resolvedProvider.error);
10355
10531
  }
10356
10532
  const { clientName, providerInstance } = resolvedProvider.entry;
10357
- if (!isRevocableOAuth2Client(auth_provider.value, providerInstance)) {
10533
+ if (!isRevocableOAuth2Client(providerInstance)) {
10358
10534
  return status("Not Implemented", "Provider does not support revocation");
10359
10535
  }
10360
10536
  const userSession = await loadSessionFromSource({
@@ -10365,16 +10541,21 @@ var revoke = ({
10365
10541
  if (userSession === undefined) {
10366
10542
  return status("Unauthorized", "No user session found");
10367
10543
  }
10368
- const { accessToken } = userSession;
10544
+ const { accessToken, oauthSubject, refreshToken } = userSession;
10369
10545
  if (accessToken === undefined) {
10370
10546
  return status("Bad Request", "Session has no access token to revoke");
10371
10547
  }
10372
10548
  try {
10373
- await providerInstance.revokeToken(accessToken);
10549
+ const tokenToRevoke = providerInstance.resolveRevocationInput({
10550
+ accessToken,
10551
+ refreshToken,
10552
+ subject: oauthSubject
10553
+ });
10554
+ await providerInstance.revokeToken(tokenToRevoke);
10374
10555
  await onRevocationSuccess?.({
10375
10556
  authClient: clientName,
10376
10557
  authProvider: auth_provider.value,
10377
- tokenToRevoke: accessToken
10558
+ tokenToRevoke
10378
10559
  });
10379
10560
  return new Response("Token revoked", {
10380
10561
  status: 204
@@ -24214,6 +24395,7 @@ var authSessionsTable = pgTable("auth_sessions", {
24214
24395
  created_at: timestamp("created_at").notNull().defaultNow(),
24215
24396
  expires_at_ms: bigint("expires_at_ms", { mode: "number" }).notNull(),
24216
24397
  id: varchar("id", { length: 255 }).primaryKey(),
24398
+ oauth_subject_json: jsonb("oauth_subject_json").$type(),
24217
24399
  refresh_token: text("refresh_token"),
24218
24400
  updated_at: timestamp("updated_at").notNull().defaultNow(),
24219
24401
  user_json: jsonb("user_json").$type().notNull()
@@ -24223,6 +24405,7 @@ var authUnregisteredSessionsTable = pgTable("auth_unregistered_sessions", {
24223
24405
  created_at: timestamp("created_at").notNull().defaultNow(),
24224
24406
  expires_at_ms: bigint("expires_at_ms", { mode: "number" }).notNull(),
24225
24407
  id: varchar("id", { length: 255 }).primaryKey(),
24408
+ oauth_subject_json: jsonb("oauth_subject_json").$type(),
24226
24409
  refresh_token: text("refresh_token"),
24227
24410
  session_information_json: jsonb("session_information_json").$type(),
24228
24411
  updated_at: timestamp("updated_at").notNull().defaultNow(),
@@ -24240,12 +24423,14 @@ var toSessionData = (row, decodeUser) => ({
24240
24423
  accessToken: row.access_token ?? undefined,
24241
24424
  authenticatedAt: row.authenticated_at_ms ?? undefined,
24242
24425
  expiresAt: row.expires_at_ms,
24426
+ oauthSubject: row.oauth_subject_json ?? undefined,
24243
24427
  refreshToken: row.refresh_token ?? undefined,
24244
24428
  user: cloneUser(decodeUser(row.user_json))
24245
24429
  });
24246
24430
  var toUnregisteredSessionData = (row) => ({
24247
24431
  accessToken: row.access_token ?? undefined,
24248
24432
  expiresAt: row.expires_at_ms,
24433
+ oauthSubject: row.oauth_subject_json ?? undefined,
24249
24434
  refreshToken: row.refresh_token ?? undefined,
24250
24435
  sessionInformation: cloneRecord(row.session_information_json ?? undefined),
24251
24436
  userIdentity: cloneRecord(row.user_identity_json ?? undefined)
@@ -24290,6 +24475,7 @@ var createNeonAuthSessionStore = (databaseUrl, decodeUser) => {
24290
24475
  authenticated_at_ms: value.authenticatedAt ?? null,
24291
24476
  expires_at_ms: value.expiresAt,
24292
24477
  id,
24478
+ oauth_subject_json: value.oauthSubject ?? null,
24293
24479
  refresh_token: value.refreshToken ?? null,
24294
24480
  updated_at: new Date,
24295
24481
  user_json: value.user ?? {}
@@ -24298,6 +24484,7 @@ var createNeonAuthSessionStore = (databaseUrl, decodeUser) => {
24298
24484
  access_token: value.accessToken ?? null,
24299
24485
  authenticated_at_ms: value.authenticatedAt ?? null,
24300
24486
  expires_at_ms: value.expiresAt,
24487
+ oauth_subject_json: value.oauthSubject ?? null,
24301
24488
  refresh_token: value.refreshToken ?? null,
24302
24489
  updated_at: new Date,
24303
24490
  user_json: value.user ?? {}
@@ -24310,6 +24497,7 @@ var createNeonAuthSessionStore = (databaseUrl, decodeUser) => {
24310
24497
  access_token: value.accessToken ?? null,
24311
24498
  expires_at_ms: value.expiresAt,
24312
24499
  id,
24500
+ oauth_subject_json: value.oauthSubject ?? null,
24313
24501
  refresh_token: value.refreshToken ?? null,
24314
24502
  session_information_json: value.sessionInformation ?? null,
24315
24503
  updated_at: new Date,
@@ -24318,6 +24506,7 @@ var createNeonAuthSessionStore = (databaseUrl, decodeUser) => {
24318
24506
  set: {
24319
24507
  access_token: value.accessToken ?? null,
24320
24508
  expires_at_ms: value.expiresAt,
24509
+ oauth_subject_json: value.oauthSubject ?? null,
24321
24510
  refresh_token: value.refreshToken ?? null,
24322
24511
  session_information_json: value.sessionInformation ?? null,
24323
24512
  updated_at: new Date,
@@ -30357,6 +30546,7 @@ var sessionSchema = Type.Object({
30357
30546
  authenticatedAt: Type.Optional(Type.Number()),
30358
30547
  expiresAt: Type.Number(),
30359
30548
  impersonator: Type.Optional(impersonatorSchema),
30549
+ oauthSubject: Type.Optional(Type.Union([Type.String(), Type.Number()])),
30360
30550
  refreshToken: Type.Optional(Type.String()),
30361
30551
  samlLogout: Type.Optional(Type.Object({
30362
30552
  connectionId: Type.String(),
@@ -30368,6 +30558,7 @@ var sessionSchema = Type.Object({
30368
30558
  var unregisteredSessionSchema = Type.Object({
30369
30559
  accessToken: Type.Optional(Type.String()),
30370
30560
  expiresAt: Type.Number(),
30561
+ oauthSubject: Type.Optional(Type.Union([Type.String(), Type.Number()])),
30371
30562
  refreshToken: Type.Optional(Type.String()),
30372
30563
  sessionInformation: Type.Optional(Type.Record(Type.String(), Type.Unknown())),
30373
30564
  userIdentity: Type.Optional(Type.Record(Type.String(), Type.Unknown()))
@@ -33452,23 +33643,28 @@ var portableJsonb = customType({
33452
33643
  fromDriver: (value) => typeof value === "string" ? JSON.parse(value) : value,
33453
33644
  toDriver: (value) => JSON.stringify(value)
33454
33645
  });
33455
- var agentDelegationsTable = pgTable("auth_agent_delegations", {
33646
+ var bunSqlJsonb = customType({
33647
+ dataType: () => "jsonb",
33648
+ fromDriver: (value) => typeof value === "string" ? JSON.parse(value) : value,
33649
+ toDriver: (value) => value
33650
+ });
33651
+ var createAgentDelegationsTable = (json5) => pgTable("auth_agent_delegations", {
33456
33652
  agent_id: varchar("agent_id", { length: ID_LENGTH7 }).notNull(),
33457
- authorization_details: portableJsonb("authorization_details").$type(),
33653
+ authorization_details: json5("authorization_details").$type(),
33458
33654
  created_at_ms: bigint("created_at_ms", { mode: "number" }).notNull(),
33459
33655
  delegation_id: varchar("delegation_id", {
33460
33656
  length: ID_LENGTH7
33461
33657
  }).primaryKey(),
33462
33658
  expires_at_ms: bigint("expires_at_ms", { mode: "number" }),
33463
33659
  organization_id: varchar("organization_id", { length: ID_LENGTH7 }),
33464
- scopes: portableJsonb("scopes").$type().notNull().default([]),
33660
+ scopes: json5("scopes").$type().notNull().default([]),
33465
33661
  status: varchar("status", { length: STATUS_LENGTH2 }).$type().notNull(),
33466
33662
  updated_at_ms: bigint("updated_at_ms", { mode: "number" }).notNull(),
33467
33663
  user_id: varchar("user_id", { length: ID_LENGTH7 }).notNull()
33468
33664
  });
33469
- var agentIdentityRegistrationsTable = pgTable("auth_agent_identity_registrations", {
33665
+ var createAgentIdentityRegistrationsTable = (json5) => pgTable("auth_agent_identity_registrations", {
33470
33666
  agent_id: varchar("agent_id", { length: ID_LENGTH7 }).notNull().unique(),
33471
- claim_attempt: portableJsonb("claim_attempt").$type(),
33667
+ claim_attempt: json5("claim_attempt").$type(),
33472
33668
  claim_attempt_token_hash: varchar("claim_attempt_token_hash", {
33473
33669
  length: ID_LENGTH7
33474
33670
  }).unique(),
@@ -33478,8 +33674,12 @@ var agentIdentityRegistrationsTable = pgTable("auth_agent_identity_registrations
33478
33674
  claim_token_hash: varchar("claim_token_hash", {
33479
33675
  length: ID_LENGTH7
33480
33676
  }).notNull().unique(),
33481
- created_at_ms: bigint("created_at_ms", { mode: "number" }).notNull(),
33482
- expires_at_ms: bigint("expires_at_ms", { mode: "number" }).notNull(),
33677
+ created_at_ms: bigint("created_at_ms", {
33678
+ mode: "number"
33679
+ }).notNull(),
33680
+ expires_at_ms: bigint("expires_at_ms", {
33681
+ mode: "number"
33682
+ }).notNull(),
33483
33683
  kind: varchar("kind", { length: 32 }).$type().notNull(),
33484
33684
  last_polled_at_ms: bigint("last_polled_at_ms", { mode: "number" }),
33485
33685
  login_hint: varchar("login_hint", { length: ID_LENGTH7 }),
@@ -33487,27 +33687,37 @@ var agentIdentityRegistrationsTable = pgTable("auth_agent_identity_registrations
33487
33687
  length: ID_LENGTH7
33488
33688
  }).primaryKey(),
33489
33689
  status: varchar("status", { length: STATUS_LENGTH2 }).$type().notNull(),
33490
- updated_at_ms: bigint("updated_at_ms", { mode: "number" }).notNull(),
33690
+ updated_at_ms: bigint("updated_at_ms", {
33691
+ mode: "number"
33692
+ }).notNull(),
33491
33693
  upstream_client_id: varchar("upstream_client_id", {
33492
33694
  length: ID_LENGTH7
33493
33695
  }),
33494
33696
  upstream_issuer: varchar("upstream_issuer", { length: ID_LENGTH7 }),
33495
- upstream_subject: varchar("upstream_subject", { length: ID_LENGTH7 }),
33697
+ upstream_subject: varchar("upstream_subject", {
33698
+ length: ID_LENGTH7
33699
+ }),
33496
33700
  user_id: varchar("user_id", { length: ID_LENGTH7 }),
33497
33701
  version: integer("version").notNull()
33498
33702
  }, (table) => [
33499
33703
  uniqueIndex("auth_agent_identity_upstream_unique").on(table.upstream_issuer, table.upstream_subject, table.upstream_client_id)
33500
33704
  ]);
33501
- var agentRegistrationsTable = pgTable("auth_agent_registrations", {
33705
+ var createAgentRegistrationsTable = (json5) => pgTable("auth_agent_registrations", {
33502
33706
  agent_id: varchar("agent_id", { length: ID_LENGTH7 }).primaryKey(),
33503
- allowed_scopes: portableJsonb("allowed_scopes").$type().notNull().default([]),
33707
+ allowed_scopes: json5("allowed_scopes").$type().notNull().default([]),
33504
33708
  client_id: varchar("client_id", { length: ID_LENGTH7 }).unique(),
33505
33709
  created_at_ms: bigint("created_at_ms", { mode: "number" }).notNull(),
33506
- metadata: portableJsonb("metadata").$type(),
33710
+ metadata: json5("metadata").$type(),
33507
33711
  name: varchar("name", { length: NAME_LENGTH }).notNull(),
33508
33712
  status: varchar("status", { length: STATUS_LENGTH2 }).$type().notNull(),
33509
33713
  updated_at_ms: bigint("updated_at_ms", { mode: "number" }).notNull()
33510
33714
  });
33715
+ var agentDelegationsBunSqlTable = createAgentDelegationsTable(bunSqlJsonb);
33716
+ var agentDelegationsTable = createAgentDelegationsTable(portableJsonb);
33717
+ var agentIdentityRegistrationsBunSqlTable = createAgentIdentityRegistrationsTable(bunSqlJsonb);
33718
+ var agentIdentityRegistrationsTable = createAgentIdentityRegistrationsTable(portableJsonb);
33719
+ var agentRegistrationsBunSqlTable = createAgentRegistrationsTable(bunSqlJsonb);
33720
+ var agentRegistrationsTable = createAgentRegistrationsTable(portableJsonb);
33511
33721
  var toRegistration = (row) => ({
33512
33722
  agentId: row.agent_id,
33513
33723
  allowedScopes: row.allowed_scopes,
@@ -33574,24 +33784,24 @@ var identityRegistrationValues = (registration) => ({
33574
33784
  var createNeonAgentDelegationStore = (databaseUrl) => createDrizzleAgentDelegationStore(createNeonDatabase(databaseUrl));
33575
33785
  var createNeonAgentIdentityRegistrationStore = (databaseUrl) => createPostgresAgentIdentityRegistrationStore(createNeonDatabase(databaseUrl));
33576
33786
  var createNeonAgentRegistrationStore = (databaseUrl) => createPostgresAgentRegistrationStore(createNeonDatabase(databaseUrl));
33577
- var createDrizzleAgentDelegationStore = (db) => ({
33787
+ var createDrizzleAgentDelegationStoreFor = (db, table) => ({
33578
33788
  findActiveDelegation: async ({
33579
33789
  agentId,
33580
33790
  now = Date.now(),
33581
33791
  organizationId,
33582
33792
  userId
33583
33793
  }) => {
33584
- const organizationCondition = organizationId === undefined ? isNull(agentDelegationsTable.organization_id) : eq(agentDelegationsTable.organization_id, organizationId);
33585
- const [row] = await db.select().from(agentDelegationsTable).where(and(eq(agentDelegationsTable.agent_id, agentId), eq(agentDelegationsTable.user_id, userId), organizationCondition, eq(agentDelegationsTable.status, "active"), or(isNull(agentDelegationsTable.expires_at_ms), gt(agentDelegationsTable.expires_at_ms, now)))).orderBy(desc(agentDelegationsTable.updated_at_ms)).limit(1);
33794
+ const organizationCondition = organizationId === undefined ? isNull(table.organization_id) : eq(table.organization_id, organizationId);
33795
+ const [row] = await db.select().from(table).where(and(eq(table.agent_id, agentId), eq(table.user_id, userId), organizationCondition, eq(table.status, "active"), or(isNull(table.expires_at_ms), gt(table.expires_at_ms, now)))).orderBy(desc(table.updated_at_ms)).limit(1);
33586
33796
  return row === undefined ? undefined : toDelegation(row);
33587
33797
  },
33588
33798
  findByDelegationId: async (delegationId) => {
33589
- const [row] = await db.select().from(agentDelegationsTable).where(eq(agentDelegationsTable.delegation_id, delegationId)).limit(1);
33799
+ const [row] = await db.select().from(table).where(eq(table.delegation_id, delegationId)).limit(1);
33590
33800
  return row === undefined ? undefined : toDelegation(row);
33591
33801
  },
33592
33802
  listDelegations: async (agentId) => {
33593
- const base = db.select().from(agentDelegationsTable);
33594
- const rows = await (agentId === undefined ? base.orderBy(desc(agentDelegationsTable.created_at_ms)) : base.where(eq(agentDelegationsTable.agent_id, agentId)).orderBy(desc(agentDelegationsTable.created_at_ms)));
33803
+ const base = db.select().from(table);
33804
+ const rows = await (agentId === undefined ? base.orderBy(desc(table.created_at_ms)) : base.where(eq(table.agent_id, agentId)).orderBy(desc(table.created_at_ms)));
33595
33805
  return rows.map(toDelegation);
33596
33806
  },
33597
33807
  saveDelegation: async (delegation) => {
@@ -33607,36 +33817,38 @@ var createDrizzleAgentDelegationStore = (db) => ({
33607
33817
  updated_at_ms: delegation.updatedAt,
33608
33818
  user_id: delegation.userId
33609
33819
  };
33610
- await db.insert(agentDelegationsTable).values(values).onConflictDoUpdate({
33820
+ await db.insert(table).values(values).onConflictDoUpdate({
33611
33821
  set: values,
33612
- target: agentDelegationsTable.delegation_id
33822
+ target: table.delegation_id
33613
33823
  });
33614
33824
  }
33615
33825
  });
33826
+ var createDrizzleAgentDelegationStore = (db) => createDrizzleAgentDelegationStoreFor(db, agentDelegationsTable);
33827
+ var createBunSqlDrizzleAgentDelegationStore = (db) => createDrizzleAgentDelegationStoreFor(db, agentDelegationsBunSqlTable);
33616
33828
  var createPostgresAgentDelegationStore = createDrizzleAgentDelegationStore;
33617
- var createPostgresAgentIdentityRegistrationStore = (db) => ({
33829
+ var createPostgresAgentIdentityRegistrationStoreFor = (db, table) => ({
33618
33830
  create: async (registration) => {
33619
- const rows = await db.insert(agentIdentityRegistrationsTable).values(identityRegistrationValues(registration)).onConflictDoNothing().returning({ id: agentIdentityRegistrationsTable.registration_id });
33831
+ const rows = await db.insert(table).values(identityRegistrationValues(registration)).onConflictDoNothing().returning({ id: table.registration_id });
33620
33832
  return rows.length === 1;
33621
33833
  },
33622
33834
  findByAgentId: async (agentId) => {
33623
- const [row] = await db.select().from(agentIdentityRegistrationsTable).where(eq(agentIdentityRegistrationsTable.agent_id, agentId)).limit(1);
33835
+ const [row] = await db.select().from(table).where(eq(table.agent_id, agentId)).limit(1);
33624
33836
  return row === undefined ? undefined : toIdentityRegistration(row);
33625
33837
  },
33626
33838
  findByAttemptTokenHash: async (attemptTokenHash) => {
33627
- const [row] = await db.select().from(agentIdentityRegistrationsTable).where(eq(agentIdentityRegistrationsTable.claim_attempt_token_hash, attemptTokenHash)).limit(1);
33839
+ const [row] = await db.select().from(table).where(eq(table.claim_attempt_token_hash, attemptTokenHash)).limit(1);
33628
33840
  return row === undefined ? undefined : toIdentityRegistration(row);
33629
33841
  },
33630
33842
  findByClaimTokenHash: async (claimTokenHash) => {
33631
- const [row] = await db.select().from(agentIdentityRegistrationsTable).where(eq(agentIdentityRegistrationsTable.claim_token_hash, claimTokenHash)).limit(1);
33843
+ const [row] = await db.select().from(table).where(eq(table.claim_token_hash, claimTokenHash)).limit(1);
33632
33844
  return row === undefined ? undefined : toIdentityRegistration(row);
33633
33845
  },
33634
33846
  findByRegistrationId: async (registrationId) => {
33635
- const [row] = await db.select().from(agentIdentityRegistrationsTable).where(eq(agentIdentityRegistrationsTable.registration_id, registrationId)).limit(1);
33847
+ const [row] = await db.select().from(table).where(eq(table.registration_id, registrationId)).limit(1);
33636
33848
  return row === undefined ? undefined : toIdentityRegistration(row);
33637
33849
  },
33638
33850
  findByUpstreamIdentity: async ({ clientId, issuer, subject }) => {
33639
- const [row] = await db.select().from(agentIdentityRegistrationsTable).where(and(eq(agentIdentityRegistrationsTable.upstream_client_id, clientId), eq(agentIdentityRegistrationsTable.upstream_issuer, issuer), eq(agentIdentityRegistrationsTable.upstream_subject, subject))).limit(1);
33851
+ const [row] = await db.select().from(table).where(and(eq(table.upstream_client_id, clientId), eq(table.upstream_issuer, issuer), eq(table.upstream_subject, subject))).limit(1);
33640
33852
  return row === undefined ? undefined : toIdentityRegistration(row);
33641
33853
  },
33642
33854
  replace: async (registration, expectedVersion) => {
@@ -33645,21 +33857,23 @@ var createPostgresAgentIdentityRegistrationStore = (db) => ({
33645
33857
  version: expectedVersion + 1
33646
33858
  };
33647
33859
  const values = identityRegistrationValues(next);
33648
- const rows = await db.update(agentIdentityRegistrationsTable).set(values).where(and(eq(agentIdentityRegistrationsTable.registration_id, registration.registrationId), eq(agentIdentityRegistrationsTable.version, expectedVersion))).returning({ id: agentIdentityRegistrationsTable.registration_id });
33860
+ const rows = await db.update(table).set(values).where(and(eq(table.registration_id, registration.registrationId), eq(table.version, expectedVersion))).returning({ id: table.registration_id });
33649
33861
  return rows.length === 1;
33650
33862
  }
33651
33863
  });
33652
- var createPostgresAgentRegistrationStore = (db) => ({
33864
+ var createBunSqlDrizzleAgentIdentityRegistrationStore = (db) => createPostgresAgentIdentityRegistrationStoreFor(db, agentIdentityRegistrationsBunSqlTable);
33865
+ var createPostgresAgentIdentityRegistrationStore = (db) => createPostgresAgentIdentityRegistrationStoreFor(db, agentIdentityRegistrationsTable);
33866
+ var createPostgresAgentRegistrationStoreFor = (db, table) => ({
33653
33867
  findByAgentId: async (agentId) => {
33654
- const [row] = await db.select().from(agentRegistrationsTable).where(eq(agentRegistrationsTable.agent_id, agentId)).limit(1);
33868
+ const [row] = await db.select().from(table).where(eq(table.agent_id, agentId)).limit(1);
33655
33869
  return row === undefined ? undefined : toRegistration(row);
33656
33870
  },
33657
33871
  findByClientId: async (clientId) => {
33658
- const [row] = await db.select().from(agentRegistrationsTable).where(eq(agentRegistrationsTable.client_id, clientId)).limit(1);
33872
+ const [row] = await db.select().from(table).where(eq(table.client_id, clientId)).limit(1);
33659
33873
  return row === undefined ? undefined : toRegistration(row);
33660
33874
  },
33661
33875
  listRegistrations: async () => {
33662
- const rows = await db.select().from(agentRegistrationsTable).orderBy(desc(agentRegistrationsTable.created_at_ms));
33876
+ const rows = await db.select().from(table).orderBy(desc(table.created_at_ms));
33663
33877
  return rows.map(toRegistration);
33664
33878
  },
33665
33879
  saveRegistration: async (registration) => {
@@ -33673,12 +33887,14 @@ var createPostgresAgentRegistrationStore = (db) => ({
33673
33887
  status: registration.status,
33674
33888
  updated_at_ms: registration.updatedAt
33675
33889
  };
33676
- await db.insert(agentRegistrationsTable).values(values).onConflictDoUpdate({
33890
+ await db.insert(table).values(values).onConflictDoUpdate({
33677
33891
  set: values,
33678
- target: agentRegistrationsTable.agent_id
33892
+ target: table.agent_id
33679
33893
  });
33680
33894
  }
33681
33895
  });
33896
+ var createBunSqlDrizzleAgentRegistrationStore = (db) => createPostgresAgentRegistrationStoreFor(db, agentRegistrationsBunSqlTable);
33897
+ var createPostgresAgentRegistrationStore = (db) => createPostgresAgentRegistrationStoreFor(db, agentRegistrationsTable);
33682
33898
  // src/apikeys/inMemoryStores.ts
33683
33899
  var createInMemoryAccessTokenStore = () => {
33684
33900
  const tokens = new Map;
@@ -36030,6 +36246,14 @@ var oidcResourceAudienceMigration = {
36030
36246
  ].join(`
36031
36247
  `)
36032
36248
  };
36249
+ var sessionOAuthSubjectMigration = {
36250
+ id: "0002_oauth_subject",
36251
+ sql: [
36252
+ 'ALTER TABLE "auth_sessions" ADD COLUMN IF NOT EXISTS "oauth_subject_json" jsonb;',
36253
+ 'ALTER TABLE "auth_unregistered_sessions" ADD COLUMN IF NOT EXISTS "oauth_subject_json" jsonb;'
36254
+ ].join(`
36255
+ `)
36256
+ };
36033
36257
  var blockMigrations = {
36034
36258
  adaptive: initMigration("adaptive", [knownDevicesTable, loginHistoryTable]),
36035
36259
  agents: {
@@ -36098,10 +36322,16 @@ var blockMigrations = {
36098
36322
  portal: initMigration("portal", [setupSessionsTable]),
36099
36323
  roles: initMigration("roles", [rolesTable]),
36100
36324
  scim: initMigration("scim", [scimTokensTable]),
36101
- sessions: initMigration("sessions", [
36102
- authSessionsTable,
36103
- authUnregisteredSessionsTable
36104
- ]),
36325
+ sessions: {
36326
+ block: "sessions",
36327
+ migrations: [
36328
+ ...initMigration("sessions", [
36329
+ authSessionsTable,
36330
+ authUnregisteredSessionsTable
36331
+ ]).migrations,
36332
+ sessionOAuthSubjectMigration
36333
+ ]
36334
+ },
36105
36335
  sso: initMigration("sso", [ssoConnectionsTable, samlServiceProvidersTable]),
36106
36336
  vault: initMigration("vault", [vaultEntriesTable]),
36107
36337
  vc: initMigration("vc", [
@@ -36787,6 +37017,7 @@ var buildAuthApplications = async (configuration) => {
36787
37017
  resolveAuthIntent
36788
37018
  }),
36789
37019
  profile({
37020
+ authSessionStore,
36790
37021
  clientProviders,
36791
37022
  onProfileError,
36792
37023
  onProfileSuccess,
@@ -37271,6 +37502,9 @@ export {
37271
37502
  createCustomOAuth2Client,
37272
37503
  createCredentialOffer,
37273
37504
  createClientIdMetadataResolver,
37505
+ createBunSqlDrizzleAgentRegistrationStore,
37506
+ createBunSqlDrizzleAgentIdentityRegistrationStore,
37507
+ createBunSqlDrizzleAgentDelegationStore,
37274
37508
  createAuthHtmxRoutes,
37275
37509
  createAuthContext,
37276
37510
  createAuthApplications,
@@ -37313,14 +37547,17 @@ export {
37313
37547
  apiKeysRoutes,
37314
37548
  apiClientsTable,
37315
37549
  agentRegistrationsTable,
37550
+ agentRegistrationsBunSqlTable,
37316
37551
  agentRegistrationEndpoints,
37317
37552
  agentRegistrationDiscoveryMetadata,
37318
37553
  agentProtectedResourceMetadata,
37319
37554
  agentOAuthGuideUrl,
37320
37555
  agentOAuthGuideRoute,
37321
37556
  agentIdentityRegistrationsTable,
37557
+ agentIdentityRegistrationsBunSqlTable,
37322
37558
  agentHasScopes,
37323
37559
  agentDelegationsTable,
37560
+ agentDelegationsBunSqlTable,
37324
37561
  agentAuthPlugin,
37325
37562
  agentAuthChallenge,
37326
37563
  addToSessionRing,
@@ -37376,5 +37613,5 @@ export {
37376
37613
  AGENT_CLAIM_GRANT_TYPE
37377
37614
  };
37378
37615
 
37379
- //# debugId=F857B4607106B28664756E2164756E21
37616
+ //# debugId=0FBF734780C91B5D64756E2164756E21
37380
37617
  //# sourceMappingURL=index.js.map