@absolutejs/auth 0.22.5 → 0.22.6
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/example/components/auth/AuthContainer.d.ts +1 -0
- package/dist/example/components/auth/OAuthButton.d.ts +7 -0
- package/dist/example/components/auth/OAuthButtons.d.ts +5 -0
- package/dist/example/components/hamburger/HamburgerDropdown.d.ts +10 -0
- package/dist/example/components/hamburger/HamburgerHeader.d.ts +5 -0
- package/dist/example/components/hamburger/HamburgerMenu.d.ts +14 -0
- package/dist/example/components/hamburger/HamburgerUserButtons.d.ts +8 -0
- package/dist/example/components/navbar/DropdownContainer.d.ts +17 -0
- package/dist/example/components/navbar/Navbar.d.ts +7 -0
- package/dist/example/components/navbar/NavbarDropdown.d.ts +10 -0
- package/dist/example/components/navbar/NavbarLink.d.ts +8 -0
- package/dist/example/components/navbar/NavbarLinks.d.ts +6 -0
- package/dist/example/components/navbar/NavbarUserButtons.d.ts +7 -0
- package/dist/example/components/page/Head.d.ts +6 -0
- package/dist/example/components/protected/AccountOverview.d.ts +6 -0
- package/dist/example/components/protected/DeleteAccountSection.d.ts +5 -0
- package/dist/example/components/protected/LinkedAuthIdentitiesPanel.d.ts +1 -0
- package/dist/example/components/protected/LinkedProvidersPanel.d.ts +1 -0
- package/dist/example/components/protected/ProviderButtons.d.ts +1 -0
- package/dist/example/components/protected/SettingsNoticeToast.d.ts +1 -0
- package/dist/example/components/protected/UserInfo.d.ts +7 -0
- package/dist/example/components/utils/AnimatedComponents.d.ts +1 -0
- package/dist/example/components/utils/Divider.d.ts +7 -0
- package/dist/example/components/utils/HighlightedJson.d.ts +5 -0
- package/dist/example/components/utils/JsonLine.d.ts +6 -0
- package/dist/example/components/utils/Modal.d.ts +9 -0
- package/dist/example/components/utils/ProfilePicture.d.ts +8 -0
- package/dist/example/components/utils/ProviderDropdown.d.ts +8 -0
- package/dist/example/components/utils/Toast.d.ts +14 -0
- package/dist/example/components/utils/ToastProvider.d.ts +30 -0
- package/dist/example/db/schema.d.ts +2570 -0
- package/dist/example/eden/treaty.d.ts +1 -0
- package/dist/example/handlers/userHandlers.d.ts +254 -0
- package/dist/example/hooks/useAuthIdentityPayload.d.ts +37 -0
- package/dist/example/hooks/useAuthStatus.d.ts +19 -0
- package/dist/example/hooks/useContainerQuery.d.ts +10 -0
- package/dist/example/hooks/useMediaQuery.d.ts +11 -0
- package/dist/example/linkedProviders/persistCallbackAuthorization.d.ts +30 -0
- package/dist/example/linkedProviders/resolver.d.ts +1 -0
- package/dist/example/linkedProviders/stores.d.ts +9 -0
- package/dist/example/pages/Connectors.d.ts +1 -0
- package/dist/example/pages/Home.d.ts +1 -0
- package/dist/example/pages/NotAuthorized.d.ts +1 -0
- package/dist/example/pages/Protected.d.ts +1 -0
- package/dist/example/pages/Settings.d.ts +1 -0
- package/dist/example/server.d.ts +902 -0
- package/dist/example/styles/authModalStyles.d.ts +22 -0
- package/dist/example/styles/navbarStyles.d.ts +15 -0
- package/dist/example/styles/styles.d.ts +15 -0
- package/dist/example/utils/absoluteAuthConfig.d.ts +4 -0
- package/dist/example/utils/constants.d.ts +1 -0
- package/dist/example/utils/navbarData.d.ts +2 -0
- package/dist/example/utils/providerData.d.ts +9 -0
- package/dist/example/utils/providersConfiguration.d.ts +1 -0
- package/dist/example/utils/typeGuards.d.ts +1 -0
- package/dist/example/utils/types.d.ts +26 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +360 -246
- package/dist/index.js.map +7 -6
- package/dist/src/index.d.ts +1 -0
- package/dist/src/neonAuthSessionStore.d.ts +563 -0
- package/package.json +86 -74
- package/.claude/settings.local.json +0 -5
- package/.env.example +0 -212
- package/.prettierignore +0 -4
- package/.prettierrc.json +0 -9
- package/CLAUDE.md +0 -91
- package/drizzle.config.ts +0 -14
- package/eslint.config.mjs +0 -251
package/dist/index.js
CHANGED
|
@@ -3289,251 +3289,6 @@ var createInMemoryAuthSessionStore = (input = {}) => {
|
|
|
3289
3289
|
listUnregisteredSessionIds: async () => [...unregisteredSessions.keys()]
|
|
3290
3290
|
};
|
|
3291
3291
|
};
|
|
3292
|
-
// src/linkedProviderResolver.ts
|
|
3293
|
-
var uniqueStrings = (values) => [...new Set(values)];
|
|
3294
|
-
var getEffectiveScopes = (grant, binding) => {
|
|
3295
|
-
if (binding.availableScopes.length === 0) {
|
|
3296
|
-
return uniqueStrings(grant.grantedScopes);
|
|
3297
|
-
}
|
|
3298
|
-
const bindingScopeSet = new Set(binding.availableScopes);
|
|
3299
|
-
return uniqueStrings(grant.grantedScopes.filter((scope) => bindingScopeSet.has(scope)));
|
|
3300
|
-
};
|
|
3301
|
-
var hasRequiredScopes = (availableScopes, requiredScopes) => (requiredScopes ?? []).every((scope) => availableScopes.includes(scope));
|
|
3302
|
-
var isGrantUsable = (grant) => grant.status === "active" || grant.status === "refresh_required";
|
|
3303
|
-
var isBindingUsable = (binding) => binding.status === "active";
|
|
3304
|
-
var needsRefresh = (lease, now, minValidityMs) => {
|
|
3305
|
-
if (!lease)
|
|
3306
|
-
return true;
|
|
3307
|
-
if (lease.expiresAt === undefined)
|
|
3308
|
-
return false;
|
|
3309
|
-
return lease.expiresAt <= now + (minValidityMs ?? 0);
|
|
3310
|
-
};
|
|
3311
|
-
var ensureLeaseScopes = (lease, requiredScopes) => {
|
|
3312
|
-
if (!hasRequiredScopes(lease.grantedScopes, requiredScopes)) {
|
|
3313
|
-
throw new Error("Linked provider access token lease is missing required scopes");
|
|
3314
|
-
}
|
|
3315
|
-
};
|
|
3316
|
-
var ensureLeaseValidity = (lease, now, minValidityMs) => {
|
|
3317
|
-
if (lease.expiresAt === undefined)
|
|
3318
|
-
return;
|
|
3319
|
-
if (lease.expiresAt <= now + (minValidityMs ?? 0)) {
|
|
3320
|
-
throw new Error("Linked provider access token lease does not satisfy minimum validity");
|
|
3321
|
-
}
|
|
3322
|
-
};
|
|
3323
|
-
var buildResolvedCredential = (grant, binding) => ({
|
|
3324
|
-
bindingId: binding.id,
|
|
3325
|
-
grantId: grant.id,
|
|
3326
|
-
ownerRef: grant.ownerRef,
|
|
3327
|
-
connectorProvider: binding.connectorProvider,
|
|
3328
|
-
providerFamily: grant.providerFamily,
|
|
3329
|
-
authProviderKey: grant.authProviderKey,
|
|
3330
|
-
externalAccountId: binding.externalAccountId,
|
|
3331
|
-
externalAccountType: binding.externalAccountType,
|
|
3332
|
-
scopes: getEffectiveScopes(grant, binding),
|
|
3333
|
-
capabilities: binding.capabilities ? [...binding.capabilities] : undefined,
|
|
3334
|
-
label: binding.label,
|
|
3335
|
-
username: binding.username,
|
|
3336
|
-
email: binding.email,
|
|
3337
|
-
metadata: {
|
|
3338
|
-
...grant.metadata ?? {},
|
|
3339
|
-
...binding.metadata ?? {}
|
|
3340
|
-
}
|
|
3341
|
-
});
|
|
3342
|
-
var annotateFailureMetadata = (metadata, report, now) => ({
|
|
3343
|
-
...metadata ?? {},
|
|
3344
|
-
lastCredentialFailureAt: now,
|
|
3345
|
-
lastCredentialFailureCode: report.code,
|
|
3346
|
-
lastCredentialFailureMessage: report.message,
|
|
3347
|
-
lastCredentialFailureRetryAt: report.retryAt
|
|
3348
|
-
});
|
|
3349
|
-
var sortNewestFirst = (items) => [...items].sort((left, right) => right.updatedAt - left.updatedAt);
|
|
3350
|
-
var createLinkedProviderCredentialResolver = ({
|
|
3351
|
-
grantStore,
|
|
3352
|
-
bindingStore,
|
|
3353
|
-
loadAccessTokenLease,
|
|
3354
|
-
refreshAccessTokenLease,
|
|
3355
|
-
now = () => Date.now(),
|
|
3356
|
-
onReportFailure
|
|
3357
|
-
}) => ({
|
|
3358
|
-
listBindings: async ({ ownerRef, connectorProvider, status }) => sortNewestFirst(await bindingStore.listBindingsByOwner(ownerRef)).filter((binding) => (connectorProvider === undefined || binding.connectorProvider === connectorProvider) && (status === undefined || binding.status === status)),
|
|
3359
|
-
resolveCredential: async (input) => {
|
|
3360
|
-
const bindings = sortNewestFirst(await bindingStore.listBindingsByOwner(input.ownerRef)).filter((binding) => binding.connectorProvider === input.connectorProvider && isBindingUsable(binding) && (input.bindingId === undefined || binding.id === input.bindingId) && (input.externalAccountId === undefined || binding.externalAccountId === input.externalAccountId));
|
|
3361
|
-
for (const binding of bindings) {
|
|
3362
|
-
const grant = await grantStore.getGrant(binding.grantId);
|
|
3363
|
-
if (!grant || grant.ownerRef !== input.ownerRef || !isGrantUsable(grant)) {
|
|
3364
|
-
continue;
|
|
3365
|
-
}
|
|
3366
|
-
const effectiveScopes = getEffectiveScopes(grant, binding);
|
|
3367
|
-
if (!hasRequiredScopes(effectiveScopes, input.requiredScopes)) {
|
|
3368
|
-
continue;
|
|
3369
|
-
}
|
|
3370
|
-
return buildResolvedCredential(grant, binding);
|
|
3371
|
-
}
|
|
3372
|
-
return null;
|
|
3373
|
-
},
|
|
3374
|
-
getAccessToken: async (credential, input) => {
|
|
3375
|
-
const binding = await bindingStore.getBinding(credential.bindingId);
|
|
3376
|
-
if (!binding || !isBindingUsable(binding)) {
|
|
3377
|
-
throw new Error("Linked provider binding is unavailable");
|
|
3378
|
-
}
|
|
3379
|
-
const grant = await grantStore.getGrant(credential.grantId);
|
|
3380
|
-
if (!grant || !isGrantUsable(grant)) {
|
|
3381
|
-
throw new Error("Linked provider grant is unavailable");
|
|
3382
|
-
}
|
|
3383
|
-
const requiredScopes = input?.requiredScopes;
|
|
3384
|
-
const effectiveScopes = getEffectiveScopes(grant, binding);
|
|
3385
|
-
if (!hasRequiredScopes(effectiveScopes, requiredScopes)) {
|
|
3386
|
-
throw new Error("Linked provider credential is missing required scopes");
|
|
3387
|
-
}
|
|
3388
|
-
const currentTime = now();
|
|
3389
|
-
let lease = await loadAccessTokenLease(grant);
|
|
3390
|
-
if (needsRefresh(lease, currentTime, input?.minValidityMs)) {
|
|
3391
|
-
if (!refreshAccessTokenLease) {
|
|
3392
|
-
throw new Error("Linked provider access token lease requires refresh");
|
|
3393
|
-
}
|
|
3394
|
-
const refreshed = await refreshAccessTokenLease(grant, input);
|
|
3395
|
-
if (!refreshed) {
|
|
3396
|
-
throw new Error("Linked provider access token refresh failed");
|
|
3397
|
-
}
|
|
3398
|
-
await grantStore.saveGrant(refreshed.grant);
|
|
3399
|
-
lease = refreshed.lease;
|
|
3400
|
-
}
|
|
3401
|
-
if (!lease) {
|
|
3402
|
-
throw new Error("Linked provider access token lease is unavailable");
|
|
3403
|
-
}
|
|
3404
|
-
ensureLeaseScopes(lease, requiredScopes);
|
|
3405
|
-
ensureLeaseValidity(lease, currentTime, input?.minValidityMs);
|
|
3406
|
-
return lease;
|
|
3407
|
-
},
|
|
3408
|
-
reportFailure: async (credential, report) => {
|
|
3409
|
-
const currentTime = now();
|
|
3410
|
-
const grant = await grantStore.getGrant(credential.grantId);
|
|
3411
|
-
const binding = await bindingStore.getBinding(credential.bindingId);
|
|
3412
|
-
if (grant) {
|
|
3413
|
-
const nextGrant = {
|
|
3414
|
-
...grant,
|
|
3415
|
-
updatedAt: currentTime,
|
|
3416
|
-
lastRefreshError: report.message ?? report.code,
|
|
3417
|
-
metadata: annotateFailureMetadata(grant.metadata, report, currentTime)
|
|
3418
|
-
};
|
|
3419
|
-
if (report.code === "unauthorized" || report.code === "revoked") {
|
|
3420
|
-
nextGrant.status = "revoked";
|
|
3421
|
-
}
|
|
3422
|
-
await grantStore.saveGrant(nextGrant);
|
|
3423
|
-
}
|
|
3424
|
-
if (binding) {
|
|
3425
|
-
const nextBinding = {
|
|
3426
|
-
...binding,
|
|
3427
|
-
updatedAt: currentTime,
|
|
3428
|
-
metadata: annotateFailureMetadata(binding.metadata, report, currentTime)
|
|
3429
|
-
};
|
|
3430
|
-
if (report.code === "unauthorized" || report.code === "revoked") {
|
|
3431
|
-
nextBinding.status = "disconnected";
|
|
3432
|
-
} else if (report.code === "insufficient_scope") {
|
|
3433
|
-
nextBinding.status = "restricted";
|
|
3434
|
-
}
|
|
3435
|
-
await bindingStore.saveBinding(nextBinding);
|
|
3436
|
-
}
|
|
3437
|
-
await onReportFailure?.({
|
|
3438
|
-
credential,
|
|
3439
|
-
report,
|
|
3440
|
-
grant: grant ?? undefined,
|
|
3441
|
-
binding: binding ?? undefined
|
|
3442
|
-
});
|
|
3443
|
-
}
|
|
3444
|
-
});
|
|
3445
|
-
// src/oauthLinkedProviderResolver.ts
|
|
3446
|
-
var getGrantedScopes = (scopeValue, fallbackScopes) => {
|
|
3447
|
-
if (typeof scopeValue === "string" && scopeValue.trim().length > 0) {
|
|
3448
|
-
return [...new Set(scopeValue.split(/\s+/).filter(Boolean))];
|
|
3449
|
-
}
|
|
3450
|
-
return [...new Set(fallbackScopes.filter(Boolean))];
|
|
3451
|
-
};
|
|
3452
|
-
var getExpiresAt = (tokenResponse) => {
|
|
3453
|
-
const expiresIn = tokenResponse.expires_in;
|
|
3454
|
-
const expiresInSeconds = typeof expiresIn === "number" ? expiresIn : typeof expiresIn === "string" && expiresIn.trim().length > 0 ? Number(expiresIn) : Number.NaN;
|
|
3455
|
-
if (!Number.isFinite(expiresInSeconds) || expiresInSeconds <= 0) {
|
|
3456
|
-
return;
|
|
3457
|
-
}
|
|
3458
|
-
return Date.now() + expiresInSeconds * 1000;
|
|
3459
|
-
};
|
|
3460
|
-
var createOAuthLinkedProviderCredentialResolver = async ({
|
|
3461
|
-
bindingStore,
|
|
3462
|
-
grantStore,
|
|
3463
|
-
now,
|
|
3464
|
-
providersConfiguration
|
|
3465
|
-
}) => {
|
|
3466
|
-
const clientEntries = [];
|
|
3467
|
-
for (const [providerName, providerConfig] of Object.entries(providersConfiguration)) {
|
|
3468
|
-
if (!isValidProviderOption(providerName)) {
|
|
3469
|
-
continue;
|
|
3470
|
-
}
|
|
3471
|
-
const resolvedProviderClientConfiguration = resolveProviderClientConfiguration({
|
|
3472
|
-
providerName,
|
|
3473
|
-
providersConfiguration
|
|
3474
|
-
});
|
|
3475
|
-
if ("error" in resolvedProviderClientConfiguration || !resolvedProviderClientConfiguration.config) {
|
|
3476
|
-
continue;
|
|
3477
|
-
}
|
|
3478
|
-
clientEntries.push(createOAuth2Client(providerName, resolvedProviderClientConfiguration.config.credentials).then((providerInstance) => [providerName, providerInstance]));
|
|
3479
|
-
}
|
|
3480
|
-
const clients = new Map(await Promise.all(clientEntries));
|
|
3481
|
-
return createLinkedProviderCredentialResolver({
|
|
3482
|
-
bindingStore,
|
|
3483
|
-
grantStore,
|
|
3484
|
-
now,
|
|
3485
|
-
loadAccessTokenLease: async (grant) => grant.accessTokenCiphertext ? {
|
|
3486
|
-
accessToken: grant.accessTokenCiphertext,
|
|
3487
|
-
expiresAt: grant.expiresAt,
|
|
3488
|
-
grantedScopes: grant.grantedScopes,
|
|
3489
|
-
tokenType: grant.tokenType
|
|
3490
|
-
} : null,
|
|
3491
|
-
refreshAccessTokenLease: async (grant) => {
|
|
3492
|
-
if (!isValidProviderOption(grant.authProviderKey) || !grant.refreshTokenCiphertext) {
|
|
3493
|
-
return null;
|
|
3494
|
-
}
|
|
3495
|
-
const providerKey = grant.authProviderKey;
|
|
3496
|
-
const providerClientName = typeof grant.metadata?.providerClient === "string" && grant.metadata.providerClient.trim().length > 0 ? grant.metadata.providerClient.trim() : undefined;
|
|
3497
|
-
const resolvedProviderClientConfiguration = resolveProviderClientConfiguration({
|
|
3498
|
-
clientName: providerClientName,
|
|
3499
|
-
providerName: providerKey,
|
|
3500
|
-
providersConfiguration
|
|
3501
|
-
});
|
|
3502
|
-
if ("error" in resolvedProviderClientConfiguration || !resolvedProviderClientConfiguration.config) {
|
|
3503
|
-
return null;
|
|
3504
|
-
}
|
|
3505
|
-
const providerClient = await createOAuth2Client(providerKey, resolvedProviderClientConfiguration.config.credentials);
|
|
3506
|
-
if (!providerClient || !isRefreshableOAuth2Client(providerKey, providerClient)) {
|
|
3507
|
-
return null;
|
|
3508
|
-
}
|
|
3509
|
-
const tokenResponse = await providerClient.refreshAccessToken(grant.refreshTokenCiphertext);
|
|
3510
|
-
const refreshedAt = Date.now();
|
|
3511
|
-
const grantedScopes = getGrantedScopes(Reflect.get(tokenResponse, "scope"), grant.grantedScopes);
|
|
3512
|
-
const tokenType = Reflect.get(tokenResponse, "token_type");
|
|
3513
|
-
const refreshedGrant = {
|
|
3514
|
-
...grant,
|
|
3515
|
-
accessTokenCiphertext: tokenResponse.access_token,
|
|
3516
|
-
expiresAt: getExpiresAt(tokenResponse),
|
|
3517
|
-
grantedScopes,
|
|
3518
|
-
lastRefreshError: undefined,
|
|
3519
|
-
lastRefreshedAt: refreshedAt,
|
|
3520
|
-
refreshTokenCiphertext: tokenResponse.refresh_token ?? grant.refreshTokenCiphertext,
|
|
3521
|
-
status: "active",
|
|
3522
|
-
tokenType: typeof tokenType === "string" ? tokenType : grant.tokenType,
|
|
3523
|
-
updatedAt: refreshedAt
|
|
3524
|
-
};
|
|
3525
|
-
return {
|
|
3526
|
-
grant: refreshedGrant,
|
|
3527
|
-
lease: {
|
|
3528
|
-
accessToken: refreshedGrant.accessTokenCiphertext ?? "",
|
|
3529
|
-
expiresAt: refreshedGrant.expiresAt,
|
|
3530
|
-
grantedScopes: refreshedGrant.grantedScopes,
|
|
3531
|
-
tokenType: refreshedGrant.tokenType
|
|
3532
|
-
}
|
|
3533
|
-
};
|
|
3534
|
-
}
|
|
3535
|
-
});
|
|
3536
|
-
};
|
|
3537
3292
|
// node_modules/@neondatabase/serverless/index.mjs
|
|
3538
3293
|
var vo = Object.create;
|
|
3539
3294
|
var Te = Object.defineProperty;
|
|
@@ -13227,6 +12982,364 @@ function drizzle(...params) {
|
|
|
13227
12982
|
drizzle2.mock = mock;
|
|
13228
12983
|
})(drizzle || (drizzle = {}));
|
|
13229
12984
|
|
|
12985
|
+
// src/neonAuthSessionStore.ts
|
|
12986
|
+
var authSessionsTable = pgTable("auth_sessions", {
|
|
12987
|
+
id: varchar("id", { length: 255 }).primaryKey(),
|
|
12988
|
+
access_token: text("access_token").notNull(),
|
|
12989
|
+
refresh_token: text("refresh_token"),
|
|
12990
|
+
expires_at_ms: bigint("expires_at_ms", { mode: "number" }).notNull(),
|
|
12991
|
+
user_json: jsonb("user_json").$type().notNull(),
|
|
12992
|
+
created_at: timestamp("created_at").notNull().defaultNow(),
|
|
12993
|
+
updated_at: timestamp("updated_at").notNull().defaultNow()
|
|
12994
|
+
});
|
|
12995
|
+
var authUnregisteredSessionsTable = pgTable("auth_unregistered_sessions", {
|
|
12996
|
+
id: varchar("id", { length: 255 }).primaryKey(),
|
|
12997
|
+
access_token: text("access_token"),
|
|
12998
|
+
refresh_token: text("refresh_token"),
|
|
12999
|
+
expires_at_ms: bigint("expires_at_ms", { mode: "number" }).notNull(),
|
|
13000
|
+
user_identity_json: jsonb("user_identity_json").$type(),
|
|
13001
|
+
session_information_json: jsonb("session_information_json").$type(),
|
|
13002
|
+
created_at: timestamp("created_at").notNull().defaultNow(),
|
|
13003
|
+
updated_at: timestamp("updated_at").notNull().defaultNow()
|
|
13004
|
+
});
|
|
13005
|
+
var authSessionSchema = {
|
|
13006
|
+
authSessions: authSessionsTable,
|
|
13007
|
+
authUnregisteredSessions: authUnregisteredSessionsTable
|
|
13008
|
+
};
|
|
13009
|
+
var cloneUser = (value) => {
|
|
13010
|
+
if (value === null || value === undefined)
|
|
13011
|
+
return value;
|
|
13012
|
+
return structuredClone(value);
|
|
13013
|
+
};
|
|
13014
|
+
var cloneRecord = (value) => value ? structuredClone(value) : undefined;
|
|
13015
|
+
var toSessionData = (row) => ({
|
|
13016
|
+
accessToken: row.access_token,
|
|
13017
|
+
expiresAt: row.expires_at_ms,
|
|
13018
|
+
refreshToken: row.refresh_token ?? undefined,
|
|
13019
|
+
user: cloneUser(row.user_json)
|
|
13020
|
+
});
|
|
13021
|
+
var toUnregisteredSessionData = (row) => ({
|
|
13022
|
+
accessToken: row.access_token ?? undefined,
|
|
13023
|
+
expiresAt: row.expires_at_ms,
|
|
13024
|
+
refreshToken: row.refresh_token ?? undefined,
|
|
13025
|
+
sessionInformation: cloneRecord(row.session_information_json ?? undefined),
|
|
13026
|
+
userIdentity: cloneRecord(row.user_identity_json ?? undefined)
|
|
13027
|
+
});
|
|
13028
|
+
var createNeonAuthSessionStore = (databaseUrl) => {
|
|
13029
|
+
const sql2 = as(databaseUrl);
|
|
13030
|
+
const db = drizzle(sql2, {
|
|
13031
|
+
schema: authSessionSchema
|
|
13032
|
+
});
|
|
13033
|
+
return {
|
|
13034
|
+
getSession: async (id) => {
|
|
13035
|
+
const [row] = await db.select().from(authSessionsTable).where(eq(authSessionsTable.id, id)).limit(1);
|
|
13036
|
+
return row ? toSessionData(row) : undefined;
|
|
13037
|
+
},
|
|
13038
|
+
setSession: async (id, value) => {
|
|
13039
|
+
await db.insert(authSessionsTable).values({
|
|
13040
|
+
id,
|
|
13041
|
+
access_token: value.accessToken,
|
|
13042
|
+
refresh_token: value.refreshToken ?? null,
|
|
13043
|
+
expires_at_ms: value.expiresAt,
|
|
13044
|
+
user_json: value.user ?? {},
|
|
13045
|
+
updated_at: new Date
|
|
13046
|
+
}).onConflictDoUpdate({
|
|
13047
|
+
target: authSessionsTable.id,
|
|
13048
|
+
set: {
|
|
13049
|
+
access_token: value.accessToken,
|
|
13050
|
+
refresh_token: value.refreshToken ?? null,
|
|
13051
|
+
expires_at_ms: value.expiresAt,
|
|
13052
|
+
user_json: value.user ?? {},
|
|
13053
|
+
updated_at: new Date
|
|
13054
|
+
}
|
|
13055
|
+
});
|
|
13056
|
+
},
|
|
13057
|
+
removeSession: async (id) => {
|
|
13058
|
+
await db.delete(authSessionsTable).where(eq(authSessionsTable.id, id));
|
|
13059
|
+
},
|
|
13060
|
+
getUnregisteredSession: async (id) => {
|
|
13061
|
+
const [row] = await db.select().from(authUnregisteredSessionsTable).where(eq(authUnregisteredSessionsTable.id, id)).limit(1);
|
|
13062
|
+
return row ? toUnregisteredSessionData(row) : undefined;
|
|
13063
|
+
},
|
|
13064
|
+
setUnregisteredSession: async (id, value) => {
|
|
13065
|
+
await db.insert(authUnregisteredSessionsTable).values({
|
|
13066
|
+
id,
|
|
13067
|
+
access_token: value.accessToken ?? null,
|
|
13068
|
+
refresh_token: value.refreshToken ?? null,
|
|
13069
|
+
expires_at_ms: value.expiresAt,
|
|
13070
|
+
user_identity_json: value.userIdentity ?? null,
|
|
13071
|
+
session_information_json: value.sessionInformation ?? null,
|
|
13072
|
+
updated_at: new Date
|
|
13073
|
+
}).onConflictDoUpdate({
|
|
13074
|
+
target: authUnregisteredSessionsTable.id,
|
|
13075
|
+
set: {
|
|
13076
|
+
access_token: value.accessToken ?? null,
|
|
13077
|
+
refresh_token: value.refreshToken ?? null,
|
|
13078
|
+
expires_at_ms: value.expiresAt,
|
|
13079
|
+
user_identity_json: value.userIdentity ?? null,
|
|
13080
|
+
session_information_json: value.sessionInformation ?? null,
|
|
13081
|
+
updated_at: new Date
|
|
13082
|
+
}
|
|
13083
|
+
});
|
|
13084
|
+
},
|
|
13085
|
+
removeUnregisteredSession: async (id) => {
|
|
13086
|
+
await db.delete(authUnregisteredSessionsTable).where(eq(authUnregisteredSessionsTable.id, id));
|
|
13087
|
+
},
|
|
13088
|
+
listSessionIds: async () => {
|
|
13089
|
+
const rows = await db.select({ id: authSessionsTable.id }).from(authSessionsTable);
|
|
13090
|
+
return rows.map((row) => row.id);
|
|
13091
|
+
},
|
|
13092
|
+
listUnregisteredSessionIds: async () => {
|
|
13093
|
+
const rows = await db.select({ id: authUnregisteredSessionsTable.id }).from(authUnregisteredSessionsTable);
|
|
13094
|
+
return rows.map((row) => row.id);
|
|
13095
|
+
}
|
|
13096
|
+
};
|
|
13097
|
+
};
|
|
13098
|
+
// src/linkedProviderResolver.ts
|
|
13099
|
+
var uniqueStrings = (values) => [...new Set(values)];
|
|
13100
|
+
var getEffectiveScopes = (grant, binding) => {
|
|
13101
|
+
if (binding.availableScopes.length === 0) {
|
|
13102
|
+
return uniqueStrings(grant.grantedScopes);
|
|
13103
|
+
}
|
|
13104
|
+
const bindingScopeSet = new Set(binding.availableScopes);
|
|
13105
|
+
return uniqueStrings(grant.grantedScopes.filter((scope) => bindingScopeSet.has(scope)));
|
|
13106
|
+
};
|
|
13107
|
+
var hasRequiredScopes = (availableScopes, requiredScopes) => (requiredScopes ?? []).every((scope) => availableScopes.includes(scope));
|
|
13108
|
+
var isGrantUsable = (grant) => grant.status === "active" || grant.status === "refresh_required";
|
|
13109
|
+
var isBindingUsable = (binding) => binding.status === "active";
|
|
13110
|
+
var needsRefresh = (lease, now, minValidityMs) => {
|
|
13111
|
+
if (!lease)
|
|
13112
|
+
return true;
|
|
13113
|
+
if (lease.expiresAt === undefined)
|
|
13114
|
+
return false;
|
|
13115
|
+
return lease.expiresAt <= now + (minValidityMs ?? 0);
|
|
13116
|
+
};
|
|
13117
|
+
var ensureLeaseScopes = (lease, requiredScopes) => {
|
|
13118
|
+
if (!hasRequiredScopes(lease.grantedScopes, requiredScopes)) {
|
|
13119
|
+
throw new Error("Linked provider access token lease is missing required scopes");
|
|
13120
|
+
}
|
|
13121
|
+
};
|
|
13122
|
+
var ensureLeaseValidity = (lease, now, minValidityMs) => {
|
|
13123
|
+
if (lease.expiresAt === undefined)
|
|
13124
|
+
return;
|
|
13125
|
+
if (lease.expiresAt <= now + (minValidityMs ?? 0)) {
|
|
13126
|
+
throw new Error("Linked provider access token lease does not satisfy minimum validity");
|
|
13127
|
+
}
|
|
13128
|
+
};
|
|
13129
|
+
var buildResolvedCredential = (grant, binding) => ({
|
|
13130
|
+
bindingId: binding.id,
|
|
13131
|
+
grantId: grant.id,
|
|
13132
|
+
ownerRef: grant.ownerRef,
|
|
13133
|
+
connectorProvider: binding.connectorProvider,
|
|
13134
|
+
providerFamily: grant.providerFamily,
|
|
13135
|
+
authProviderKey: grant.authProviderKey,
|
|
13136
|
+
externalAccountId: binding.externalAccountId,
|
|
13137
|
+
externalAccountType: binding.externalAccountType,
|
|
13138
|
+
scopes: getEffectiveScopes(grant, binding),
|
|
13139
|
+
capabilities: binding.capabilities ? [...binding.capabilities] : undefined,
|
|
13140
|
+
label: binding.label,
|
|
13141
|
+
username: binding.username,
|
|
13142
|
+
email: binding.email,
|
|
13143
|
+
metadata: {
|
|
13144
|
+
...grant.metadata ?? {},
|
|
13145
|
+
...binding.metadata ?? {}
|
|
13146
|
+
}
|
|
13147
|
+
});
|
|
13148
|
+
var annotateFailureMetadata = (metadata, report, now) => ({
|
|
13149
|
+
...metadata ?? {},
|
|
13150
|
+
lastCredentialFailureAt: now,
|
|
13151
|
+
lastCredentialFailureCode: report.code,
|
|
13152
|
+
lastCredentialFailureMessage: report.message,
|
|
13153
|
+
lastCredentialFailureRetryAt: report.retryAt
|
|
13154
|
+
});
|
|
13155
|
+
var sortNewestFirst = (items) => [...items].sort((left, right) => right.updatedAt - left.updatedAt);
|
|
13156
|
+
var createLinkedProviderCredentialResolver = ({
|
|
13157
|
+
grantStore,
|
|
13158
|
+
bindingStore,
|
|
13159
|
+
loadAccessTokenLease,
|
|
13160
|
+
refreshAccessTokenLease,
|
|
13161
|
+
now = () => Date.now(),
|
|
13162
|
+
onReportFailure
|
|
13163
|
+
}) => ({
|
|
13164
|
+
listBindings: async ({ ownerRef, connectorProvider, status }) => sortNewestFirst(await bindingStore.listBindingsByOwner(ownerRef)).filter((binding) => (connectorProvider === undefined || binding.connectorProvider === connectorProvider) && (status === undefined || binding.status === status)),
|
|
13165
|
+
resolveCredential: async (input) => {
|
|
13166
|
+
const bindings = sortNewestFirst(await bindingStore.listBindingsByOwner(input.ownerRef)).filter((binding) => binding.connectorProvider === input.connectorProvider && isBindingUsable(binding) && (input.bindingId === undefined || binding.id === input.bindingId) && (input.externalAccountId === undefined || binding.externalAccountId === input.externalAccountId));
|
|
13167
|
+
for (const binding of bindings) {
|
|
13168
|
+
const grant = await grantStore.getGrant(binding.grantId);
|
|
13169
|
+
if (!grant || grant.ownerRef !== input.ownerRef || !isGrantUsable(grant)) {
|
|
13170
|
+
continue;
|
|
13171
|
+
}
|
|
13172
|
+
const effectiveScopes = getEffectiveScopes(grant, binding);
|
|
13173
|
+
if (!hasRequiredScopes(effectiveScopes, input.requiredScopes)) {
|
|
13174
|
+
continue;
|
|
13175
|
+
}
|
|
13176
|
+
return buildResolvedCredential(grant, binding);
|
|
13177
|
+
}
|
|
13178
|
+
return null;
|
|
13179
|
+
},
|
|
13180
|
+
getAccessToken: async (credential, input) => {
|
|
13181
|
+
const binding = await bindingStore.getBinding(credential.bindingId);
|
|
13182
|
+
if (!binding || !isBindingUsable(binding)) {
|
|
13183
|
+
throw new Error("Linked provider binding is unavailable");
|
|
13184
|
+
}
|
|
13185
|
+
const grant = await grantStore.getGrant(credential.grantId);
|
|
13186
|
+
if (!grant || !isGrantUsable(grant)) {
|
|
13187
|
+
throw new Error("Linked provider grant is unavailable");
|
|
13188
|
+
}
|
|
13189
|
+
const requiredScopes = input?.requiredScopes;
|
|
13190
|
+
const effectiveScopes = getEffectiveScopes(grant, binding);
|
|
13191
|
+
if (!hasRequiredScopes(effectiveScopes, requiredScopes)) {
|
|
13192
|
+
throw new Error("Linked provider credential is missing required scopes");
|
|
13193
|
+
}
|
|
13194
|
+
const currentTime = now();
|
|
13195
|
+
let lease = await loadAccessTokenLease(grant);
|
|
13196
|
+
if (needsRefresh(lease, currentTime, input?.minValidityMs)) {
|
|
13197
|
+
if (!refreshAccessTokenLease) {
|
|
13198
|
+
throw new Error("Linked provider access token lease requires refresh");
|
|
13199
|
+
}
|
|
13200
|
+
const refreshed = await refreshAccessTokenLease(grant, input);
|
|
13201
|
+
if (!refreshed) {
|
|
13202
|
+
throw new Error("Linked provider access token refresh failed");
|
|
13203
|
+
}
|
|
13204
|
+
await grantStore.saveGrant(refreshed.grant);
|
|
13205
|
+
lease = refreshed.lease;
|
|
13206
|
+
}
|
|
13207
|
+
if (!lease) {
|
|
13208
|
+
throw new Error("Linked provider access token lease is unavailable");
|
|
13209
|
+
}
|
|
13210
|
+
ensureLeaseScopes(lease, requiredScopes);
|
|
13211
|
+
ensureLeaseValidity(lease, currentTime, input?.minValidityMs);
|
|
13212
|
+
return lease;
|
|
13213
|
+
},
|
|
13214
|
+
reportFailure: async (credential, report) => {
|
|
13215
|
+
const currentTime = now();
|
|
13216
|
+
const grant = await grantStore.getGrant(credential.grantId);
|
|
13217
|
+
const binding = await bindingStore.getBinding(credential.bindingId);
|
|
13218
|
+
if (grant) {
|
|
13219
|
+
const nextGrant = {
|
|
13220
|
+
...grant,
|
|
13221
|
+
updatedAt: currentTime,
|
|
13222
|
+
lastRefreshError: report.message ?? report.code,
|
|
13223
|
+
metadata: annotateFailureMetadata(grant.metadata, report, currentTime)
|
|
13224
|
+
};
|
|
13225
|
+
if (report.code === "unauthorized" || report.code === "revoked") {
|
|
13226
|
+
nextGrant.status = "revoked";
|
|
13227
|
+
}
|
|
13228
|
+
await grantStore.saveGrant(nextGrant);
|
|
13229
|
+
}
|
|
13230
|
+
if (binding) {
|
|
13231
|
+
const nextBinding = {
|
|
13232
|
+
...binding,
|
|
13233
|
+
updatedAt: currentTime,
|
|
13234
|
+
metadata: annotateFailureMetadata(binding.metadata, report, currentTime)
|
|
13235
|
+
};
|
|
13236
|
+
if (report.code === "unauthorized" || report.code === "revoked") {
|
|
13237
|
+
nextBinding.status = "disconnected";
|
|
13238
|
+
} else if (report.code === "insufficient_scope") {
|
|
13239
|
+
nextBinding.status = "restricted";
|
|
13240
|
+
}
|
|
13241
|
+
await bindingStore.saveBinding(nextBinding);
|
|
13242
|
+
}
|
|
13243
|
+
await onReportFailure?.({
|
|
13244
|
+
credential,
|
|
13245
|
+
report,
|
|
13246
|
+
grant: grant ?? undefined,
|
|
13247
|
+
binding: binding ?? undefined
|
|
13248
|
+
});
|
|
13249
|
+
}
|
|
13250
|
+
});
|
|
13251
|
+
// src/oauthLinkedProviderResolver.ts
|
|
13252
|
+
var getGrantedScopes = (scopeValue, fallbackScopes) => {
|
|
13253
|
+
if (typeof scopeValue === "string" && scopeValue.trim().length > 0) {
|
|
13254
|
+
return [...new Set(scopeValue.split(/\s+/).filter(Boolean))];
|
|
13255
|
+
}
|
|
13256
|
+
return [...new Set(fallbackScopes.filter(Boolean))];
|
|
13257
|
+
};
|
|
13258
|
+
var getExpiresAt = (tokenResponse) => {
|
|
13259
|
+
const expiresIn = tokenResponse.expires_in;
|
|
13260
|
+
const expiresInSeconds = typeof expiresIn === "number" ? expiresIn : typeof expiresIn === "string" && expiresIn.trim().length > 0 ? Number(expiresIn) : Number.NaN;
|
|
13261
|
+
if (!Number.isFinite(expiresInSeconds) || expiresInSeconds <= 0) {
|
|
13262
|
+
return;
|
|
13263
|
+
}
|
|
13264
|
+
return Date.now() + expiresInSeconds * 1000;
|
|
13265
|
+
};
|
|
13266
|
+
var createOAuthLinkedProviderCredentialResolver = async ({
|
|
13267
|
+
bindingStore,
|
|
13268
|
+
grantStore,
|
|
13269
|
+
now,
|
|
13270
|
+
providersConfiguration
|
|
13271
|
+
}) => {
|
|
13272
|
+
const clientEntries = [];
|
|
13273
|
+
for (const [providerName, providerConfig] of Object.entries(providersConfiguration)) {
|
|
13274
|
+
if (!isValidProviderOption(providerName)) {
|
|
13275
|
+
continue;
|
|
13276
|
+
}
|
|
13277
|
+
const resolvedProviderClientConfiguration = resolveProviderClientConfiguration({
|
|
13278
|
+
providerName,
|
|
13279
|
+
providersConfiguration
|
|
13280
|
+
});
|
|
13281
|
+
if ("error" in resolvedProviderClientConfiguration || !resolvedProviderClientConfiguration.config) {
|
|
13282
|
+
continue;
|
|
13283
|
+
}
|
|
13284
|
+
clientEntries.push(createOAuth2Client(providerName, resolvedProviderClientConfiguration.config.credentials).then((providerInstance) => [providerName, providerInstance]));
|
|
13285
|
+
}
|
|
13286
|
+
const clients = new Map(await Promise.all(clientEntries));
|
|
13287
|
+
return createLinkedProviderCredentialResolver({
|
|
13288
|
+
bindingStore,
|
|
13289
|
+
grantStore,
|
|
13290
|
+
now,
|
|
13291
|
+
loadAccessTokenLease: async (grant) => grant.accessTokenCiphertext ? {
|
|
13292
|
+
accessToken: grant.accessTokenCiphertext,
|
|
13293
|
+
expiresAt: grant.expiresAt,
|
|
13294
|
+
grantedScopes: grant.grantedScopes,
|
|
13295
|
+
tokenType: grant.tokenType
|
|
13296
|
+
} : null,
|
|
13297
|
+
refreshAccessTokenLease: async (grant) => {
|
|
13298
|
+
if (!isValidProviderOption(grant.authProviderKey) || !grant.refreshTokenCiphertext) {
|
|
13299
|
+
return null;
|
|
13300
|
+
}
|
|
13301
|
+
const providerKey = grant.authProviderKey;
|
|
13302
|
+
const providerClientName = typeof grant.metadata?.providerClient === "string" && grant.metadata.providerClient.trim().length > 0 ? grant.metadata.providerClient.trim() : undefined;
|
|
13303
|
+
const resolvedProviderClientConfiguration = resolveProviderClientConfiguration({
|
|
13304
|
+
clientName: providerClientName,
|
|
13305
|
+
providerName: providerKey,
|
|
13306
|
+
providersConfiguration
|
|
13307
|
+
});
|
|
13308
|
+
if ("error" in resolvedProviderClientConfiguration || !resolvedProviderClientConfiguration.config) {
|
|
13309
|
+
return null;
|
|
13310
|
+
}
|
|
13311
|
+
const providerClient = await createOAuth2Client(providerKey, resolvedProviderClientConfiguration.config.credentials);
|
|
13312
|
+
if (!providerClient || !isRefreshableOAuth2Client(providerKey, providerClient)) {
|
|
13313
|
+
return null;
|
|
13314
|
+
}
|
|
13315
|
+
const tokenResponse = await providerClient.refreshAccessToken(grant.refreshTokenCiphertext);
|
|
13316
|
+
const refreshedAt = Date.now();
|
|
13317
|
+
const grantedScopes = getGrantedScopes(Reflect.get(tokenResponse, "scope"), grant.grantedScopes);
|
|
13318
|
+
const tokenType = Reflect.get(tokenResponse, "token_type");
|
|
13319
|
+
const refreshedGrant = {
|
|
13320
|
+
...grant,
|
|
13321
|
+
accessTokenCiphertext: tokenResponse.access_token,
|
|
13322
|
+
expiresAt: getExpiresAt(tokenResponse),
|
|
13323
|
+
grantedScopes,
|
|
13324
|
+
lastRefreshError: undefined,
|
|
13325
|
+
lastRefreshedAt: refreshedAt,
|
|
13326
|
+
refreshTokenCiphertext: tokenResponse.refresh_token ?? grant.refreshTokenCiphertext,
|
|
13327
|
+
status: "active",
|
|
13328
|
+
tokenType: typeof tokenType === "string" ? tokenType : grant.tokenType,
|
|
13329
|
+
updatedAt: refreshedAt
|
|
13330
|
+
};
|
|
13331
|
+
return {
|
|
13332
|
+
grant: refreshedGrant,
|
|
13333
|
+
lease: {
|
|
13334
|
+
accessToken: refreshedGrant.accessTokenCiphertext ?? "",
|
|
13335
|
+
expiresAt: refreshedGrant.expiresAt,
|
|
13336
|
+
grantedScopes: refreshedGrant.grantedScopes,
|
|
13337
|
+
tokenType: refreshedGrant.tokenType
|
|
13338
|
+
}
|
|
13339
|
+
};
|
|
13340
|
+
}
|
|
13341
|
+
});
|
|
13342
|
+
};
|
|
13230
13343
|
// src/neonLinkedProviders.ts
|
|
13231
13344
|
var linkedProviderGrantsTable = pgTable("linked_provider_grants", {
|
|
13232
13345
|
id: varchar("id", { length: 255 }).primaryKey(),
|
|
@@ -13753,6 +13866,7 @@ export {
|
|
|
13753
13866
|
createOAuthLinkedProviderCredentialResolver,
|
|
13754
13867
|
createNeonOAuthLinkedProviderCredentialResolver,
|
|
13755
13868
|
createNeonLinkedProviderStores,
|
|
13869
|
+
createNeonAuthSessionStore,
|
|
13756
13870
|
createLinkedProviderCredentialResolver,
|
|
13757
13871
|
createInMemoryLinkedProviderStores,
|
|
13758
13872
|
createInMemoryAuthSessionStore,
|
|
@@ -13765,5 +13879,5 @@ export {
|
|
|
13765
13879
|
AbsoluteAuthIdentityConflictError
|
|
13766
13880
|
};
|
|
13767
13881
|
|
|
13768
|
-
//# debugId=
|
|
13882
|
+
//# debugId=A6C23409DC7CDF3964756E2164756E21
|
|
13769
13883
|
//# sourceMappingURL=index.js.map
|