@absolutejs/auth 0.27.0 → 0.29.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +112 -2
- package/dist/index.js +647 -40
- package/dist/index.js.map +12 -10
- package/dist/oidc/config.d.ts +91 -2
- package/dist/oidc/inMemoryStores.d.ts +2 -1
- package/dist/oidc/postgresStores.d.ts +199 -1
- package/dist/oidc/routes.d.ts +108 -0
- package/dist/oidc/types.d.ts +20 -0
- package/dist/webhooks/config.d.ts +14 -1
- package/dist/webhooks/dispatcher.d.ts +1 -1
- package/dist/webhooks/inMemoryStore.d.ts +2 -0
- package/dist/webhooks/postgresStore.d.ts +136 -0
- package/dist/webhooks/types.d.ts +14 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4297,6 +4297,160 @@ var mcpProtectedResourceMetadata = ({
|
|
|
4297
4297
|
scopes_supported: scopes ?? []
|
|
4298
4298
|
});
|
|
4299
4299
|
var verifyPkce = async (codeVerifier, codeChallenge) => await hashToken(codeVerifier) === codeChallenge;
|
|
4300
|
+
var inactive = { active: false };
|
|
4301
|
+
var introspectToken = async ({
|
|
4302
|
+
config,
|
|
4303
|
+
hint,
|
|
4304
|
+
now = Date.now(),
|
|
4305
|
+
token
|
|
4306
|
+
}) => {
|
|
4307
|
+
if (hint !== "refresh_token") {
|
|
4308
|
+
const verified = await verifyJwt(token, config.signingKey.publicJwk);
|
|
4309
|
+
const payload = verified?.payload;
|
|
4310
|
+
if (payload !== undefined && typeof payload.sub === "string" && typeof payload.exp === "number" && payload.exp > nowSeconds(now)) {
|
|
4311
|
+
return {
|
|
4312
|
+
active: true,
|
|
4313
|
+
client_id: typeof payload.client_id === "string" ? payload.client_id : "",
|
|
4314
|
+
exp: payload.exp,
|
|
4315
|
+
iat: typeof payload.iat === "number" ? payload.iat : 0,
|
|
4316
|
+
scope: typeof payload.scope === "string" ? payload.scope : "",
|
|
4317
|
+
sub: payload.sub,
|
|
4318
|
+
token_type: "access_token"
|
|
4319
|
+
};
|
|
4320
|
+
}
|
|
4321
|
+
}
|
|
4322
|
+
if (hint !== "access_token") {
|
|
4323
|
+
const refresh = await config.refreshTokenStore.getToken(await hashToken(token));
|
|
4324
|
+
if (refresh && refresh.expiresAt > now) {
|
|
4325
|
+
return {
|
|
4326
|
+
active: true,
|
|
4327
|
+
client_id: refresh.clientId,
|
|
4328
|
+
exp: nowSeconds(refresh.expiresAt),
|
|
4329
|
+
iat: nowSeconds(refresh.createdAt),
|
|
4330
|
+
scope: refresh.scopes.join(" "),
|
|
4331
|
+
sub: refresh.userId,
|
|
4332
|
+
token_type: "refresh_token"
|
|
4333
|
+
};
|
|
4334
|
+
}
|
|
4335
|
+
}
|
|
4336
|
+
return inactive;
|
|
4337
|
+
};
|
|
4338
|
+
var revokeRefreshToken = async (config, token) => {
|
|
4339
|
+
const consumed = await config.refreshTokenStore.consumeToken(await hashToken(token));
|
|
4340
|
+
return consumed !== undefined;
|
|
4341
|
+
};
|
|
4342
|
+
var DEVICE_CODE_BYTES = 32;
|
|
4343
|
+
var USER_CODE_HALF_LENGTH = 4;
|
|
4344
|
+
var USER_CODE_ALPHABET = "BCDFGHJKLMNPQRSTVWXZ23456789";
|
|
4345
|
+
var DEFAULT_DEVICE_CODE_TTL_MINUTES = 15;
|
|
4346
|
+
var DEFAULT_DEVICE_CODE_TTL_MS = MILLISECONDS_IN_A_MINUTE * DEFAULT_DEVICE_CODE_TTL_MINUTES;
|
|
4347
|
+
var DEFAULT_DEVICE_POLL_INTERVAL_SECONDS = 5;
|
|
4348
|
+
var generateUserCode = () => {
|
|
4349
|
+
const length = USER_CODE_HALF_LENGTH * 2;
|
|
4350
|
+
const random = crypto.getRandomValues(new Uint8Array(length));
|
|
4351
|
+
let code = "";
|
|
4352
|
+
for (const byte of random) {
|
|
4353
|
+
code += USER_CODE_ALPHABET[byte % USER_CODE_ALPHABET.length];
|
|
4354
|
+
}
|
|
4355
|
+
return `${code.slice(0, USER_CODE_HALF_LENGTH)}-${code.slice(USER_CODE_HALF_LENGTH)}`;
|
|
4356
|
+
};
|
|
4357
|
+
var issueDeviceAuthorization = async ({
|
|
4358
|
+
clientId,
|
|
4359
|
+
config,
|
|
4360
|
+
now = Date.now(),
|
|
4361
|
+
requestedScopes
|
|
4362
|
+
}) => {
|
|
4363
|
+
if (!config.deviceAuthorizationStore) {
|
|
4364
|
+
throw new Error("oidc.deviceAuthorizationStore is not configured \u2014 cannot start a device flow");
|
|
4365
|
+
}
|
|
4366
|
+
const deviceCode = generateSecureToken(DEVICE_CODE_BYTES);
|
|
4367
|
+
const userCode = generateUserCode();
|
|
4368
|
+
const ttl = config.deviceCodeTtlMs ?? DEFAULT_DEVICE_CODE_TTL_MS;
|
|
4369
|
+
const interval = config.devicePollIntervalSeconds ?? DEFAULT_DEVICE_POLL_INTERVAL_SECONDS;
|
|
4370
|
+
await config.deviceAuthorizationStore.saveDeviceAuthorization({
|
|
4371
|
+
clientId,
|
|
4372
|
+
createdAt: now,
|
|
4373
|
+
deviceCodeHash: await hashToken(deviceCode),
|
|
4374
|
+
expiresAt: now + ttl,
|
|
4375
|
+
intervalSeconds: interval,
|
|
4376
|
+
scopes: requestedScopes,
|
|
4377
|
+
status: "pending",
|
|
4378
|
+
userCode
|
|
4379
|
+
});
|
|
4380
|
+
const verificationUri = `${config.issuer}${config.oidcRoute ?? DEFAULT_OIDC_ROUTE}/device`;
|
|
4381
|
+
return {
|
|
4382
|
+
device_code: deviceCode,
|
|
4383
|
+
expires_in: Math.floor(ttl / MS_PER_SECOND),
|
|
4384
|
+
interval,
|
|
4385
|
+
user_code: userCode,
|
|
4386
|
+
verification_uri: verificationUri,
|
|
4387
|
+
verification_uri_complete: `${verificationUri}?user_code=${encodeURIComponent(userCode)}`
|
|
4388
|
+
};
|
|
4389
|
+
};
|
|
4390
|
+
var decideDeviceAuthorization = async (config, userCode, approval) => {
|
|
4391
|
+
if (!config.deviceAuthorizationStore) {
|
|
4392
|
+
return { error: "not_configured", ok: false };
|
|
4393
|
+
}
|
|
4394
|
+
const record = await config.deviceAuthorizationStore.findByUserCode(userCode);
|
|
4395
|
+
if (!record)
|
|
4396
|
+
return { error: "invalid_user_code", ok: false };
|
|
4397
|
+
if (record.expiresAt < Date.now()) {
|
|
4398
|
+
return { error: "expired_token", ok: false };
|
|
4399
|
+
}
|
|
4400
|
+
if (record.status !== "pending") {
|
|
4401
|
+
return { error: "already_decided", ok: false };
|
|
4402
|
+
}
|
|
4403
|
+
await config.deviceAuthorizationStore.updateStatus(record.deviceCodeHash, approval.status, approval.userSub);
|
|
4404
|
+
return { ok: true };
|
|
4405
|
+
};
|
|
4406
|
+
var approveDeviceAuthorization = async ({
|
|
4407
|
+
config,
|
|
4408
|
+
userCode,
|
|
4409
|
+
userSub
|
|
4410
|
+
}) => decideDeviceAuthorization(config, userCode, {
|
|
4411
|
+
status: "approved",
|
|
4412
|
+
userSub
|
|
4413
|
+
});
|
|
4414
|
+
var denyDeviceAuthorization = async ({
|
|
4415
|
+
config,
|
|
4416
|
+
userCode
|
|
4417
|
+
}) => decideDeviceAuthorization(config, userCode, { status: "denied" });
|
|
4418
|
+
var exchangeDeviceCode = async ({
|
|
4419
|
+
clientId,
|
|
4420
|
+
config,
|
|
4421
|
+
deviceCode,
|
|
4422
|
+
dpopJkt,
|
|
4423
|
+
now = Date.now()
|
|
4424
|
+
}) => {
|
|
4425
|
+
if (!config.deviceAuthorizationStore) {
|
|
4426
|
+
return { error: "invalid_grant", ok: false };
|
|
4427
|
+
}
|
|
4428
|
+
const deviceCodeHash = await hashToken(deviceCode);
|
|
4429
|
+
const record = await config.deviceAuthorizationStore.findByDeviceCodeHash(deviceCodeHash);
|
|
4430
|
+
if (!record || record.clientId !== clientId) {
|
|
4431
|
+
return { error: "invalid_grant", ok: false };
|
|
4432
|
+
}
|
|
4433
|
+
if (record.expiresAt < now) {
|
|
4434
|
+
await config.deviceAuthorizationStore.deleteByDeviceCodeHash(deviceCodeHash);
|
|
4435
|
+
return { error: "expired_token", ok: false };
|
|
4436
|
+
}
|
|
4437
|
+
if (record.status === "pending") {
|
|
4438
|
+
return { error: "authorization_pending", ok: false };
|
|
4439
|
+
}
|
|
4440
|
+
if (record.status === "denied" || record.userSub === undefined) {
|
|
4441
|
+
return { error: "access_denied", ok: false };
|
|
4442
|
+
}
|
|
4443
|
+
await config.deviceAuthorizationStore.deleteByDeviceCodeHash(deviceCodeHash);
|
|
4444
|
+
const tokenSet = await issueTokenSet({
|
|
4445
|
+
clientId,
|
|
4446
|
+
config,
|
|
4447
|
+
dpopJkt,
|
|
4448
|
+
now,
|
|
4449
|
+
scopes: record.scopes,
|
|
4450
|
+
sub: record.userSub
|
|
4451
|
+
});
|
|
4452
|
+
return { ...tokenSet, ok: true };
|
|
4453
|
+
};
|
|
4300
4454
|
|
|
4301
4455
|
// src/oidc/dpop.ts
|
|
4302
4456
|
var DEFAULT_MAX_AGE_MS = 60000;
|
|
@@ -4391,6 +4545,10 @@ var oidcProviderRoutes = (config) => {
|
|
|
4391
4545
|
const authorizeRoute = `${oidcRoute}/authorize`;
|
|
4392
4546
|
const tokenRoute = `${oidcRoute}/token`;
|
|
4393
4547
|
const jwksRoute = `${oidcRoute}/jwks`;
|
|
4548
|
+
const introspectRoute = `${oidcRoute}/introspect`;
|
|
4549
|
+
const revokeRoute = `${oidcRoute}/revoke`;
|
|
4550
|
+
const deviceAuthorizationRoute = `${oidcRoute}/device_authorization`;
|
|
4551
|
+
const deviceApproveRoute = `${oidcRoute}/device/decision`;
|
|
4394
4552
|
const tokenUrl = `${issuer}${oidcRoute}/token`;
|
|
4395
4553
|
const authenticateClient = async (clientId, clientSecret) => {
|
|
4396
4554
|
const client = await clientStore.findClient(clientId);
|
|
@@ -4492,19 +4650,57 @@ var oidcProviderRoutes = (config) => {
|
|
|
4492
4650
|
token_type: dpopResult === undefined ? "Bearer" : "DPoP"
|
|
4493
4651
|
}, HTTP_OK2);
|
|
4494
4652
|
};
|
|
4653
|
+
const grantDeviceCode = async (client, body, dpop) => {
|
|
4654
|
+
if (config.deviceAuthorizationStore === undefined) {
|
|
4655
|
+
return oauthError2(HTTP_BAD_REQUEST2, "unsupported_grant_type");
|
|
4656
|
+
}
|
|
4657
|
+
if (body.device_code === undefined) {
|
|
4658
|
+
return oauthError2(HTTP_BAD_REQUEST2, "invalid_request");
|
|
4659
|
+
}
|
|
4660
|
+
const dpopResult = dpop === undefined ? undefined : await verifyDpopProof({
|
|
4661
|
+
htm: "POST",
|
|
4662
|
+
htu: tokenUrl,
|
|
4663
|
+
proof: dpop
|
|
4664
|
+
});
|
|
4665
|
+
if (dpop !== undefined && dpopResult === undefined) {
|
|
4666
|
+
return oauthError2(HTTP_BAD_REQUEST2, "invalid_dpop_proof");
|
|
4667
|
+
}
|
|
4668
|
+
const result = await exchangeDeviceCode({
|
|
4669
|
+
clientId: client.clientId,
|
|
4670
|
+
config,
|
|
4671
|
+
deviceCode: body.device_code,
|
|
4672
|
+
dpopJkt: dpopResult?.jkt
|
|
4673
|
+
});
|
|
4674
|
+
if (!result.ok)
|
|
4675
|
+
return oauthError2(HTTP_BAD_REQUEST2, result.error);
|
|
4676
|
+
return jsonResponse({
|
|
4677
|
+
access_token: result.access_token,
|
|
4678
|
+
expires_in: result.expires_in,
|
|
4679
|
+
id_token: result.id_token,
|
|
4680
|
+
refresh_token: result.refresh_token,
|
|
4681
|
+
scope: result.scope,
|
|
4682
|
+
token_type: dpopResult === undefined ? "Bearer" : "DPoP"
|
|
4683
|
+
}, HTTP_OK2);
|
|
4684
|
+
};
|
|
4685
|
+
const grantTypes = [
|
|
4686
|
+
"authorization_code",
|
|
4687
|
+
"refresh_token",
|
|
4688
|
+
"urn:ietf:params:oauth:grant-type:token-exchange"
|
|
4689
|
+
];
|
|
4690
|
+
if (config.deviceAuthorizationStore) {
|
|
4691
|
+
grantTypes.push("urn:ietf:params:oauth:grant-type:device_code");
|
|
4692
|
+
}
|
|
4495
4693
|
const discovery = {
|
|
4496
4694
|
authorization_endpoint: `${issuer}${authorizeRoute}`,
|
|
4497
4695
|
code_challenge_methods_supported: ["S256"],
|
|
4498
4696
|
dpop_signing_alg_values_supported: ["ES256"],
|
|
4499
|
-
grant_types_supported:
|
|
4500
|
-
"authorization_code",
|
|
4501
|
-
"refresh_token",
|
|
4502
|
-
"urn:ietf:params:oauth:grant-type:token-exchange"
|
|
4503
|
-
],
|
|
4697
|
+
grant_types_supported: grantTypes,
|
|
4504
4698
|
id_token_signing_alg_values_supported: ["ES256"],
|
|
4699
|
+
introspection_endpoint: `${issuer}${introspectRoute}`,
|
|
4505
4700
|
issuer,
|
|
4506
4701
|
jwks_uri: `${issuer}${jwksRoute}`,
|
|
4507
4702
|
response_types_supported: ["code"],
|
|
4703
|
+
revocation_endpoint: `${issuer}${revokeRoute}`,
|
|
4508
4704
|
subject_types_supported: ["public"],
|
|
4509
4705
|
token_endpoint: tokenUrl,
|
|
4510
4706
|
token_endpoint_auth_methods_supported: [
|
|
@@ -4513,6 +4709,9 @@ var oidcProviderRoutes = (config) => {
|
|
|
4513
4709
|
"none"
|
|
4514
4710
|
]
|
|
4515
4711
|
};
|
|
4712
|
+
if (config.deviceAuthorizationStore) {
|
|
4713
|
+
discovery.device_authorization_endpoint = `${issuer}${deviceAuthorizationRoute}`;
|
|
4714
|
+
}
|
|
4516
4715
|
return new Elysia15().use(sessionStore()).get(authorizeRoute, async ({ cookie: { user_session_id }, query, request, store }) => {
|
|
4517
4716
|
const {
|
|
4518
4717
|
client_id: clientId,
|
|
@@ -4610,6 +4809,9 @@ var oidcProviderRoutes = (config) => {
|
|
|
4610
4809
|
if (body.grant_type === "urn:ietf:params:oauth:grant-type:token-exchange") {
|
|
4611
4810
|
return grantTokenExchange(client, body, headers.dpop);
|
|
4612
4811
|
}
|
|
4812
|
+
if (body.grant_type === "urn:ietf:params:oauth:grant-type:device_code") {
|
|
4813
|
+
return grantDeviceCode(client, body, headers.dpop);
|
|
4814
|
+
}
|
|
4613
4815
|
return oauthError2(HTTP_BAD_REQUEST2, "unsupported_grant_type");
|
|
4614
4816
|
}, {
|
|
4615
4817
|
body: t12.Object({
|
|
@@ -4618,6 +4820,7 @@ var oidcProviderRoutes = (config) => {
|
|
|
4618
4820
|
client_secret: t12.Optional(t12.String()),
|
|
4619
4821
|
code: t12.Optional(t12.String()),
|
|
4620
4822
|
code_verifier: t12.Optional(t12.String()),
|
|
4823
|
+
device_code: t12.Optional(t12.String()),
|
|
4621
4824
|
grant_type: t12.Optional(t12.String()),
|
|
4622
4825
|
redirect_uri: t12.Optional(t12.String()),
|
|
4623
4826
|
refresh_token: t12.Optional(t12.String()),
|
|
@@ -4626,6 +4829,121 @@ var oidcProviderRoutes = (config) => {
|
|
|
4626
4829
|
subject_token: t12.Optional(t12.String()),
|
|
4627
4830
|
subject_token_type: t12.Optional(t12.String())
|
|
4628
4831
|
})
|
|
4832
|
+
}).post(introspectRoute, async ({ body, headers }) => {
|
|
4833
|
+
const basic = readBasicAuth2(headers.authorization);
|
|
4834
|
+
const clientId = body.client_id ?? basic.clientId;
|
|
4835
|
+
const clientSecret = body.client_secret ?? basic.clientSecret;
|
|
4836
|
+
if (clientId === undefined) {
|
|
4837
|
+
return oauthError2(HTTP_UNAUTHORIZED2, "invalid_client");
|
|
4838
|
+
}
|
|
4839
|
+
const client = await authenticateClient(clientId, clientSecret);
|
|
4840
|
+
if (client === undefined) {
|
|
4841
|
+
return oauthError2(HTTP_UNAUTHORIZED2, "invalid_client");
|
|
4842
|
+
}
|
|
4843
|
+
const result = await introspectToken({
|
|
4844
|
+
config,
|
|
4845
|
+
hint: body.token_type_hint === "access_token" || body.token_type_hint === "refresh_token" ? body.token_type_hint : undefined,
|
|
4846
|
+
now: Date.now(),
|
|
4847
|
+
token: body.token
|
|
4848
|
+
});
|
|
4849
|
+
return jsonResponse(result, HTTP_OK2);
|
|
4850
|
+
}, {
|
|
4851
|
+
body: t12.Object({
|
|
4852
|
+
client_id: t12.Optional(t12.String()),
|
|
4853
|
+
client_secret: t12.Optional(t12.String()),
|
|
4854
|
+
token: t12.String(),
|
|
4855
|
+
token_type_hint: t12.Optional(t12.String())
|
|
4856
|
+
}),
|
|
4857
|
+
headers: t12.Object({
|
|
4858
|
+
authorization: t12.Optional(t12.String())
|
|
4859
|
+
})
|
|
4860
|
+
}).post(revokeRoute, async ({ body, headers }) => {
|
|
4861
|
+
const basic = readBasicAuth2(headers.authorization);
|
|
4862
|
+
const clientId = body.client_id ?? basic.clientId;
|
|
4863
|
+
const clientSecret = body.client_secret ?? basic.clientSecret;
|
|
4864
|
+
if (clientId === undefined) {
|
|
4865
|
+
return oauthError2(HTTP_UNAUTHORIZED2, "invalid_client");
|
|
4866
|
+
}
|
|
4867
|
+
const client = await authenticateClient(clientId, clientSecret);
|
|
4868
|
+
if (client === undefined) {
|
|
4869
|
+
return oauthError2(HTTP_UNAUTHORIZED2, "invalid_client");
|
|
4870
|
+
}
|
|
4871
|
+
if (body.token_type_hint !== "access_token") {
|
|
4872
|
+
await revokeRefreshToken(config, body.token);
|
|
4873
|
+
}
|
|
4874
|
+
return new Response(null, { status: HTTP_OK2 });
|
|
4875
|
+
}, {
|
|
4876
|
+
body: t12.Object({
|
|
4877
|
+
client_id: t12.Optional(t12.String()),
|
|
4878
|
+
client_secret: t12.Optional(t12.String()),
|
|
4879
|
+
token: t12.String(),
|
|
4880
|
+
token_type_hint: t12.Optional(t12.String())
|
|
4881
|
+
}),
|
|
4882
|
+
headers: t12.Object({
|
|
4883
|
+
authorization: t12.Optional(t12.String())
|
|
4884
|
+
})
|
|
4885
|
+
}).post(deviceAuthorizationRoute, async ({ body, headers }) => {
|
|
4886
|
+
if (config.deviceAuthorizationStore === undefined) {
|
|
4887
|
+
return oauthError2(HTTP_BAD_REQUEST2, "unsupported_grant_type");
|
|
4888
|
+
}
|
|
4889
|
+
const basic = readBasicAuth2(headers.authorization);
|
|
4890
|
+
const clientId = body.client_id ?? basic.clientId;
|
|
4891
|
+
const clientSecret = body.client_secret ?? basic.clientSecret;
|
|
4892
|
+
if (clientId === undefined) {
|
|
4893
|
+
return oauthError2(HTTP_UNAUTHORIZED2, "invalid_client");
|
|
4894
|
+
}
|
|
4895
|
+
const client = await authenticateClient(clientId, clientSecret);
|
|
4896
|
+
if (client === undefined) {
|
|
4897
|
+
return oauthError2(HTTP_UNAUTHORIZED2, "invalid_client");
|
|
4898
|
+
}
|
|
4899
|
+
const requested = body.scope === undefined || body.scope.length === 0 ? client.scopes : body.scope.split(" ").filter((entry) => client.scopes.includes(entry));
|
|
4900
|
+
const response = await issueDeviceAuthorization({
|
|
4901
|
+
clientId: client.clientId,
|
|
4902
|
+
config,
|
|
4903
|
+
now: Date.now(),
|
|
4904
|
+
requestedScopes: requested
|
|
4905
|
+
});
|
|
4906
|
+
return jsonResponse(response, HTTP_OK2);
|
|
4907
|
+
}, {
|
|
4908
|
+
body: t12.Object({
|
|
4909
|
+
client_id: t12.Optional(t12.String()),
|
|
4910
|
+
client_secret: t12.Optional(t12.String()),
|
|
4911
|
+
scope: t12.Optional(t12.String())
|
|
4912
|
+
}),
|
|
4913
|
+
headers: t12.Object({
|
|
4914
|
+
authorization: t12.Optional(t12.String())
|
|
4915
|
+
})
|
|
4916
|
+
}).post(deviceApproveRoute, async ({ body, cookie: { user_session_id }, store }) => {
|
|
4917
|
+
if (config.deviceAuthorizationStore === undefined) {
|
|
4918
|
+
return oauthError2(HTTP_BAD_REQUEST2, "unsupported_grant_type");
|
|
4919
|
+
}
|
|
4920
|
+
const userSession = await loadSessionFromSource({
|
|
4921
|
+
authSessionStore,
|
|
4922
|
+
session: store.session,
|
|
4923
|
+
userSessionId: user_session_id.value
|
|
4924
|
+
});
|
|
4925
|
+
if (userSession === undefined) {
|
|
4926
|
+
return oauthError2(HTTP_UNAUTHORIZED2, "login_required");
|
|
4927
|
+
}
|
|
4928
|
+
const result = body.action === "deny" ? await denyDeviceAuthorization({
|
|
4929
|
+
config,
|
|
4930
|
+
userCode: body.user_code
|
|
4931
|
+
}) : await approveDeviceAuthorization({
|
|
4932
|
+
config,
|
|
4933
|
+
userCode: body.user_code,
|
|
4934
|
+
userSub: getUserId(userSession.user)
|
|
4935
|
+
});
|
|
4936
|
+
if (!result.ok)
|
|
4937
|
+
return oauthError2(HTTP_BAD_REQUEST2, result.error);
|
|
4938
|
+
return jsonResponse({ ok: true }, HTTP_OK2);
|
|
4939
|
+
}, {
|
|
4940
|
+
body: t12.Object({
|
|
4941
|
+
action: t12.Optional(t12.Union([t12.Literal("approve"), t12.Literal("deny")])),
|
|
4942
|
+
user_code: t12.String()
|
|
4943
|
+
}),
|
|
4944
|
+
cookie: t12.Cookie({
|
|
4945
|
+
user_session_id: t12.Optional(userSessionIdTypebox)
|
|
4946
|
+
})
|
|
4629
4947
|
}).get(jwksRoute, () => ({ keys: [toPublicJwk(signingKey)] })).get("/.well-known/openid-configuration", () => discovery);
|
|
4630
4948
|
};
|
|
4631
4949
|
|
|
@@ -7602,6 +7920,14 @@ var webauthnRoutes = ({
|
|
|
7602
7920
|
|
|
7603
7921
|
// src/webhooks/config.ts
|
|
7604
7922
|
var DEFAULT_TIMEOUT_SECONDS = 5;
|
|
7923
|
+
var DEFAULT_RETRY_ATTEMPTS = 3;
|
|
7924
|
+
var DEFAULT_RETRY_INITIAL_DELAY_MS = MILLISECONDS_IN_A_SECOND;
|
|
7925
|
+
var DEFAULT_RETRY_BACKOFF_MULTIPLIER = 2;
|
|
7926
|
+
var DEFAULT_WEBHOOK_RETRY = {
|
|
7927
|
+
attempts: DEFAULT_RETRY_ATTEMPTS,
|
|
7928
|
+
backoffMultiplier: DEFAULT_RETRY_BACKOFF_MULTIPLIER,
|
|
7929
|
+
initialDelayMs: DEFAULT_RETRY_INITIAL_DELAY_MS
|
|
7930
|
+
};
|
|
7605
7931
|
var DEFAULT_WEBHOOK_TIMEOUT_MS = MILLISECONDS_IN_A_SECOND * DEFAULT_TIMEOUT_SECONDS;
|
|
7606
7932
|
|
|
7607
7933
|
// src/webhooks/sign.ts
|
|
@@ -7634,12 +7960,145 @@ var verifyWebhookSignature = async ({
|
|
|
7634
7960
|
};
|
|
7635
7961
|
|
|
7636
7962
|
// src/webhooks/dispatcher.ts
|
|
7963
|
+
var defaultSleep = (delayMs) => new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
7964
|
+
var attemptOnce = async ({
|
|
7965
|
+
envelope,
|
|
7966
|
+
endpoint,
|
|
7967
|
+
fetchImpl,
|
|
7968
|
+
payload,
|
|
7969
|
+
signature,
|
|
7970
|
+
timeoutMs,
|
|
7971
|
+
timestamp
|
|
7972
|
+
}) => {
|
|
7973
|
+
const response = await fetchImpl(endpoint.url, {
|
|
7974
|
+
body: payload,
|
|
7975
|
+
headers: {
|
|
7976
|
+
"content-type": "application/json",
|
|
7977
|
+
"webhook-id": envelope.id,
|
|
7978
|
+
"webhook-signature": signature,
|
|
7979
|
+
"webhook-timestamp": timestamp
|
|
7980
|
+
},
|
|
7981
|
+
method: "POST",
|
|
7982
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
7983
|
+
});
|
|
7984
|
+
if (!response.ok) {
|
|
7985
|
+
throw new Error(`Webhook delivery returned ${response.status}`);
|
|
7986
|
+
}
|
|
7987
|
+
return response.status;
|
|
7988
|
+
};
|
|
7989
|
+
var errorMessage = (error) => error instanceof Error ? error.message : String(error);
|
|
7990
|
+
var statusFromError = (error) => {
|
|
7991
|
+
if (!(error instanceof Error))
|
|
7992
|
+
return;
|
|
7993
|
+
const match = /returned (\d+)/.exec(error.message);
|
|
7994
|
+
return match?.[1] === undefined ? undefined : Number(match[1]);
|
|
7995
|
+
};
|
|
7996
|
+
var persistFailure = async ({
|
|
7997
|
+
attempts,
|
|
7998
|
+
deliveryStore,
|
|
7999
|
+
endpoint,
|
|
8000
|
+
envelope,
|
|
8001
|
+
lastError
|
|
8002
|
+
}) => {
|
|
8003
|
+
if (deliveryStore === undefined)
|
|
8004
|
+
return;
|
|
8005
|
+
const record = {
|
|
8006
|
+
attempts,
|
|
8007
|
+
createdAt: Date.now(),
|
|
8008
|
+
endpointUrl: endpoint.url,
|
|
8009
|
+
envelope,
|
|
8010
|
+
lastError: errorMessage(lastError),
|
|
8011
|
+
lastStatus: statusFromError(lastError)
|
|
8012
|
+
};
|
|
8013
|
+
await deliveryStore.recordFailure(record);
|
|
8014
|
+
};
|
|
8015
|
+
var tryDeliverThenBackoff = async ({
|
|
8016
|
+
attempt,
|
|
8017
|
+
endpoint,
|
|
8018
|
+
envelope,
|
|
8019
|
+
fetchImpl,
|
|
8020
|
+
payload,
|
|
8021
|
+
retry,
|
|
8022
|
+
signature,
|
|
8023
|
+
sleep,
|
|
8024
|
+
timeoutMs,
|
|
8025
|
+
timestamp
|
|
8026
|
+
}) => {
|
|
8027
|
+
try {
|
|
8028
|
+
await attemptOnce({
|
|
8029
|
+
endpoint,
|
|
8030
|
+
envelope,
|
|
8031
|
+
fetchImpl,
|
|
8032
|
+
payload,
|
|
8033
|
+
signature,
|
|
8034
|
+
timeoutMs,
|
|
8035
|
+
timestamp
|
|
8036
|
+
});
|
|
8037
|
+
return;
|
|
8038
|
+
} catch (error) {
|
|
8039
|
+
const isLastAttempt = attempt >= retry.attempts - 1;
|
|
8040
|
+
await (isLastAttempt ? Promise.resolve() : sleep(retry.initialDelayMs * retry.backoffMultiplier ** attempt));
|
|
8041
|
+
return error;
|
|
8042
|
+
}
|
|
8043
|
+
};
|
|
8044
|
+
var deliverToEndpoint = async ({
|
|
8045
|
+
deliveryStore,
|
|
8046
|
+
endpoint,
|
|
8047
|
+
envelope,
|
|
8048
|
+
fetchImpl,
|
|
8049
|
+
onDeliveryError,
|
|
8050
|
+
payload,
|
|
8051
|
+
retry,
|
|
8052
|
+
signature,
|
|
8053
|
+
sleep,
|
|
8054
|
+
timeoutMs,
|
|
8055
|
+
timestamp
|
|
8056
|
+
}) => {
|
|
8057
|
+
let lastError;
|
|
8058
|
+
for (let attempt = 0;attempt < retry.attempts; attempt++) {
|
|
8059
|
+
const error = await tryDeliverThenBackoff({
|
|
8060
|
+
attempt,
|
|
8061
|
+
endpoint,
|
|
8062
|
+
envelope,
|
|
8063
|
+
fetchImpl,
|
|
8064
|
+
payload,
|
|
8065
|
+
retry,
|
|
8066
|
+
signature,
|
|
8067
|
+
sleep,
|
|
8068
|
+
timeoutMs,
|
|
8069
|
+
timestamp
|
|
8070
|
+
});
|
|
8071
|
+
if (error === undefined)
|
|
8072
|
+
return;
|
|
8073
|
+
lastError = error;
|
|
8074
|
+
}
|
|
8075
|
+
await onDeliveryError?.({
|
|
8076
|
+
endpoint,
|
|
8077
|
+
error: lastError,
|
|
8078
|
+
event: envelope
|
|
8079
|
+
});
|
|
8080
|
+
await persistFailure({
|
|
8081
|
+
attempts: retry.attempts,
|
|
8082
|
+
deliveryStore,
|
|
8083
|
+
endpoint,
|
|
8084
|
+
envelope,
|
|
8085
|
+
lastError
|
|
8086
|
+
});
|
|
8087
|
+
};
|
|
7637
8088
|
var createWebhookDispatcher = ({
|
|
8089
|
+
deliveryStore,
|
|
7638
8090
|
endpoints,
|
|
7639
8091
|
fetch: fetchImpl = globalThis.fetch,
|
|
7640
8092
|
onDeliveryError,
|
|
8093
|
+
retry,
|
|
8094
|
+
sleep = defaultSleep,
|
|
7641
8095
|
timeoutMs = DEFAULT_WEBHOOK_TIMEOUT_MS
|
|
7642
8096
|
}) => {
|
|
8097
|
+
const effectiveRetry = {
|
|
8098
|
+
attempts: retry?.attempts ?? DEFAULT_WEBHOOK_RETRY.attempts,
|
|
8099
|
+
backoffMultiplier: retry?.backoffMultiplier ?? DEFAULT_WEBHOOK_RETRY.backoffMultiplier,
|
|
8100
|
+
initialDelayMs: retry?.initialDelayMs ?? DEFAULT_WEBHOOK_RETRY.initialDelayMs
|
|
8101
|
+
};
|
|
7643
8102
|
const dispatch = async (event) => {
|
|
7644
8103
|
const envelope = {
|
|
7645
8104
|
createdAt: Date.now(),
|
|
@@ -7649,35 +8108,26 @@ var createWebhookDispatcher = ({
|
|
|
7649
8108
|
};
|
|
7650
8109
|
const payload = JSON.stringify(envelope);
|
|
7651
8110
|
const timestamp = Math.floor(Date.now() / MILLISECONDS_IN_A_SECOND).toString();
|
|
7652
|
-
await Promise.all(endpoints.map(async (endpoint) => {
|
|
7653
|
-
|
|
7654
|
-
|
|
7655
|
-
|
|
7656
|
-
|
|
7657
|
-
|
|
7658
|
-
|
|
7659
|
-
|
|
7660
|
-
|
|
7661
|
-
|
|
7662
|
-
|
|
7663
|
-
|
|
7664
|
-
|
|
7665
|
-
|
|
7666
|
-
|
|
7667
|
-
|
|
7668
|
-
|
|
7669
|
-
|
|
7670
|
-
|
|
7671
|
-
|
|
7672
|
-
throw new Error(`Webhook delivery returned ${response.status}`);
|
|
7673
|
-
}
|
|
7674
|
-
} catch (error) {
|
|
7675
|
-
await onDeliveryError?.({
|
|
7676
|
-
endpoint,
|
|
7677
|
-
error,
|
|
7678
|
-
event: envelope
|
|
7679
|
-
});
|
|
7680
|
-
}
|
|
8111
|
+
await Promise.all(endpoints.filter((endpoint) => endpoint.events === undefined || endpoint.events.includes(event.type)).map(async (endpoint) => {
|
|
8112
|
+
const signature = await signWebhook({
|
|
8113
|
+
id: envelope.id,
|
|
8114
|
+
payload,
|
|
8115
|
+
secret: endpoint.secret,
|
|
8116
|
+
timestamp
|
|
8117
|
+
});
|
|
8118
|
+
await deliverToEndpoint({
|
|
8119
|
+
deliveryStore,
|
|
8120
|
+
endpoint,
|
|
8121
|
+
envelope,
|
|
8122
|
+
fetchImpl,
|
|
8123
|
+
onDeliveryError,
|
|
8124
|
+
payload,
|
|
8125
|
+
retry: effectiveRetry,
|
|
8126
|
+
signature,
|
|
8127
|
+
sleep,
|
|
8128
|
+
timeoutMs,
|
|
8129
|
+
timestamp
|
|
8130
|
+
});
|
|
7681
8131
|
}));
|
|
7682
8132
|
};
|
|
7683
8133
|
return dispatch;
|
|
@@ -19646,6 +20096,33 @@ var createInMemoryAuthorizationCodeStore = () => {
|
|
|
19646
20096
|
}
|
|
19647
20097
|
};
|
|
19648
20098
|
};
|
|
20099
|
+
var createInMemoryDeviceAuthorizationStore = () => {
|
|
20100
|
+
const byDeviceCode = new Map;
|
|
20101
|
+
return {
|
|
20102
|
+
deleteByDeviceCodeHash: async (deviceCodeHash) => {
|
|
20103
|
+
byDeviceCode.delete(deviceCodeHash);
|
|
20104
|
+
},
|
|
20105
|
+
findByDeviceCodeHash: async (deviceCodeHash) => byDeviceCode.get(deviceCodeHash),
|
|
20106
|
+
findByUserCode: async (userCode) => {
|
|
20107
|
+
for (const record of byDeviceCode.values()) {
|
|
20108
|
+
if (record.userCode === userCode)
|
|
20109
|
+
return record;
|
|
20110
|
+
}
|
|
20111
|
+
return;
|
|
20112
|
+
},
|
|
20113
|
+
saveDeviceAuthorization: async (deviceAuthorization) => {
|
|
20114
|
+
byDeviceCode.set(deviceAuthorization.deviceCodeHash, {
|
|
20115
|
+
...deviceAuthorization
|
|
20116
|
+
});
|
|
20117
|
+
},
|
|
20118
|
+
updateStatus: async (deviceCodeHash, status, userSub) => {
|
|
20119
|
+
const record = byDeviceCode.get(deviceCodeHash);
|
|
20120
|
+
if (!record)
|
|
20121
|
+
return;
|
|
20122
|
+
byDeviceCode.set(deviceCodeHash, { ...record, status, userSub });
|
|
20123
|
+
}
|
|
20124
|
+
};
|
|
20125
|
+
};
|
|
19649
20126
|
var createInMemoryOAuthClientStore = (clients) => {
|
|
19650
20127
|
const registry = new Map(clients.map((client) => [client.clientId, client]));
|
|
19651
20128
|
return {
|
|
@@ -19666,6 +20143,7 @@ var createInMemoryOidcRefreshTokenStore = () => {
|
|
|
19666
20143
|
tokens.delete(hash);
|
|
19667
20144
|
}
|
|
19668
20145
|
},
|
|
20146
|
+
getToken: async (tokenHash) => tokens.get(tokenHash),
|
|
19669
20147
|
saveToken: async (token) => {
|
|
19670
20148
|
tokens.set(token.tokenHash, { ...token });
|
|
19671
20149
|
}
|
|
@@ -19693,6 +20171,19 @@ var oauthCodesTable = pgTable("auth_oauth_codes", {
|
|
|
19693
20171
|
scopes: text("scopes").array().notNull(),
|
|
19694
20172
|
user_id: varchar("user_id", { length: ID_LENGTH7 }).notNull()
|
|
19695
20173
|
});
|
|
20174
|
+
var oauthDeviceAuthorizationsTable = pgTable("auth_oauth_device_authorizations", {
|
|
20175
|
+
client_id: varchar("client_id", { length: ID_LENGTH7 }).notNull(),
|
|
20176
|
+
created_at_ms: bigint("created_at_ms", { mode: "number" }).notNull(),
|
|
20177
|
+
device_code_hash: varchar("device_code_hash", {
|
|
20178
|
+
length: ID_LENGTH7
|
|
20179
|
+
}).primaryKey(),
|
|
20180
|
+
expires_at_ms: bigint("expires_at_ms", { mode: "number" }).notNull(),
|
|
20181
|
+
interval_seconds: bigint("interval_seconds", { mode: "number" }).notNull(),
|
|
20182
|
+
scopes: text("scopes").array().notNull(),
|
|
20183
|
+
status: varchar("status", { length: 16 }).notNull(),
|
|
20184
|
+
user_code: varchar("user_code", { length: 16 }).notNull().unique(),
|
|
20185
|
+
user_sub: varchar("user_sub", { length: ID_LENGTH7 })
|
|
20186
|
+
});
|
|
19696
20187
|
var oauthRefreshTokensTable = pgTable("auth_oauth_refresh_tokens", {
|
|
19697
20188
|
claims_json: jsonb("claims_json").$type(),
|
|
19698
20189
|
client_id: varchar("client_id", { length: ID_LENGTH7 }).notNull(),
|
|
@@ -19736,6 +20227,17 @@ var toCodeValues = (code) => ({
|
|
|
19736
20227
|
scopes: code.scopes,
|
|
19737
20228
|
user_id: code.userId
|
|
19738
20229
|
});
|
|
20230
|
+
var toDeviceAuth = (row) => ({
|
|
20231
|
+
clientId: row.client_id,
|
|
20232
|
+
createdAt: row.created_at_ms,
|
|
20233
|
+
deviceCodeHash: row.device_code_hash,
|
|
20234
|
+
expiresAt: row.expires_at_ms,
|
|
20235
|
+
intervalSeconds: row.interval_seconds,
|
|
20236
|
+
scopes: row.scopes,
|
|
20237
|
+
status: row.status,
|
|
20238
|
+
userCode: row.user_code,
|
|
20239
|
+
userSub: row.user_sub ?? undefined
|
|
20240
|
+
});
|
|
19739
20241
|
var toRefresh = (row) => ({
|
|
19740
20242
|
claims: row.claims_json ?? undefined,
|
|
19741
20243
|
clientId: row.client_id,
|
|
@@ -19757,6 +20259,7 @@ var toRefreshValues = (token) => ({
|
|
|
19757
20259
|
user_id: token.userId
|
|
19758
20260
|
});
|
|
19759
20261
|
var createNeonAuthorizationCodeStore = (databaseUrl) => createPostgresAuthorizationCodeStore(createNeonDatabase(databaseUrl));
|
|
20262
|
+
var createNeonDeviceAuthorizationStore = (databaseUrl) => createPostgresDeviceAuthorizationStore(createNeonDatabase(databaseUrl));
|
|
19760
20263
|
var createNeonOAuthClientStore = (databaseUrl) => createPostgresOAuthClientStore(createNeonDatabase(databaseUrl));
|
|
19761
20264
|
var createNeonOidcRefreshTokenStore = (databaseUrl) => createPostgresOidcRefreshTokenStore(createNeonDatabase(databaseUrl));
|
|
19762
20265
|
var createPostgresAuthorizationCodeStore = (db) => ({
|
|
@@ -19768,6 +20271,35 @@ var createPostgresAuthorizationCodeStore = (db) => ({
|
|
|
19768
20271
|
await db.insert(oauthCodesTable).values(toCodeValues(code));
|
|
19769
20272
|
}
|
|
19770
20273
|
});
|
|
20274
|
+
var createPostgresDeviceAuthorizationStore = (db) => ({
|
|
20275
|
+
deleteByDeviceCodeHash: async (deviceCodeHash) => {
|
|
20276
|
+
await db.delete(oauthDeviceAuthorizationsTable).where(eq(oauthDeviceAuthorizationsTable.device_code_hash, deviceCodeHash));
|
|
20277
|
+
},
|
|
20278
|
+
findByDeviceCodeHash: async (deviceCodeHash) => {
|
|
20279
|
+
const [row] = await db.select().from(oauthDeviceAuthorizationsTable).where(eq(oauthDeviceAuthorizationsTable.device_code_hash, deviceCodeHash)).limit(1);
|
|
20280
|
+
return row ? toDeviceAuth(row) : undefined;
|
|
20281
|
+
},
|
|
20282
|
+
findByUserCode: async (userCode) => {
|
|
20283
|
+
const [row] = await db.select().from(oauthDeviceAuthorizationsTable).where(eq(oauthDeviceAuthorizationsTable.user_code, userCode)).limit(1);
|
|
20284
|
+
return row ? toDeviceAuth(row) : undefined;
|
|
20285
|
+
},
|
|
20286
|
+
saveDeviceAuthorization: async (deviceAuthorization) => {
|
|
20287
|
+
await db.insert(oauthDeviceAuthorizationsTable).values({
|
|
20288
|
+
client_id: deviceAuthorization.clientId,
|
|
20289
|
+
created_at_ms: deviceAuthorization.createdAt,
|
|
20290
|
+
device_code_hash: deviceAuthorization.deviceCodeHash,
|
|
20291
|
+
expires_at_ms: deviceAuthorization.expiresAt,
|
|
20292
|
+
interval_seconds: deviceAuthorization.intervalSeconds,
|
|
20293
|
+
scopes: deviceAuthorization.scopes,
|
|
20294
|
+
status: deviceAuthorization.status,
|
|
20295
|
+
user_code: deviceAuthorization.userCode,
|
|
20296
|
+
user_sub: deviceAuthorization.userSub ?? null
|
|
20297
|
+
});
|
|
20298
|
+
},
|
|
20299
|
+
updateStatus: async (deviceCodeHash, status, userSub) => {
|
|
20300
|
+
await db.update(oauthDeviceAuthorizationsTable).set({ status, user_sub: userSub ?? null }).where(eq(oauthDeviceAuthorizationsTable.device_code_hash, deviceCodeHash));
|
|
20301
|
+
}
|
|
20302
|
+
});
|
|
19771
20303
|
var createPostgresOAuthClientStore = (db) => ({
|
|
19772
20304
|
findClient: async (clientId) => {
|
|
19773
20305
|
const [row] = await db.select().from(oauthClientsTable).where(eq(oauthClientsTable.client_id, clientId)).limit(1);
|
|
@@ -19782,6 +20314,10 @@ var createPostgresOidcRefreshTokenStore = (db) => ({
|
|
|
19782
20314
|
deleteForUser: async (userId) => {
|
|
19783
20315
|
await db.delete(oauthRefreshTokensTable).where(eq(oauthRefreshTokensTable.user_id, userId));
|
|
19784
20316
|
},
|
|
20317
|
+
getToken: async (tokenHash) => {
|
|
20318
|
+
const [row] = await db.select().from(oauthRefreshTokensTable).where(eq(oauthRefreshTokensTable.token_hash, tokenHash)).limit(1);
|
|
20319
|
+
return row ? toRefresh(row) : undefined;
|
|
20320
|
+
},
|
|
19785
20321
|
saveToken: async (token) => {
|
|
19786
20322
|
await db.insert(oauthRefreshTokensTable).values(toRefreshValues(token));
|
|
19787
20323
|
}
|
|
@@ -20914,6 +21450,62 @@ var createPostgresPasswordlessTokenStore = (db) => ({
|
|
|
20914
21450
|
});
|
|
20915
21451
|
}
|
|
20916
21452
|
});
|
|
21453
|
+
// src/webhooks/inMemoryStore.ts
|
|
21454
|
+
var DEFAULT_LIST_LIMIT = 100;
|
|
21455
|
+
var createInMemoryWebhookDeliveryStore = () => {
|
|
21456
|
+
const failures = new Map;
|
|
21457
|
+
return {
|
|
21458
|
+
listFailed: async (limit = DEFAULT_LIST_LIMIT) => Array.from(failures.values()).sort((left, right) => right.createdAt - left.createdAt).slice(0, limit),
|
|
21459
|
+
recordFailure: async (delivery) => {
|
|
21460
|
+
failures.set(delivery.envelope.id, delivery);
|
|
21461
|
+
},
|
|
21462
|
+
removeFailure: async (envelopeId) => {
|
|
21463
|
+
failures.delete(envelopeId);
|
|
21464
|
+
}
|
|
21465
|
+
};
|
|
21466
|
+
};
|
|
21467
|
+
// src/webhooks/postgresStore.ts
|
|
21468
|
+
var ID_LENGTH15 = 255;
|
|
21469
|
+
var URL_LENGTH = 2048;
|
|
21470
|
+
var DEFAULT_LIST_LIMIT2 = 100;
|
|
21471
|
+
var webhookDeliveriesTable = pgTable("auth_webhook_deliveries", {
|
|
21472
|
+
attempts: bigint("attempts", { mode: "number" }).notNull(),
|
|
21473
|
+
created_at_ms: bigint("created_at_ms", { mode: "number" }).notNull(),
|
|
21474
|
+
endpoint_url: varchar("endpoint_url", { length: URL_LENGTH }).notNull(),
|
|
21475
|
+
envelope_id: varchar("envelope_id", { length: ID_LENGTH15 }).primaryKey(),
|
|
21476
|
+
envelope_json: jsonb("envelope_json").$type().notNull(),
|
|
21477
|
+
last_error: text("last_error"),
|
|
21478
|
+
last_status: bigint("last_status", { mode: "number" })
|
|
21479
|
+
});
|
|
21480
|
+
var toDelivery = (row) => ({
|
|
21481
|
+
attempts: row.attempts,
|
|
21482
|
+
createdAt: row.created_at_ms,
|
|
21483
|
+
endpointUrl: row.endpoint_url,
|
|
21484
|
+
envelope: row.envelope_json,
|
|
21485
|
+
lastError: row.last_error ?? undefined,
|
|
21486
|
+
lastStatus: row.last_status ?? undefined
|
|
21487
|
+
});
|
|
21488
|
+
var createNeonWebhookDeliveryStore = (databaseUrl) => createPostgresWebhookDeliveryStore(createNeonDatabase(databaseUrl));
|
|
21489
|
+
var createPostgresWebhookDeliveryStore = (db) => ({
|
|
21490
|
+
listFailed: async (limit = DEFAULT_LIST_LIMIT2) => {
|
|
21491
|
+
const rows = await db.select().from(webhookDeliveriesTable).orderBy(desc(webhookDeliveriesTable.created_at_ms)).limit(limit);
|
|
21492
|
+
return rows.map(toDelivery);
|
|
21493
|
+
},
|
|
21494
|
+
recordFailure: async (delivery) => {
|
|
21495
|
+
await db.insert(webhookDeliveriesTable).values({
|
|
21496
|
+
attempts: delivery.attempts,
|
|
21497
|
+
created_at_ms: delivery.createdAt,
|
|
21498
|
+
endpoint_url: delivery.endpointUrl,
|
|
21499
|
+
envelope_id: delivery.envelope.id,
|
|
21500
|
+
envelope_json: delivery.envelope,
|
|
21501
|
+
last_error: delivery.lastError ?? null,
|
|
21502
|
+
last_status: delivery.lastStatus ?? null
|
|
21503
|
+
});
|
|
21504
|
+
},
|
|
21505
|
+
removeFailure: async (envelopeId) => {
|
|
21506
|
+
await db.delete(webhookDeliveriesTable).where(eq(webhookDeliveriesTable.envelope_id, envelopeId));
|
|
21507
|
+
}
|
|
21508
|
+
});
|
|
20917
21509
|
// src/portal/inMemorySetupSessionStore.ts
|
|
20918
21510
|
var cloneSession = (value) => ({
|
|
20919
21511
|
...value,
|
|
@@ -20935,19 +21527,19 @@ var createInMemorySetupSessionStore = () => {
|
|
|
20935
21527
|
};
|
|
20936
21528
|
};
|
|
20937
21529
|
// src/portal/postgresSetupSessionStore.ts
|
|
20938
|
-
var
|
|
21530
|
+
var ID_LENGTH16 = 255;
|
|
20939
21531
|
var setupSessionsTable = pgTable("auth_setup_sessions", {
|
|
20940
21532
|
capabilities: jsonb("capabilities").$type().notNull().default([]),
|
|
20941
21533
|
created_at_ms: bigint("created_at_ms", { mode: "number" }).notNull(),
|
|
20942
|
-
created_by: varchar("created_by", { length:
|
|
21534
|
+
created_by: varchar("created_by", { length: ID_LENGTH16 }),
|
|
20943
21535
|
expires_at_ms: bigint("expires_at_ms", { mode: "number" }).notNull(),
|
|
20944
21536
|
organization_id: varchar("organization_id", {
|
|
20945
|
-
length:
|
|
21537
|
+
length: ID_LENGTH16
|
|
20946
21538
|
}).notNull(),
|
|
20947
21539
|
setup_session_id: varchar("setup_session_id", {
|
|
20948
|
-
length:
|
|
21540
|
+
length: ID_LENGTH16
|
|
20949
21541
|
}).primaryKey(),
|
|
20950
|
-
token_hash: varchar("token_hash", { length:
|
|
21542
|
+
token_hash: varchar("token_hash", { length: ID_LENGTH16 }).notNull().unique()
|
|
20951
21543
|
});
|
|
20952
21544
|
var toSession = (row) => ({
|
|
20953
21545
|
capabilities: row.capabilities,
|
|
@@ -21138,6 +21730,7 @@ var auth = async ({
|
|
|
21138
21730
|
};
|
|
21139
21731
|
export {
|
|
21140
21732
|
writeWarrant,
|
|
21733
|
+
webhookDeliveriesTable,
|
|
21141
21734
|
webauthnRoutes,
|
|
21142
21735
|
webauthnCredentialsTable,
|
|
21143
21736
|
warrantsTable,
|
|
@@ -21182,6 +21775,7 @@ export {
|
|
|
21182
21775
|
rolesTable,
|
|
21183
21776
|
roleRoutes,
|
|
21184
21777
|
revokeUserSessions,
|
|
21778
|
+
revokeRefreshToken,
|
|
21185
21779
|
revocableProviderOptions,
|
|
21186
21780
|
resolveSetupSession,
|
|
21187
21781
|
resolveScimOrganization,
|
|
@@ -21213,6 +21807,7 @@ export {
|
|
|
21213
21807
|
oidcProviderRoutes,
|
|
21214
21808
|
oidcProviderOptions,
|
|
21215
21809
|
oauthRefreshTokensTable,
|
|
21810
|
+
oauthDeviceAuthorizationsTable,
|
|
21216
21811
|
oauthCodesTable,
|
|
21217
21812
|
oauthClientsTable,
|
|
21218
21813
|
mfaTotpRoutes,
|
|
@@ -21230,6 +21825,7 @@ export {
|
|
|
21230
21825
|
knownDevicesTable,
|
|
21231
21826
|
jwkThumbprint,
|
|
21232
21827
|
issueTokenSet,
|
|
21828
|
+
issueDeviceAuthorization,
|
|
21233
21829
|
isValidUser,
|
|
21234
21830
|
isValidProviderOption,
|
|
21235
21831
|
isUserSessionId,
|
|
@@ -21246,6 +21842,7 @@ export {
|
|
|
21246
21842
|
isAuthIntent,
|
|
21247
21843
|
isAnonymousSession,
|
|
21248
21844
|
inviteToOrganization,
|
|
21845
|
+
introspectToken,
|
|
21249
21846
|
instantiateUserSession,
|
|
21250
21847
|
hashToken,
|
|
21251
21848
|
hashPassword,
|
|
@@ -21264,11 +21861,13 @@ export {
|
|
|
21264
21861
|
extractPropFromIdentity,
|
|
21265
21862
|
exportAuditCsv,
|
|
21266
21863
|
exchangeToken,
|
|
21864
|
+
exchangeDeviceCode,
|
|
21267
21865
|
exchangeClientCredentials,
|
|
21268
21866
|
evaluatePassword,
|
|
21269
21867
|
endImpersonation,
|
|
21270
21868
|
encryptTotpSecret,
|
|
21271
21869
|
encryptSecret,
|
|
21870
|
+
denyDeviceAuthorization,
|
|
21272
21871
|
deleteWarrant,
|
|
21273
21872
|
defineProvidersConfiguration,
|
|
21274
21873
|
defineAuthSettings,
|
|
@@ -21297,6 +21896,7 @@ export {
|
|
|
21297
21896
|
createRiskEngine,
|
|
21298
21897
|
createRedisLockoutStore,
|
|
21299
21898
|
createRedisAuthSessionStore,
|
|
21899
|
+
createPostgresWebhookDeliveryStore,
|
|
21300
21900
|
createPostgresWebAuthnCredentialStore,
|
|
21301
21901
|
createPostgresWarrantStore,
|
|
21302
21902
|
createPostgresVaultStore,
|
|
@@ -21312,6 +21912,7 @@ export {
|
|
|
21312
21912
|
createPostgresLoginHistoryStore,
|
|
21313
21913
|
createPostgresLockoutStore,
|
|
21314
21914
|
createPostgresKnownDeviceStore,
|
|
21915
|
+
createPostgresDeviceAuthorizationStore,
|
|
21315
21916
|
createPostgresCredentialStore,
|
|
21316
21917
|
createPostgresAuthorizationCodeStore,
|
|
21317
21918
|
createPostgresAuditSink,
|
|
@@ -21320,6 +21921,7 @@ export {
|
|
|
21320
21921
|
createPostgresAccessTokenStore,
|
|
21321
21922
|
createOrganization,
|
|
21322
21923
|
createOAuthLinkedProviderCredentialResolver,
|
|
21924
|
+
createNeonWebhookDeliveryStore,
|
|
21323
21925
|
createNeonWebAuthnCredentialStore,
|
|
21324
21926
|
createNeonWarrantStore,
|
|
21325
21927
|
createNeonVaultStore,
|
|
@@ -21337,6 +21939,7 @@ export {
|
|
|
21337
21939
|
createNeonLockoutStore,
|
|
21338
21940
|
createNeonLinkedProviderStores,
|
|
21339
21941
|
createNeonKnownDeviceStore,
|
|
21942
|
+
createNeonDeviceAuthorizationStore,
|
|
21340
21943
|
createNeonDatabase,
|
|
21341
21944
|
createNeonCredentialStore,
|
|
21342
21945
|
createNeonAuthorizationCodeStore,
|
|
@@ -21349,6 +21952,7 @@ export {
|
|
|
21349
21952
|
createMembershipPermissionResolver,
|
|
21350
21953
|
createLockoutGuard,
|
|
21351
21954
|
createLinkedProviderCredentialResolver,
|
|
21955
|
+
createInMemoryWebhookDeliveryStore,
|
|
21352
21956
|
createInMemoryWebAuthnCredentialStore,
|
|
21353
21957
|
createInMemoryWarrantStore,
|
|
21354
21958
|
createInMemoryVaultStore,
|
|
@@ -21365,6 +21969,7 @@ export {
|
|
|
21365
21969
|
createInMemoryLockoutStore,
|
|
21366
21970
|
createInMemoryLinkedProviderStores,
|
|
21367
21971
|
createInMemoryKnownDeviceStore,
|
|
21972
|
+
createInMemoryDeviceAuthorizationStore,
|
|
21368
21973
|
createInMemoryCredentialStore,
|
|
21369
21974
|
createInMemoryCheckCache,
|
|
21370
21975
|
createInMemoryAuthorizationCodeStore,
|
|
@@ -21396,6 +22001,7 @@ export {
|
|
|
21396
22001
|
auditEventsTable,
|
|
21397
22002
|
assessRisk,
|
|
21398
22003
|
assessAbuse,
|
|
22004
|
+
approveDeviceAuthorization,
|
|
21399
22005
|
apiKeysTable,
|
|
21400
22006
|
apiKeysRoutes,
|
|
21401
22007
|
apiClientsTable,
|
|
@@ -21404,6 +22010,7 @@ export {
|
|
|
21404
22010
|
acceptInvitation,
|
|
21405
22011
|
WEBAUTHN_CHALLENGE_COOKIE,
|
|
21406
22012
|
DEFAULT_WEBHOOK_TIMEOUT_MS,
|
|
22013
|
+
DEFAULT_WEBHOOK_RETRY,
|
|
21407
22014
|
DEFAULT_WEBAUTHN_SESSION_TTL_MS,
|
|
21408
22015
|
DEFAULT_WEBAUTHN_ROUTE,
|
|
21409
22016
|
DEFAULT_WEBAUTHN_CHALLENGE_TTL_MS,
|
|
@@ -21432,5 +22039,5 @@ export {
|
|
|
21432
22039
|
AuthIdentityConflictError
|
|
21433
22040
|
};
|
|
21434
22041
|
|
|
21435
|
-
//# debugId=
|
|
22042
|
+
//# debugId=451C9751C02E5E2164756E2164756E21
|
|
21436
22043
|
//# sourceMappingURL=index.js.map
|