@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/server.js CHANGED
@@ -1363,17 +1363,23 @@ var providers = defineProviders({
1363
1363
  },
1364
1364
  apple: {
1365
1365
  authorizationUrl: "https://appleid.apple.com/auth/authorize",
1366
+ createAuthorizationURLSearchParams: {
1367
+ response_mode: "form_post"
1368
+ },
1369
+ createClientSecret: (config) => createAppleClientSecret(config),
1366
1370
  isOIDC: true,
1367
1371
  isRefreshable: true,
1368
- PKCEMethod: "S256",
1369
- profileRequest: {
1370
- authIn: "header",
1371
- encoding: "application/json",
1372
- method: "GET",
1373
- url: "https://appleid.apple.com/auth/userinfo"
1372
+ revocationRequest: {
1373
+ authIn: "body",
1374
+ encoding: "application/x-www-form-urlencoded",
1375
+ tokenParamName: "token",
1376
+ url: "https://appleid.apple.com/auth/revoke"
1374
1377
  },
1375
1378
  scopeRequired: false,
1376
- subject: ["id"],
1379
+ subject: ["sub"],
1380
+ subjectBySource: {
1381
+ idToken: ["sub"]
1382
+ },
1377
1383
  subjectType: "string",
1378
1384
  tokenRequest: {
1379
1385
  authIn: "body",
@@ -1442,6 +1448,7 @@ var providers = defineProviders({
1442
1448
  token_type_hint: "refresh_token"
1443
1449
  }),
1444
1450
  encoding: "application/json",
1451
+ inputSource: "refreshToken",
1445
1452
  tokenParamName: "token",
1446
1453
  url: (config) => `https://${config.domain}/oauth/revoke`
1447
1454
  },
@@ -2573,6 +2580,7 @@ var providers = defineProviders({
2573
2580
  token_type_hint: "refresh_token"
2574
2581
  }),
2575
2582
  encoding: "application/json",
2583
+ inputSource: "refreshToken",
2576
2584
  url: "https://www.reddit.com/api/v1/revoke_token"
2577
2585
  },
2578
2586
  scopeRequired: true,
@@ -2946,49 +2954,27 @@ var providers = defineProviders({
2946
2954
  authorizationUrl: "https://account.withings.com/oauth2_user/authorize2",
2947
2955
  isOIDC: false,
2948
2956
  isRefreshable: true,
2949
- profileRequest: {
2950
- authIn: "header",
2951
- body: async (config) => {
2952
- const props = await getWithingsProps(config);
2953
- if (props === undefined)
2954
- throw new Error("Failed to get Withings search properties");
2955
- const { nonce, hashedSignature } = props;
2956
- return [
2957
- ["action", "getuser"],
2958
- ["nonce", nonce],
2959
- ["client_id", config.clientId],
2960
- ["signature", hashedSignature]
2961
- ];
2962
- },
2963
- encoding: "application/x-www-form-urlencoded",
2964
- method: "POST",
2965
- url: "https://wbsapi.withings.net/v2/oauth2"
2966
- },
2967
2957
  refreshAccessTokenBody: {
2968
2958
  action: "requesttoken"
2969
2959
  },
2970
2960
  revocationRequest: {
2971
- authIn: "header",
2972
- body: async (config) => {
2973
- const props = await getWithingsProps(config);
2974
- if (!props)
2975
- throw new Error("Failed to get Withings props");
2976
- const { nonce, hashedSignature } = props;
2977
- return [
2978
- ["action", "revoke"],
2979
- ["client_id", config.clientId],
2980
- ["nonce", nonce],
2981
- ["signature", hashedSignature]
2982
- ];
2983
- },
2961
+ authIn: "body",
2962
+ body: (config) => getWithingsSignatureParams(config, "revoke"),
2984
2963
  encoding: "application/x-www-form-urlencoded",
2985
- method: "POST",
2986
- url: "https://wbsapi.withings.net/v2/oauth2"
2964
+ includeClientCredentials: false,
2965
+ inputSource: "subject",
2966
+ inputType: "number",
2967
+ tokenParamName: "userid",
2968
+ url: "https://wbsapi.withings.net/v2/oauth2",
2969
+ validateResponse: (value) => assertWithingsSuccess(value)
2987
2970
  },
2988
2971
  scopeDelimiter: ",",
2989
2972
  scopeRequired: true,
2990
2973
  subject: ["userid"],
2991
- subjectType: "string",
2974
+ subjectBySource: {
2975
+ tokenResponse: ["body", "userid"]
2976
+ },
2977
+ subjectType: "number",
2992
2978
  tokenRequest: {
2993
2979
  authIn: "body",
2994
2980
  encoding: "application/x-www-form-urlencoded",
@@ -3180,14 +3166,39 @@ var isPKCEProviderOption = (option) => {
3180
3166
  const provider = providers[option];
3181
3167
  return provider.PKCEMethod !== undefined;
3182
3168
  };
3183
- var isRefreshableOAuth2Client = (providerName, _client) => isRefreshableProviderOption(providerName);
3169
+ function isProfileOAuth2Client(providerOrClient, maybeClient) {
3170
+ const client = maybeClient ?? providerOrClient;
3171
+ if (maybeClient !== undefined && (typeof providerOrClient !== "string" || !isProfileProviderOption(providerOrClient))) {
3172
+ return false;
3173
+ }
3174
+ return typeof client === "object" && client !== null && "fetchUserProfile" in client && typeof client.fetchUserProfile === "function";
3175
+ }
3176
+ var isProfileProviderOption = (option) => {
3177
+ if (!isValidProviderOption(option))
3178
+ return false;
3179
+ const provider = providers[option];
3180
+ return provider.profileRequest !== undefined;
3181
+ };
3182
+ function isRefreshableOAuth2Client(providerOrClient, maybeClient) {
3183
+ const client = maybeClient ?? providerOrClient;
3184
+ if (maybeClient !== undefined && (typeof providerOrClient !== "string" || !isRefreshableProviderOption(providerOrClient))) {
3185
+ return false;
3186
+ }
3187
+ return typeof client === "object" && client !== null && "refreshAccessToken" in client && typeof client.refreshAccessToken === "function";
3188
+ }
3184
3189
  var isRefreshableProviderOption = (option) => {
3185
3190
  if (!isValidProviderOption(option))
3186
3191
  return false;
3187
3192
  const provider = providers[option];
3188
3193
  return provider.isRefreshable;
3189
3194
  };
3190
- var isRevocableOAuth2Client = (providerName, _client) => isRevocableProviderOption(providerName);
3195
+ function isRevocableOAuth2Client(providerOrClient, maybeClient) {
3196
+ const client = maybeClient ?? providerOrClient;
3197
+ if (maybeClient !== undefined && (typeof providerOrClient !== "string" || !isRevocableProviderOption(providerOrClient))) {
3198
+ return false;
3199
+ }
3200
+ return typeof client === "object" && client !== null && "resolveRevocationInput" in client && typeof client.resolveRevocationInput === "function" && "revokeToken" in client && typeof client.revokeToken === "function";
3201
+ }
3191
3202
  var isRevocableProviderOption = (option) => {
3192
3203
  if (!isValidProviderOption(option))
3193
3204
  return false;
@@ -3201,6 +3212,14 @@ var isScopeRequiredProviderOption = (option) => {
3201
3212
  return provider.scopeRequired;
3202
3213
  };
3203
3214
  var isValidProviderOption = (option) => Object.hasOwn(providers, option);
3215
+ var readPath = (value, path) => path.reduce((cursor, key) => cursor && typeof cursor === "object" ? Reflect.get(cursor, key) : undefined, value);
3216
+ var assertWithingsSuccess = (value) => {
3217
+ if (!isObject(value) || value.status !== 0) {
3218
+ const status = isObject(value) ? value.status : "invalid response";
3219
+ const detail = isObject(value) && typeof value.error === "string" ? `: ${value.error}` : "";
3220
+ throw new Error(`Withings request failed (${String(status)})${detail}`);
3221
+ }
3222
+ };
3204
3223
  var createOAuth2FetchError = async (response) => {
3205
3224
  const clone = response.clone();
3206
3225
  const prefix = `HTTP ${response.status} ${response.statusText} for ${response.url}`;
@@ -3234,16 +3253,27 @@ var createOAuth2Request = ({
3234
3253
  }
3235
3254
  oauthHeaders.set("Authorization", `Basic ${encodeBase64(`${clientId}:${clientSecret}`)}`);
3236
3255
  }
3256
+ if (body === undefined && authIn !== "body") {
3257
+ return new Request(url, {
3258
+ headers: oauthHeaders,
3259
+ method: "POST"
3260
+ });
3261
+ }
3237
3262
  if (encoding === "application/json") {
3238
3263
  oauthHeaders.set("Content-Type", "application/json");
3264
+ const jsonBody = body instanceof URLSearchParams ? Object.fromEntries(body.entries()) : { ...body };
3265
+ if (authIn === "body")
3266
+ jsonBody.client_id = clientId;
3267
+ if (authIn === "body" && clientSecret)
3268
+ jsonBody.client_secret = clientSecret;
3239
3269
  return new Request(url, {
3240
- body: JSON.stringify(body),
3270
+ body: JSON.stringify(jsonBody),
3241
3271
  headers: oauthHeaders,
3242
3272
  method: "POST"
3243
3273
  });
3244
3274
  }
3245
3275
  oauthHeaders.set("Content-Type", "application/x-www-form-urlencoded");
3246
- const entries = body instanceof URLSearchParams ? Array.from(body.entries()) : Object.entries(body).filter((entry) => typeof entry[1] === "string");
3276
+ const entries = body instanceof URLSearchParams ? Array.from(body.entries()) : Object.entries(body ?? {}).filter((entry) => typeof entry[1] === "string");
3247
3277
  const params = new URLSearchParams(entries);
3248
3278
  if (authIn === "body") {
3249
3279
  params.set("client_id", clientId);
@@ -3289,25 +3319,31 @@ var encodeBase64 = (input) => {
3289
3319
  }
3290
3320
  return btoa(raw);
3291
3321
  };
3292
- var getWithingsProps = async (config) => {
3322
+ var getWithingsSignatureParams = async (config, action) => {
3293
3323
  const timestamp = Math.floor(Date.now() / 1000);
3294
- const signature = `getnonce,${config.clientId},${timestamp}`;
3295
- const hashedSignature = await hmacSha256(signature, config.clientSecret);
3324
+ const nonceSignature = await hmacSha256(`getnonce,${config.clientId},${timestamp}`, config.clientSecret);
3296
3325
  const nonceUrl = new URL("https://wbsapi.withings.net/v2/signature");
3297
3326
  nonceUrl.searchParams.set("action", "getnonce");
3298
3327
  nonceUrl.searchParams.set("client_id", config.clientId);
3299
3328
  nonceUrl.searchParams.set("timestamp", timestamp.toString());
3300
- nonceUrl.searchParams.set("signature", hashedSignature);
3329
+ nonceUrl.searchParams.set("signature", nonceSignature);
3301
3330
  const nonceTarget = nonceUrl.toString();
3302
3331
  const nonceResponse = await fetch(nonceTarget, { method: "POST" });
3332
+ if (!nonceResponse.ok) {
3333
+ throw await createOAuth2FetchError(nonceResponse);
3334
+ }
3303
3335
  const nonceData = await nonceResponse.json();
3304
- if (nonceData.status === 0) {
3305
- return {
3306
- hashedSignature,
3307
- nonce: nonceData.body.nonce
3308
- };
3336
+ if (!isObject(nonceData) || nonceData.status !== 0 || !isObject(nonceData.body) || typeof nonceData.body.nonce !== "string" || nonceData.body.nonce.length === 0) {
3337
+ throw new Error("Withings returned an invalid nonce response");
3309
3338
  }
3310
- return;
3339
+ const { nonce } = nonceData.body;
3340
+ const signature = await hmacSha256(`${action},${config.clientId},${nonce}`, config.clientSecret);
3341
+ return {
3342
+ action,
3343
+ client_id: config.clientId,
3344
+ nonce,
3345
+ signature
3346
+ };
3311
3347
  };
3312
3348
  var hmacSha256 = async (message, secret) => {
3313
3349
  const encoder = new TextEncoder;
@@ -3315,15 +3351,53 @@ var hmacSha256 = async (message, secret) => {
3315
3351
  const sigBuffer = await crypto.subtle.sign("HMAC", key, encoder.encode(message));
3316
3352
  return Array.from(new Uint8Array(sigBuffer)).map((byte) => byte.toString(16).padStart(2, "0")).join("");
3317
3353
  };
3354
+ var parseOAuth2TokenResponse = (value, accessTokenPath) => {
3355
+ if (!isObject(value)) {
3356
+ throw new Error("OAuth token endpoint returned a non-object response");
3357
+ }
3358
+ const oauthError = Reflect.get(value, "error");
3359
+ if (typeof oauthError === "string" && oauthError.length > 0) {
3360
+ throw new Error(`OAuth token exchange failed: ${oauthError}`);
3361
+ }
3362
+ const response = { ...value };
3363
+ const nestedToken = accessTokenPath ? readPath(value, accessTokenPath) : undefined;
3364
+ if (typeof nestedToken === "string" && nestedToken.length > 0) {
3365
+ response.access_token = nestedToken;
3366
+ }
3367
+ if (typeof response.access_token !== "string" || response.access_token.length === 0) {
3368
+ throw new Error("OAuth token endpoint returned no access_token");
3369
+ }
3370
+ for (const key of ["refresh_token", "token_type", "scope", "id_token"]) {
3371
+ const field = response[key];
3372
+ if (field !== undefined && typeof field !== "string") {
3373
+ throw new Error(`OAuth token endpoint returned invalid ${key}: expected string`);
3374
+ }
3375
+ }
3376
+ const expiresIn = response.expires_in;
3377
+ if (typeof expiresIn === "string" && expiresIn.trim() !== "") {
3378
+ response.expires_in = Number(expiresIn);
3379
+ }
3380
+ if (response.expires_in !== undefined && (typeof response.expires_in !== "number" || !Number.isFinite(response.expires_in) || response.expires_in < 0)) {
3381
+ throw new Error("OAuth token endpoint returned invalid expires_in: expected a non-negative number");
3382
+ }
3383
+ return response;
3384
+ };
3385
+ var readIdentityKey = (value, key) => {
3386
+ if (Array.isArray(value)) {
3387
+ if (!/^\d+$/.test(key)) {
3388
+ throw new Error(`Invalid identity data shape: expected an array index, got ${key}`);
3389
+ }
3390
+ return value[Number(key)];
3391
+ }
3392
+ if (!isObject(value)) {
3393
+ throw new Error(`Invalid identity data shape: expected object, got ${typeof value}`);
3394
+ }
3395
+ return value[key];
3396
+ };
3318
3397
  var extractPropFromIdentity = (identity, keys, propType) => {
3319
3398
  let value = identity;
3320
3399
  for (const key of keys) {
3321
- if (Array.isArray(value))
3322
- value = value[Number(key)];
3323
- if (!isObject(value)) {
3324
- throw new Error(`Invalid identity data shape: expected object, got ${typeof value}`);
3325
- }
3326
- value = value[key];
3400
+ value = readIdentityKey(value, key);
3327
3401
  }
3328
3402
  if (propType !== undefined && !isExpectedType(value, propType)) {
3329
3403
  throw new Error(`Invalid identity data shape: expected ${propType}, got ${typeof value}`);
@@ -3358,6 +3432,13 @@ var normalizeProviderIdentity = ({
3358
3432
  const normalizedIdentity = structuredClone(identity);
3359
3433
  return setPropInIdentity(normalizedIdentity, canonicalKeys, subject);
3360
3434
  };
3435
+ var DAYS_IN_APPLE_CLIENT_SECRET_LIFETIME = 180;
3436
+ var HOURS_PER_DAY = 24;
3437
+ var MINUTES_PER_HOUR = 60;
3438
+ var SECONDS_PER_MINUTE = 60;
3439
+ var APPLE_CLIENT_SECRET_LIFETIME_SECONDS = SECONDS_PER_MINUTE * MINUTES_PER_HOUR * HOURS_PER_DAY * DAYS_IN_APPLE_CLIENT_SECRET_LIFETIME;
3440
+ var APPLE_ISSUER = "https://appleid.apple.com";
3441
+ var MILLISECONDS_PER_SECOND = 1000;
3361
3442
  var createS256CodeChallenge = async (codeVerifier) => {
3362
3443
  const data = new TextEncoder().encode(codeVerifier);
3363
3444
  const hashBuffer = await crypto.subtle.digest("SHA-256", data);
@@ -3370,20 +3451,40 @@ var createRandomBase64UrlGenerator = (length) => () => {
3370
3451
  var generateCodeVerifier = createRandomBase64UrlGenerator(NUM_GENERATOR_BYTES);
3371
3452
  var generateState = createRandomBase64UrlGenerator(NUM_GENERATOR_BYTES);
3372
3453
  var base64Url = (input) => encodeBase64(input).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
3454
+ var encodeJwtPart = (value) => base64Url(new TextEncoder().encode(JSON.stringify(value)));
3455
+ var createAppleClientSecret = async (credentials) => {
3456
+ const issuedAt = Math.floor(Date.now() / MILLISECONDS_PER_SECOND);
3457
+ const header = encodeJwtPart({
3458
+ alg: "ES256",
3459
+ kid: credentials.keyId,
3460
+ typ: "JWT"
3461
+ });
3462
+ const payload = encodeJwtPart({
3463
+ aud: APPLE_ISSUER,
3464
+ exp: issuedAt + APPLE_CLIENT_SECRET_LIFETIME_SECONDS,
3465
+ iat: issuedAt,
3466
+ iss: credentials.teamId,
3467
+ sub: credentials.clientId
3468
+ });
3469
+ const signingInput = `${header}.${payload}`;
3470
+ const privateKey = await crypto.subtle.importKey("pkcs8", Uint8Array.from(credentials.pkcs8PrivateKey), { name: "ECDSA", namedCurve: "P-256" }, false, ["sign"]);
3471
+ const signature = await crypto.subtle.sign({ hash: "SHA-256", name: "ECDSA" }, privateKey, new TextEncoder().encode(signingInput));
3472
+ return `${signingInput}.${base64Url(signature)}`;
3473
+ };
3373
3474
  var ALG_ES256 = "ES256";
3374
3475
  var ALG_RS256 = "RS256";
3375
3476
  var CLOCK_SKEW_SECONDS = 60;
3376
3477
  var DEFAULT_SCOPES = ["openid", "email", "profile"];
3377
3478
  var JWKS_REFETCH_COOLDOWN_MS = 60000;
3378
3479
  var JWT_SEGMENT_COUNT = 3;
3379
- var MILLISECONDS_PER_SECOND = 1000;
3480
+ var MILLISECONDS_PER_SECOND2 = 1000;
3380
3481
  var trimTrailingSlash = (value) => value.endsWith("/") ? value.slice(0, -1) : value;
3381
3482
  var fetchJson = async (url) => {
3382
3483
  const response = await fetch(url, {
3383
3484
  headers: { accept: "application/json" }
3384
3485
  });
3385
3486
  if (!response.ok) {
3386
- throw new Error(`Request to ${url} failed with status ${response.status}`);
3487
+ throw await createOAuth2FetchError(response);
3387
3488
  }
3388
3489
  return response.json();
3389
3490
  };
@@ -3414,11 +3515,14 @@ var verifySignature = (key, alg, signingInput, signature) => {
3414
3515
  var selectKey = (jwks, kid) => jwks.find((jwk) => kid === undefined || jwk.kid === kid);
3415
3516
  var assertClaims = (payload, expected) => {
3416
3517
  const aud = Reflect.get(payload, "aud");
3518
+ const azp = Reflect.get(payload, "azp");
3417
3519
  const exp = Reflect.get(payload, "exp");
3520
+ const iat = Reflect.get(payload, "iat");
3418
3521
  const iss = Reflect.get(payload, "iss");
3522
+ const nbf = Reflect.get(payload, "nbf");
3419
3523
  const sub = Reflect.get(payload, "sub");
3420
3524
  const audiences = Array.isArray(aud) ? aud : [aud];
3421
- const nowSeconds = Math.floor(Date.now() / MILLISECONDS_PER_SECOND);
3525
+ const nowSeconds = Math.floor(Date.now() / MILLISECONDS_PER_SECOND2);
3422
3526
  if (iss !== expected.issuer) {
3423
3527
  throw new Error('id_token "iss" does not match the provider issuer');
3424
3528
  }
@@ -3428,9 +3532,24 @@ var assertClaims = (payload, expected) => {
3428
3532
  if (!audiences.includes(expected.audience)) {
3429
3533
  throw new Error('id_token "aud" does not include the client id');
3430
3534
  }
3535
+ if (audiences.some((audience) => typeof audience !== "string") || typeof aud !== "string" && !Array.isArray(aud)) {
3536
+ throw new Error('id_token "aud" must be a string or string array');
3537
+ }
3538
+ if (audiences.length > 1 && (typeof azp !== "string" || azp !== expected.audience)) {
3539
+ throw new Error('id_token with multiple audiences requires matching "azp"');
3540
+ }
3431
3541
  if (typeof exp !== "number" || exp + CLOCK_SKEW_SECONDS < nowSeconds) {
3432
3542
  throw new Error("id_token has expired");
3433
3543
  }
3544
+ if (typeof iat !== "number") {
3545
+ throw new Error('id_token is missing numeric "iat"');
3546
+ }
3547
+ if (iat > nowSeconds + CLOCK_SKEW_SECONDS) {
3548
+ throw new Error('id_token "iat" is in the future');
3549
+ }
3550
+ if (nbf !== undefined && (typeof nbf !== "number" || nbf > nowSeconds + CLOCK_SKEW_SECONDS)) {
3551
+ throw new Error("id_token is not active yet");
3552
+ }
3434
3553
  if (expected.nonce !== undefined && Reflect.get(payload, "nonce") !== expected.nonce) {
3435
3554
  throw new Error('id_token "nonce" does not match');
3436
3555
  }
@@ -3557,9 +3676,9 @@ var createOIDCClient = async (config) => {
3557
3676
  method: "POST"
3558
3677
  });
3559
3678
  if (!response.ok) {
3560
- throw new Error(`OIDC token request failed with status ${response.status}`);
3679
+ throw await createOAuth2FetchError(response);
3561
3680
  }
3562
- const tokens = await response.json();
3681
+ const tokens = parseOAuth2TokenResponse(await response.json());
3563
3682
  return tokens;
3564
3683
  };
3565
3684
  const verifyToken = async (idToken, options) => {
@@ -3605,20 +3724,26 @@ var createOIDCClient = async (config) => {
3605
3724
  };
3606
3725
  var oidcProviderOptions = Object.keys(providers).filter(isOIDCProviderOption);
3607
3726
  var pkceProviderOptions = Object.keys(providers).filter(isPKCEProviderOption);
3727
+ var profileProviderOptions = Object.keys(providers).filter(isProfileProviderOption);
3608
3728
  var providerOptions = Object.keys(providers).filter(isValidProviderOption);
3609
3729
  var refreshableProviderOptions = Object.keys(providers).filter(isRefreshableProviderOption);
3610
3730
  var revocableProviderOptions = Object.keys(providers).filter(isRevocableProviderOption);
3611
3731
  var scopeRequiredProviderOptions = Object.keys(providers).filter(isScopeRequiredProviderOption);
3612
- var readPath = (value, path) => path.reduce((cursor, key) => cursor && typeof cursor === "object" ? Reflect.get(cursor, key) : undefined, value);
3613
3732
  var buildOAuth2Client = async (meta, config) => {
3614
3733
  const isConfigPropertyFunction = (cfgProp) => typeof cfgProp === "function";
3615
3734
  const resolveConfigProp = async (cfgProp) => {
3616
3735
  const result = isConfigPropertyFunction(cfgProp) ? cfgProp(config) : cfgProp;
3617
3736
  return result;
3618
3737
  };
3738
+ const resolveClientSecret = async () => {
3739
+ if (meta.createClientSecret) {
3740
+ return resolveConfigProp(meta.createClientSecret);
3741
+ }
3742
+ return hasClientSecret(config) ? config.clientSecret : undefined;
3743
+ };
3619
3744
  const authorizationUrl = await resolveConfigProp(meta.authorizationUrl);
3620
3745
  const tokenUrl = await resolveConfigProp(meta.tokenRequest.url);
3621
- return {
3746
+ const client = {
3622
3747
  async createAuthorizationUrl(opts) {
3623
3748
  const { state, scope = [], searchParams = [], codeVerifier } = opts;
3624
3749
  const url = new URL(authorizationUrl);
@@ -3639,7 +3764,7 @@ var buildOAuth2Client = async (meta, config) => {
3639
3764
  url.searchParams.set("code_challenge_method", meta.PKCEMethod);
3640
3765
  url.searchParams.set("code_challenge", codeChallenge);
3641
3766
  }
3642
- Object.entries(resolveConfigProp(meta.createAuthorizationURLSearchParams) ?? {}).forEach(([key, value]) => url.searchParams.set(key, value));
3767
+ Object.entries(await resolveConfigProp(meta.createAuthorizationURLSearchParams) ?? {}).forEach(([key, value]) => url.searchParams.set(key, value));
3643
3768
  searchParams.forEach(([key, value]) => url.searchParams.set(key, value));
3644
3769
  return url;
3645
3770
  },
@@ -3672,7 +3797,7 @@ var buildOAuth2Client = async (meta, config) => {
3672
3797
  if (authIn === "header") {
3673
3798
  profileHeaders.Authorization = `Bearer ${accessToken}`;
3674
3799
  } else if (authIn === "path") {
3675
- endpoint.pathname = `${endpoint.pathname.replace(/\/+$/, "")}/${accessToken}`;
3800
+ endpoint.pathname = `${endpoint.pathname.replace(/\/+$/, "")}/${encodeURIComponent(accessToken)}`;
3676
3801
  } else {
3677
3802
  endpoint.searchParams.append("access_token", accessToken);
3678
3803
  }
@@ -3693,9 +3818,8 @@ var buildOAuth2Client = async (meta, config) => {
3693
3818
  params.set("grant_type", "refresh_token");
3694
3819
  params.set("refresh_token", refreshToken);
3695
3820
  const { clientId } = config;
3696
- let clientSecretValue;
3697
- if (hasClientSecret(config)) {
3698
- clientSecretValue = config.clientSecret;
3821
+ const clientSecretValue = await resolveClientSecret();
3822
+ if (clientSecretValue) {
3699
3823
  params.set("client_id", clientId);
3700
3824
  params.set("client_secret", clientSecretValue);
3701
3825
  }
@@ -3710,60 +3834,99 @@ var buildOAuth2Client = async (meta, config) => {
3710
3834
  const response = await fetch(request);
3711
3835
  if (!response.ok)
3712
3836
  throw await createOAuth2FetchError(response);
3713
- return response.json();
3837
+ return parseOAuth2TokenResponse(await response.json());
3714
3838
  },
3715
- async revokeToken(token) {
3839
+ resolveRevocationInput(context) {
3716
3840
  const { revocationRequest } = meta;
3717
3841
  if (!revocationRequest) {
3718
3842
  throw new Error("Token revocation not defined for this provider");
3719
3843
  }
3720
- const { url, authIn, body, headers, tokenParamName } = revocationRequest;
3844
+ const inputSource = revocationRequest.inputSource ?? "accessToken";
3845
+ const input = context[inputSource];
3846
+ if (input === undefined) {
3847
+ throw new Error(`Revocation requires ${inputSource}, but it was not provided`);
3848
+ }
3849
+ const expectsNumber = revocationRequest.authIn !== "header" && revocationRequest.inputType === "number";
3850
+ if (expectsNumber && (typeof input !== "number" || !Number.isFinite(input))) {
3851
+ throw new TypeError("This provider requires a numeric revocation input");
3852
+ }
3853
+ if (!expectsNumber && typeof input !== "string") {
3854
+ throw new TypeError("This provider requires a string revocation input");
3855
+ }
3856
+ return input;
3857
+ },
3858
+ async revokeToken(input) {
3859
+ const { revocationRequest } = meta;
3860
+ if (!revocationRequest) {
3861
+ throw new Error("Token revocation not defined for this provider");
3862
+ }
3863
+ if (revocationRequest.authIn !== "header" && revocationRequest.inputType === "number" && (typeof input !== "number" || !Number.isFinite(input))) {
3864
+ throw new TypeError("This provider requires a numeric revocation input");
3865
+ }
3866
+ const {
3867
+ url,
3868
+ authIn,
3869
+ body,
3870
+ encoding,
3871
+ headers,
3872
+ includeClientCredentials = true,
3873
+ tokenParamName,
3874
+ validateResponse
3875
+ } = revocationRequest;
3721
3876
  const endpoint = await resolveConfigProp(url);
3722
3877
  const resolvedBody = await resolveConfigProp(body);
3723
- const revocationBody = new URLSearchParams(resolvedBody);
3878
+ const revocationBody = resolvedBody === undefined ? undefined : new URLSearchParams(resolvedBody);
3724
3879
  const revocationHeaders = new Headers(headers && await resolveConfigProp(headers));
3725
3880
  const { clientId } = config;
3726
- const clientSecret = hasClientSecret(config) ? config.clientSecret : undefined;
3881
+ const clientSecret = await resolveClientSecret();
3727
3882
  let request;
3728
3883
  if (authIn === "body") {
3729
- revocationBody.set(tokenParamName, token);
3730
- revocationBody.set("client_id", clientId);
3731
- if (clientSecret)
3732
- revocationBody.set("client_secret", clientSecret);
3884
+ const bodyWithToken = revocationBody ?? new URLSearchParams;
3885
+ bodyWithToken.set(tokenParamName, String(input));
3886
+ const hasAuthorizationHeader = revocationHeaders.has("Authorization");
3887
+ if (includeClientCredentials && !hasAuthorizationHeader)
3888
+ bodyWithToken.set("client_id", clientId);
3889
+ if (includeClientCredentials && !hasAuthorizationHeader && clientSecret)
3890
+ bodyWithToken.set("client_secret", clientSecret);
3733
3891
  request = createOAuth2Request({
3734
- authIn: "body",
3735
- body: revocationBody,
3892
+ authIn: hasAuthorizationHeader || !includeClientCredentials ? "query" : "body",
3893
+ body: bodyWithToken,
3736
3894
  clientId,
3737
3895
  clientSecret,
3738
- encoding: "application/x-www-form-urlencoded",
3896
+ encoding,
3739
3897
  headers: revocationHeaders,
3740
3898
  url: endpoint.toString()
3741
3899
  });
3742
3900
  } else if (authIn === "header") {
3743
- revocationHeaders.set("Authorization", `Bearer ${token}`);
3901
+ revocationHeaders.set("Authorization", `Bearer ${String(input)}`);
3744
3902
  request = createOAuth2Request({
3745
- authIn: "header",
3903
+ authIn: "query",
3746
3904
  body: revocationBody,
3747
3905
  clientId,
3748
- clientSecret,
3749
- encoding: "application/x-www-form-urlencoded",
3906
+ encoding,
3750
3907
  headers: revocationHeaders,
3751
3908
  url: endpoint.toString()
3752
3909
  });
3753
3910
  } else {
3911
+ const queryEndpoint = new URL(endpoint);
3912
+ queryEndpoint.searchParams.set(tokenParamName, String(input));
3754
3913
  request = createOAuth2Request({
3755
3914
  authIn: "query",
3756
3915
  body: revocationBody,
3757
3916
  clientId,
3758
- clientSecret,
3759
- encoding: "application/x-www-form-urlencoded",
3917
+ encoding,
3760
3918
  headers: revocationHeaders,
3761
- url: `${endpoint.toString()}?${tokenParamName}=${token}`
3919
+ url: queryEndpoint.toString()
3762
3920
  });
3763
3921
  }
3764
3922
  const response = await fetch(request);
3765
3923
  if (!response.ok)
3766
3924
  throw await createOAuth2FetchError(response);
3925
+ if (validateResponse) {
3926
+ await validateResponse(await response.json().catch(() => {
3927
+ return;
3928
+ }));
3929
+ }
3767
3930
  },
3768
3931
  async validateAuthorizationCode(opts) {
3769
3932
  const { code, codeVerifier } = opts;
@@ -3789,32 +3952,27 @@ var buildOAuth2Client = async (meta, config) => {
3789
3952
  authIn,
3790
3953
  body: payload,
3791
3954
  clientId: config.clientId,
3792
- clientSecret: hasClientSecret(config) ? config.clientSecret : undefined,
3955
+ clientSecret: await resolveClientSecret(),
3793
3956
  encoding,
3794
3957
  url: tokenUrl
3795
3958
  });
3796
3959
  const response = await fetch(request);
3797
3960
  if (!response.ok)
3798
3961
  throw await createOAuth2FetchError(response);
3799
- const tokenResponse = await response.json();
3800
- if (!tokenResponse || typeof tokenResponse !== "object") {
3801
- throw new Error("OAuth token endpoint returned a non-object response");
3802
- }
3803
- const oauthError = Reflect.get(tokenResponse, "error");
3804
- if (typeof oauthError === "string" && oauthError.length > 0) {
3805
- throw new Error(`OAuth token exchange failed: ${oauthError}`);
3806
- }
3807
- const nestedToken = meta.accessTokenPath ? readPath(tokenResponse, meta.accessTokenPath) : undefined;
3808
- if (typeof nestedToken === "string" && nestedToken.length > 0 && tokenResponse && typeof tokenResponse === "object") {
3809
- tokenResponse.access_token = nestedToken;
3810
- }
3811
- const accessToken = Reflect.get(tokenResponse, "access_token");
3812
- if (typeof accessToken !== "string" || accessToken.length === 0) {
3813
- throw new Error("OAuth token endpoint returned no access_token");
3814
- }
3815
- return tokenResponse;
3962
+ return parseOAuth2TokenResponse(await response.json(), meta.accessTokenPath);
3816
3963
  }
3817
3964
  };
3965
+ if (!meta.profileRequest) {
3966
+ Reflect.deleteProperty(client, "fetchUserProfile");
3967
+ }
3968
+ if (!meta.isRefreshable) {
3969
+ Reflect.deleteProperty(client, "refreshAccessToken");
3970
+ }
3971
+ if (!meta.revocationRequest) {
3972
+ Reflect.deleteProperty(client, "resolveRevocationInput");
3973
+ Reflect.deleteProperty(client, "revokeToken");
3974
+ }
3975
+ return client;
3818
3976
  };
3819
3977
  var createCustomOAuth2Client = (providerConfig, credentials) => buildOAuth2Client(providerConfig, credentials);
3820
3978
  var createOAuth2Client = (providerName, config) => buildOAuth2Client(providers[providerName], config);
@@ -5572,7 +5730,15 @@ var instantiateUserSession = async ({
5572
5730
  providerInstance,
5573
5731
  tokenResponse
5574
5732
  });
5575
- const { accessToken, refreshToken, userIdentity } = authorization;
5733
+ const {
5734
+ accessToken,
5735
+ oauthSubject: resolvedOAuthSubject,
5736
+ refreshToken,
5737
+ userIdentity
5738
+ } = authorization;
5739
+ const providerMeta = providerConfiguration ?? (isValidProviderOption(authProvider) ? providers[authProvider] : undefined);
5740
+ const extractedSubject = providerMeta ? extractPropFromIdentity(userIdentity, providerMeta.subject, providerMeta.subjectType) : Reflect.get(userIdentity, "sub");
5741
+ const oauthSubject = resolvedOAuthSubject ?? (typeof extractedSubject === "string" || typeof extractedSubject === "number" ? extractedSubject : undefined);
5576
5742
  const userSession = validateSession({ session, user_session_id });
5577
5743
  const userSessionId = getUserSessionId({
5578
5744
  cookieSecure,
@@ -5589,6 +5755,7 @@ var instantiateUserSession = async ({
5589
5755
  accessToken,
5590
5756
  authenticatedAt: Date.now(),
5591
5757
  expiresAt: Date.now() + sessionDurationMs,
5758
+ oauthSubject,
5592
5759
  refreshToken,
5593
5760
  user
5594
5761
  };
@@ -5598,6 +5765,7 @@ var instantiateUserSession = async ({
5598
5765
  if (existingUnregistered) {
5599
5766
  existingUnregistered.accessToken = accessToken;
5600
5767
  existingUnregistered.expiresAt = Date.now() + unregisteredSessionDurationMs;
5768
+ existingUnregistered.oauthSubject = oauthSubject;
5601
5769
  existingUnregistered.refreshToken = refreshToken;
5602
5770
  existingUnregistered.userIdentity = userIdentity;
5603
5771
  return response;
@@ -5605,6 +5773,7 @@ var instantiateUserSession = async ({
5605
5773
  unregisteredSession[userSessionId] = {
5606
5774
  accessToken,
5607
5775
  expiresAt: Date.now() + unregisteredSessionDurationMs,
5776
+ oauthSubject,
5608
5777
  refreshToken,
5609
5778
  userIdentity
5610
5779
  };
@@ -5653,6 +5822,9 @@ var resolveOAuthAuthorization = async ({
5653
5822
  accessToken = readOptionalString(withingsBody, "access_token") ?? accessToken;
5654
5823
  refreshToken = readOptionalString(withingsBody, "refresh_token") ?? refreshToken;
5655
5824
  } else {
5825
+ if (!isProfileOAuth2Client(providerInstance)) {
5826
+ throw new Error(`Provider "${authProvider}" returned no identity and has no profile endpoint`);
5827
+ }
5656
5828
  userIdentity = normalizeProviderIdentity({
5657
5829
  identity: await providerInstance.fetchUserProfile(accessToken),
5658
5830
  providerConfiguration: meta,
@@ -5660,9 +5832,14 @@ var resolveOAuthAuthorization = async ({
5660
5832
  });
5661
5833
  }
5662
5834
  const tokenType = Reflect.get(tokenResponse, "token_type");
5835
+ const oauthSubject = extractPropFromIdentity(userIdentity, meta.subject, meta.subjectType);
5836
+ if (typeof oauthSubject !== "string" && typeof oauthSubject !== "number") {
5837
+ throw new Error(`Provider "${authProvider}" returned an invalid OAuth subject`);
5838
+ }
5663
5839
  return {
5664
5840
  accessToken,
5665
5841
  expiresAt: resolveOAuthTokenExpiresAt(tokenResponse, now),
5842
+ oauthSubject,
5666
5843
  refreshToken,
5667
5844
  tokenType: typeof tokenType === "string" ? tokenType : undefined,
5668
5845
  userIdentity
@@ -7610,10 +7787,10 @@ var exchangeBackchannelAuth = async ({
7610
7787
  init_constants();
7611
7788
  var CLIENT_ASSERTION_TYPE = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer";
7612
7789
  var MAX_ASSERTION_LIFETIME_MINUTES = 5;
7613
- var SECONDS_PER_MINUTE = 60;
7614
- var MAX_ASSERTION_LIFETIME_MS = MAX_ASSERTION_LIFETIME_MINUTES * SECONDS_PER_MINUTE * MILLISECONDS_IN_A_SECOND;
7790
+ var SECONDS_PER_MINUTE2 = 60;
7791
+ var MAX_ASSERTION_LIFETIME_MS = MAX_ASSERTION_LIFETIME_MINUTES * SECONDS_PER_MINUTE2 * MILLISECONDS_IN_A_SECOND;
7615
7792
  var jwksCache = new Map;
7616
- var JWKS_CACHE_TTL_MS = SECONDS_PER_MINUTE * MILLISECONDS_IN_A_SECOND;
7793
+ var JWKS_CACHE_TTL_MS = SECONDS_PER_MINUTE2 * MILLISECONDS_IN_A_SECOND;
7617
7794
  var JWKS_FETCH_TIMEOUT_SECONDS = 5;
7618
7795
  var JWKS_FETCH_TIMEOUT_MS = JWKS_FETCH_TIMEOUT_SECONDS * MILLISECONDS_IN_A_SECOND;
7619
7796
  var fetchJwksUri = async (jwksUri) => {
@@ -11170,6 +11347,7 @@ var callback = ({
11170
11347
  // src/routes/profile.ts
11171
11348
  import { Elysia as Elysia29, t as t22 } from "elysia";
11172
11349
  var profile = ({
11350
+ authSessionStore,
11173
11351
  clientProviders,
11174
11352
  profileRoute = "/oauth2/profile",
11175
11353
  onProfileSuccess,
@@ -11184,9 +11362,6 @@ var profile = ({
11184
11362
  if (auth_provider.value === undefined) {
11185
11363
  return status("Unauthorized", "No auth provider found");
11186
11364
  }
11187
- if (!isValidProviderOption(auth_provider.value)) {
11188
- return status("Unauthorized", "Invalid provider");
11189
- }
11190
11365
  if (user_session_id.value === undefined) {
11191
11366
  return status("Unauthorized", "No user session found");
11192
11367
  }
@@ -11199,7 +11374,14 @@ var profile = ({
11199
11374
  return status("Unauthorized", resolvedProvider.error);
11200
11375
  }
11201
11376
  const { clientName, providerInstance } = resolvedProvider.entry;
11202
- const userSession = session[user_session_id.value];
11377
+ if (!isProfileOAuth2Client(providerInstance)) {
11378
+ return status("Not Implemented", "Provider does not expose a profile endpoint");
11379
+ }
11380
+ const userSession = await loadSessionFromSource({
11381
+ authSessionStore,
11382
+ session,
11383
+ userSessionId: user_session_id.value
11384
+ });
11203
11385
  if (userSession === undefined) {
11204
11386
  return status("Unauthorized", "No user session found");
11205
11387
  }
@@ -11251,9 +11433,6 @@ var refresh = ({
11251
11433
  if (auth_provider.value === undefined) {
11252
11434
  return status("Unauthorized", "No auth provider found");
11253
11435
  }
11254
- if (!isValidProviderOption(auth_provider.value)) {
11255
- return status("Bad Request", "Invalid provider");
11256
- }
11257
11436
  if (user_session_id.value === undefined) {
11258
11437
  return status("Unauthorized", "No user session found");
11259
11438
  }
@@ -11275,7 +11454,7 @@ var refresh = ({
11275
11454
  return status("Unauthorized", "No user session found");
11276
11455
  }
11277
11456
  const { refreshToken } = userSession;
11278
- if (!isRefreshableOAuth2Client(auth_provider.value, providerInstance)) {
11457
+ if (!isRefreshableOAuth2Client(providerInstance)) {
11279
11458
  return status("Not Implemented", "Provider is not refreshable");
11280
11459
  }
11281
11460
  if (refreshToken === undefined) {
@@ -11335,9 +11514,6 @@ var revoke = ({
11335
11514
  if (auth_provider.value === undefined) {
11336
11515
  return status("Unauthorized", "No auth provider found");
11337
11516
  }
11338
- if (!isValidProviderOption(auth_provider.value)) {
11339
- return status("Bad Request", "Invalid provider");
11340
- }
11341
11517
  if (user_session_id.value === undefined) {
11342
11518
  return status("Unauthorized", "No user session found");
11343
11519
  }
@@ -11350,7 +11526,7 @@ var revoke = ({
11350
11526
  return status("Unauthorized", resolvedProvider.error);
11351
11527
  }
11352
11528
  const { clientName, providerInstance } = resolvedProvider.entry;
11353
- if (!isRevocableOAuth2Client(auth_provider.value, providerInstance)) {
11529
+ if (!isRevocableOAuth2Client(providerInstance)) {
11354
11530
  return status("Not Implemented", "Provider does not support revocation");
11355
11531
  }
11356
11532
  const userSession = await loadSessionFromSource({
@@ -11361,16 +11537,21 @@ var revoke = ({
11361
11537
  if (userSession === undefined) {
11362
11538
  return status("Unauthorized", "No user session found");
11363
11539
  }
11364
- const { accessToken } = userSession;
11540
+ const { accessToken, oauthSubject, refreshToken } = userSession;
11365
11541
  if (accessToken === undefined) {
11366
11542
  return status("Bad Request", "Session has no access token to revoke");
11367
11543
  }
11368
11544
  try {
11369
- await providerInstance.revokeToken(accessToken);
11545
+ const tokenToRevoke = providerInstance.resolveRevocationInput({
11546
+ accessToken,
11547
+ refreshToken,
11548
+ subject: oauthSubject
11549
+ });
11550
+ await providerInstance.revokeToken(tokenToRevoke);
11370
11551
  await onRevocationSuccess?.({
11371
11552
  authClient: clientName,
11372
11553
  authProvider: auth_provider.value,
11373
- tokenToRevoke: accessToken
11554
+ tokenToRevoke
11374
11555
  });
11375
11556
  return new Response("Token revoked", {
11376
11557
  status: 204
@@ -25210,6 +25391,7 @@ var authSessionsTable = pgTable("auth_sessions", {
25210
25391
  created_at: timestamp("created_at").notNull().defaultNow(),
25211
25392
  expires_at_ms: bigint("expires_at_ms", { mode: "number" }).notNull(),
25212
25393
  id: varchar("id", { length: 255 }).primaryKey(),
25394
+ oauth_subject_json: jsonb("oauth_subject_json").$type(),
25213
25395
  refresh_token: text("refresh_token"),
25214
25396
  updated_at: timestamp("updated_at").notNull().defaultNow(),
25215
25397
  user_json: jsonb("user_json").$type().notNull()
@@ -25219,6 +25401,7 @@ var authUnregisteredSessionsTable = pgTable("auth_unregistered_sessions", {
25219
25401
  created_at: timestamp("created_at").notNull().defaultNow(),
25220
25402
  expires_at_ms: bigint("expires_at_ms", { mode: "number" }).notNull(),
25221
25403
  id: varchar("id", { length: 255 }).primaryKey(),
25404
+ oauth_subject_json: jsonb("oauth_subject_json").$type(),
25222
25405
  refresh_token: text("refresh_token"),
25223
25406
  session_information_json: jsonb("session_information_json").$type(),
25224
25407
  updated_at: timestamp("updated_at").notNull().defaultNow(),
@@ -25236,12 +25419,14 @@ var toSessionData = (row, decodeUser) => ({
25236
25419
  accessToken: row.access_token ?? undefined,
25237
25420
  authenticatedAt: row.authenticated_at_ms ?? undefined,
25238
25421
  expiresAt: row.expires_at_ms,
25422
+ oauthSubject: row.oauth_subject_json ?? undefined,
25239
25423
  refreshToken: row.refresh_token ?? undefined,
25240
25424
  user: cloneUser(decodeUser(row.user_json))
25241
25425
  });
25242
25426
  var toUnregisteredSessionData = (row) => ({
25243
25427
  accessToken: row.access_token ?? undefined,
25244
25428
  expiresAt: row.expires_at_ms,
25429
+ oauthSubject: row.oauth_subject_json ?? undefined,
25245
25430
  refreshToken: row.refresh_token ?? undefined,
25246
25431
  sessionInformation: cloneRecord(row.session_information_json ?? undefined),
25247
25432
  userIdentity: cloneRecord(row.user_identity_json ?? undefined)
@@ -25286,6 +25471,7 @@ var createNeonAuthSessionStore = (databaseUrl, decodeUser) => {
25286
25471
  authenticated_at_ms: value.authenticatedAt ?? null,
25287
25472
  expires_at_ms: value.expiresAt,
25288
25473
  id,
25474
+ oauth_subject_json: value.oauthSubject ?? null,
25289
25475
  refresh_token: value.refreshToken ?? null,
25290
25476
  updated_at: new Date,
25291
25477
  user_json: value.user ?? {}
@@ -25294,6 +25480,7 @@ var createNeonAuthSessionStore = (databaseUrl, decodeUser) => {
25294
25480
  access_token: value.accessToken ?? null,
25295
25481
  authenticated_at_ms: value.authenticatedAt ?? null,
25296
25482
  expires_at_ms: value.expiresAt,
25483
+ oauth_subject_json: value.oauthSubject ?? null,
25297
25484
  refresh_token: value.refreshToken ?? null,
25298
25485
  updated_at: new Date,
25299
25486
  user_json: value.user ?? {}
@@ -25306,6 +25493,7 @@ var createNeonAuthSessionStore = (databaseUrl, decodeUser) => {
25306
25493
  access_token: value.accessToken ?? null,
25307
25494
  expires_at_ms: value.expiresAt,
25308
25495
  id,
25496
+ oauth_subject_json: value.oauthSubject ?? null,
25309
25497
  refresh_token: value.refreshToken ?? null,
25310
25498
  session_information_json: value.sessionInformation ?? null,
25311
25499
  updated_at: new Date,
@@ -25314,6 +25502,7 @@ var createNeonAuthSessionStore = (databaseUrl, decodeUser) => {
25314
25502
  set: {
25315
25503
  access_token: value.accessToken ?? null,
25316
25504
  expires_at_ms: value.expiresAt,
25505
+ oauth_subject_json: value.oauthSubject ?? null,
25317
25506
  refresh_token: value.refreshToken ?? null,
25318
25507
  session_information_json: value.sessionInformation ?? null,
25319
25508
  updated_at: new Date,
@@ -31353,6 +31542,7 @@ var sessionSchema = Type.Object({
31353
31542
  authenticatedAt: Type.Optional(Type.Number()),
31354
31543
  expiresAt: Type.Number(),
31355
31544
  impersonator: Type.Optional(impersonatorSchema),
31545
+ oauthSubject: Type.Optional(Type.Union([Type.String(), Type.Number()])),
31356
31546
  refreshToken: Type.Optional(Type.String()),
31357
31547
  samlLogout: Type.Optional(Type.Object({
31358
31548
  connectionId: Type.String(),
@@ -31364,6 +31554,7 @@ var sessionSchema = Type.Object({
31364
31554
  var unregisteredSessionSchema = Type.Object({
31365
31555
  accessToken: Type.Optional(Type.String()),
31366
31556
  expiresAt: Type.Number(),
31557
+ oauthSubject: Type.Optional(Type.Union([Type.String(), Type.Number()])),
31367
31558
  refreshToken: Type.Optional(Type.String()),
31368
31559
  sessionInformation: Type.Optional(Type.Record(Type.String(), Type.Unknown())),
31369
31560
  userIdentity: Type.Optional(Type.Record(Type.String(), Type.Unknown()))
@@ -34448,23 +34639,28 @@ var portableJsonb = customType({
34448
34639
  fromDriver: (value) => typeof value === "string" ? JSON.parse(value) : value,
34449
34640
  toDriver: (value) => JSON.stringify(value)
34450
34641
  });
34451
- var agentDelegationsTable = pgTable("auth_agent_delegations", {
34642
+ var bunSqlJsonb = customType({
34643
+ dataType: () => "jsonb",
34644
+ fromDriver: (value) => typeof value === "string" ? JSON.parse(value) : value,
34645
+ toDriver: (value) => value
34646
+ });
34647
+ var createAgentDelegationsTable = (json5) => pgTable("auth_agent_delegations", {
34452
34648
  agent_id: varchar("agent_id", { length: ID_LENGTH7 }).notNull(),
34453
- authorization_details: portableJsonb("authorization_details").$type(),
34649
+ authorization_details: json5("authorization_details").$type(),
34454
34650
  created_at_ms: bigint("created_at_ms", { mode: "number" }).notNull(),
34455
34651
  delegation_id: varchar("delegation_id", {
34456
34652
  length: ID_LENGTH7
34457
34653
  }).primaryKey(),
34458
34654
  expires_at_ms: bigint("expires_at_ms", { mode: "number" }),
34459
34655
  organization_id: varchar("organization_id", { length: ID_LENGTH7 }),
34460
- scopes: portableJsonb("scopes").$type().notNull().default([]),
34656
+ scopes: json5("scopes").$type().notNull().default([]),
34461
34657
  status: varchar("status", { length: STATUS_LENGTH2 }).$type().notNull(),
34462
34658
  updated_at_ms: bigint("updated_at_ms", { mode: "number" }).notNull(),
34463
34659
  user_id: varchar("user_id", { length: ID_LENGTH7 }).notNull()
34464
34660
  });
34465
- var agentIdentityRegistrationsTable = pgTable("auth_agent_identity_registrations", {
34661
+ var createAgentIdentityRegistrationsTable = (json5) => pgTable("auth_agent_identity_registrations", {
34466
34662
  agent_id: varchar("agent_id", { length: ID_LENGTH7 }).notNull().unique(),
34467
- claim_attempt: portableJsonb("claim_attempt").$type(),
34663
+ claim_attempt: json5("claim_attempt").$type(),
34468
34664
  claim_attempt_token_hash: varchar("claim_attempt_token_hash", {
34469
34665
  length: ID_LENGTH7
34470
34666
  }).unique(),
@@ -34474,8 +34670,12 @@ var agentIdentityRegistrationsTable = pgTable("auth_agent_identity_registrations
34474
34670
  claim_token_hash: varchar("claim_token_hash", {
34475
34671
  length: ID_LENGTH7
34476
34672
  }).notNull().unique(),
34477
- created_at_ms: bigint("created_at_ms", { mode: "number" }).notNull(),
34478
- expires_at_ms: bigint("expires_at_ms", { mode: "number" }).notNull(),
34673
+ created_at_ms: bigint("created_at_ms", {
34674
+ mode: "number"
34675
+ }).notNull(),
34676
+ expires_at_ms: bigint("expires_at_ms", {
34677
+ mode: "number"
34678
+ }).notNull(),
34479
34679
  kind: varchar("kind", { length: 32 }).$type().notNull(),
34480
34680
  last_polled_at_ms: bigint("last_polled_at_ms", { mode: "number" }),
34481
34681
  login_hint: varchar("login_hint", { length: ID_LENGTH7 }),
@@ -34483,27 +34683,37 @@ var agentIdentityRegistrationsTable = pgTable("auth_agent_identity_registrations
34483
34683
  length: ID_LENGTH7
34484
34684
  }).primaryKey(),
34485
34685
  status: varchar("status", { length: STATUS_LENGTH2 }).$type().notNull(),
34486
- updated_at_ms: bigint("updated_at_ms", { mode: "number" }).notNull(),
34686
+ updated_at_ms: bigint("updated_at_ms", {
34687
+ mode: "number"
34688
+ }).notNull(),
34487
34689
  upstream_client_id: varchar("upstream_client_id", {
34488
34690
  length: ID_LENGTH7
34489
34691
  }),
34490
34692
  upstream_issuer: varchar("upstream_issuer", { length: ID_LENGTH7 }),
34491
- upstream_subject: varchar("upstream_subject", { length: ID_LENGTH7 }),
34693
+ upstream_subject: varchar("upstream_subject", {
34694
+ length: ID_LENGTH7
34695
+ }),
34492
34696
  user_id: varchar("user_id", { length: ID_LENGTH7 }),
34493
34697
  version: integer("version").notNull()
34494
34698
  }, (table) => [
34495
34699
  uniqueIndex("auth_agent_identity_upstream_unique").on(table.upstream_issuer, table.upstream_subject, table.upstream_client_id)
34496
34700
  ]);
34497
- var agentRegistrationsTable = pgTable("auth_agent_registrations", {
34701
+ var createAgentRegistrationsTable = (json5) => pgTable("auth_agent_registrations", {
34498
34702
  agent_id: varchar("agent_id", { length: ID_LENGTH7 }).primaryKey(),
34499
- allowed_scopes: portableJsonb("allowed_scopes").$type().notNull().default([]),
34703
+ allowed_scopes: json5("allowed_scopes").$type().notNull().default([]),
34500
34704
  client_id: varchar("client_id", { length: ID_LENGTH7 }).unique(),
34501
34705
  created_at_ms: bigint("created_at_ms", { mode: "number" }).notNull(),
34502
- metadata: portableJsonb("metadata").$type(),
34706
+ metadata: json5("metadata").$type(),
34503
34707
  name: varchar("name", { length: NAME_LENGTH }).notNull(),
34504
34708
  status: varchar("status", { length: STATUS_LENGTH2 }).$type().notNull(),
34505
34709
  updated_at_ms: bigint("updated_at_ms", { mode: "number" }).notNull()
34506
34710
  });
34711
+ var agentDelegationsBunSqlTable = createAgentDelegationsTable(bunSqlJsonb);
34712
+ var agentDelegationsTable = createAgentDelegationsTable(portableJsonb);
34713
+ var agentIdentityRegistrationsBunSqlTable = createAgentIdentityRegistrationsTable(bunSqlJsonb);
34714
+ var agentIdentityRegistrationsTable = createAgentIdentityRegistrationsTable(portableJsonb);
34715
+ var agentRegistrationsBunSqlTable = createAgentRegistrationsTable(bunSqlJsonb);
34716
+ var agentRegistrationsTable = createAgentRegistrationsTable(portableJsonb);
34507
34717
  var toRegistration = (row) => ({
34508
34718
  agentId: row.agent_id,
34509
34719
  allowedScopes: row.allowed_scopes,
@@ -34570,24 +34780,24 @@ var identityRegistrationValues = (registration) => ({
34570
34780
  var createNeonAgentDelegationStore = (databaseUrl) => createDrizzleAgentDelegationStore(createNeonDatabase(databaseUrl));
34571
34781
  var createNeonAgentIdentityRegistrationStore = (databaseUrl) => createPostgresAgentIdentityRegistrationStore(createNeonDatabase(databaseUrl));
34572
34782
  var createNeonAgentRegistrationStore = (databaseUrl) => createPostgresAgentRegistrationStore(createNeonDatabase(databaseUrl));
34573
- var createDrizzleAgentDelegationStore = (db) => ({
34783
+ var createDrizzleAgentDelegationStoreFor = (db, table) => ({
34574
34784
  findActiveDelegation: async ({
34575
34785
  agentId,
34576
34786
  now = Date.now(),
34577
34787
  organizationId,
34578
34788
  userId
34579
34789
  }) => {
34580
- const organizationCondition = organizationId === undefined ? isNull(agentDelegationsTable.organization_id) : eq(agentDelegationsTable.organization_id, organizationId);
34581
- 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);
34790
+ const organizationCondition = organizationId === undefined ? isNull(table.organization_id) : eq(table.organization_id, organizationId);
34791
+ 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);
34582
34792
  return row === undefined ? undefined : toDelegation(row);
34583
34793
  },
34584
34794
  findByDelegationId: async (delegationId) => {
34585
- const [row] = await db.select().from(agentDelegationsTable).where(eq(agentDelegationsTable.delegation_id, delegationId)).limit(1);
34795
+ const [row] = await db.select().from(table).where(eq(table.delegation_id, delegationId)).limit(1);
34586
34796
  return row === undefined ? undefined : toDelegation(row);
34587
34797
  },
34588
34798
  listDelegations: async (agentId) => {
34589
- const base = db.select().from(agentDelegationsTable);
34590
- 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)));
34799
+ const base = db.select().from(table);
34800
+ 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)));
34591
34801
  return rows.map(toDelegation);
34592
34802
  },
34593
34803
  saveDelegation: async (delegation) => {
@@ -34603,36 +34813,38 @@ var createDrizzleAgentDelegationStore = (db) => ({
34603
34813
  updated_at_ms: delegation.updatedAt,
34604
34814
  user_id: delegation.userId
34605
34815
  };
34606
- await db.insert(agentDelegationsTable).values(values).onConflictDoUpdate({
34816
+ await db.insert(table).values(values).onConflictDoUpdate({
34607
34817
  set: values,
34608
- target: agentDelegationsTable.delegation_id
34818
+ target: table.delegation_id
34609
34819
  });
34610
34820
  }
34611
34821
  });
34822
+ var createDrizzleAgentDelegationStore = (db) => createDrizzleAgentDelegationStoreFor(db, agentDelegationsTable);
34823
+ var createBunSqlDrizzleAgentDelegationStore = (db) => createDrizzleAgentDelegationStoreFor(db, agentDelegationsBunSqlTable);
34612
34824
  var createPostgresAgentDelegationStore = createDrizzleAgentDelegationStore;
34613
- var createPostgresAgentIdentityRegistrationStore = (db) => ({
34825
+ var createPostgresAgentIdentityRegistrationStoreFor = (db, table) => ({
34614
34826
  create: async (registration) => {
34615
- const rows = await db.insert(agentIdentityRegistrationsTable).values(identityRegistrationValues(registration)).onConflictDoNothing().returning({ id: agentIdentityRegistrationsTable.registration_id });
34827
+ const rows = await db.insert(table).values(identityRegistrationValues(registration)).onConflictDoNothing().returning({ id: table.registration_id });
34616
34828
  return rows.length === 1;
34617
34829
  },
34618
34830
  findByAgentId: async (agentId) => {
34619
- const [row] = await db.select().from(agentIdentityRegistrationsTable).where(eq(agentIdentityRegistrationsTable.agent_id, agentId)).limit(1);
34831
+ const [row] = await db.select().from(table).where(eq(table.agent_id, agentId)).limit(1);
34620
34832
  return row === undefined ? undefined : toIdentityRegistration(row);
34621
34833
  },
34622
34834
  findByAttemptTokenHash: async (attemptTokenHash) => {
34623
- const [row] = await db.select().from(agentIdentityRegistrationsTable).where(eq(agentIdentityRegistrationsTable.claim_attempt_token_hash, attemptTokenHash)).limit(1);
34835
+ const [row] = await db.select().from(table).where(eq(table.claim_attempt_token_hash, attemptTokenHash)).limit(1);
34624
34836
  return row === undefined ? undefined : toIdentityRegistration(row);
34625
34837
  },
34626
34838
  findByClaimTokenHash: async (claimTokenHash) => {
34627
- const [row] = await db.select().from(agentIdentityRegistrationsTable).where(eq(agentIdentityRegistrationsTable.claim_token_hash, claimTokenHash)).limit(1);
34839
+ const [row] = await db.select().from(table).where(eq(table.claim_token_hash, claimTokenHash)).limit(1);
34628
34840
  return row === undefined ? undefined : toIdentityRegistration(row);
34629
34841
  },
34630
34842
  findByRegistrationId: async (registrationId) => {
34631
- const [row] = await db.select().from(agentIdentityRegistrationsTable).where(eq(agentIdentityRegistrationsTable.registration_id, registrationId)).limit(1);
34843
+ const [row] = await db.select().from(table).where(eq(table.registration_id, registrationId)).limit(1);
34632
34844
  return row === undefined ? undefined : toIdentityRegistration(row);
34633
34845
  },
34634
34846
  findByUpstreamIdentity: async ({ clientId, issuer, subject }) => {
34635
- 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);
34847
+ 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);
34636
34848
  return row === undefined ? undefined : toIdentityRegistration(row);
34637
34849
  },
34638
34850
  replace: async (registration, expectedVersion) => {
@@ -34641,21 +34853,23 @@ var createPostgresAgentIdentityRegistrationStore = (db) => ({
34641
34853
  version: expectedVersion + 1
34642
34854
  };
34643
34855
  const values = identityRegistrationValues(next);
34644
- 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 });
34856
+ 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 });
34645
34857
  return rows.length === 1;
34646
34858
  }
34647
34859
  });
34648
- var createPostgresAgentRegistrationStore = (db) => ({
34860
+ var createBunSqlDrizzleAgentIdentityRegistrationStore = (db) => createPostgresAgentIdentityRegistrationStoreFor(db, agentIdentityRegistrationsBunSqlTable);
34861
+ var createPostgresAgentIdentityRegistrationStore = (db) => createPostgresAgentIdentityRegistrationStoreFor(db, agentIdentityRegistrationsTable);
34862
+ var createPostgresAgentRegistrationStoreFor = (db, table) => ({
34649
34863
  findByAgentId: async (agentId) => {
34650
- const [row] = await db.select().from(agentRegistrationsTable).where(eq(agentRegistrationsTable.agent_id, agentId)).limit(1);
34864
+ const [row] = await db.select().from(table).where(eq(table.agent_id, agentId)).limit(1);
34651
34865
  return row === undefined ? undefined : toRegistration(row);
34652
34866
  },
34653
34867
  findByClientId: async (clientId) => {
34654
- const [row] = await db.select().from(agentRegistrationsTable).where(eq(agentRegistrationsTable.client_id, clientId)).limit(1);
34868
+ const [row] = await db.select().from(table).where(eq(table.client_id, clientId)).limit(1);
34655
34869
  return row === undefined ? undefined : toRegistration(row);
34656
34870
  },
34657
34871
  listRegistrations: async () => {
34658
- const rows = await db.select().from(agentRegistrationsTable).orderBy(desc(agentRegistrationsTable.created_at_ms));
34872
+ const rows = await db.select().from(table).orderBy(desc(table.created_at_ms));
34659
34873
  return rows.map(toRegistration);
34660
34874
  },
34661
34875
  saveRegistration: async (registration) => {
@@ -34669,12 +34883,14 @@ var createPostgresAgentRegistrationStore = (db) => ({
34669
34883
  status: registration.status,
34670
34884
  updated_at_ms: registration.updatedAt
34671
34885
  };
34672
- await db.insert(agentRegistrationsTable).values(values).onConflictDoUpdate({
34886
+ await db.insert(table).values(values).onConflictDoUpdate({
34673
34887
  set: values,
34674
- target: agentRegistrationsTable.agent_id
34888
+ target: table.agent_id
34675
34889
  });
34676
34890
  }
34677
34891
  });
34892
+ var createBunSqlDrizzleAgentRegistrationStore = (db) => createPostgresAgentRegistrationStoreFor(db, agentRegistrationsBunSqlTable);
34893
+ var createPostgresAgentRegistrationStore = (db) => createPostgresAgentRegistrationStoreFor(db, agentRegistrationsTable);
34678
34894
  // src/apikeys/inMemoryStores.ts
34679
34895
  var createInMemoryAccessTokenStore = () => {
34680
34896
  const tokens = new Map;
@@ -37026,6 +37242,14 @@ var oidcResourceAudienceMigration = {
37026
37242
  ].join(`
37027
37243
  `)
37028
37244
  };
37245
+ var sessionOAuthSubjectMigration = {
37246
+ id: "0002_oauth_subject",
37247
+ sql: [
37248
+ 'ALTER TABLE "auth_sessions" ADD COLUMN IF NOT EXISTS "oauth_subject_json" jsonb;',
37249
+ 'ALTER TABLE "auth_unregistered_sessions" ADD COLUMN IF NOT EXISTS "oauth_subject_json" jsonb;'
37250
+ ].join(`
37251
+ `)
37252
+ };
37029
37253
  var blockMigrations = {
37030
37254
  adaptive: initMigration("adaptive", [knownDevicesTable, loginHistoryTable]),
37031
37255
  agents: {
@@ -37094,10 +37318,16 @@ var blockMigrations = {
37094
37318
  portal: initMigration("portal", [setupSessionsTable]),
37095
37319
  roles: initMigration("roles", [rolesTable]),
37096
37320
  scim: initMigration("scim", [scimTokensTable]),
37097
- sessions: initMigration("sessions", [
37098
- authSessionsTable,
37099
- authUnregisteredSessionsTable
37100
- ]),
37321
+ sessions: {
37322
+ block: "sessions",
37323
+ migrations: [
37324
+ ...initMigration("sessions", [
37325
+ authSessionsTable,
37326
+ authUnregisteredSessionsTable
37327
+ ]).migrations,
37328
+ sessionOAuthSubjectMigration
37329
+ ]
37330
+ },
37101
37331
  sso: initMigration("sso", [ssoConnectionsTable, samlServiceProvidersTable]),
37102
37332
  vault: initMigration("vault", [vaultEntriesTable]),
37103
37333
  vc: initMigration("vc", [
@@ -37783,6 +38013,7 @@ var buildAuthApplications = async (configuration) => {
37783
38013
  resolveAuthIntent
37784
38014
  }),
37785
38015
  profile({
38016
+ authSessionStore,
37786
38017
  clientProviders,
37787
38018
  onProfileError,
37788
38019
  onProfileSuccess,
@@ -38052,5 +38283,5 @@ export {
38052
38283
  auth2 as auth
38053
38284
  };
38054
38285
 
38055
- //# debugId=365532246DA9FA0C64756E2164756E21
38286
+ //# debugId=8E94D3B40F6913D564756E2164756E21
38056
38287
  //# sourceMappingURL=server.js.map