@absolutejs/auth 0.27.0 → 0.28.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 +110 -2
- package/dist/index.js +420 -6
- package/dist/index.js.map +7 -7
- 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/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
|
|
|
@@ -19646,6 +19964,33 @@ var createInMemoryAuthorizationCodeStore = () => {
|
|
|
19646
19964
|
}
|
|
19647
19965
|
};
|
|
19648
19966
|
};
|
|
19967
|
+
var createInMemoryDeviceAuthorizationStore = () => {
|
|
19968
|
+
const byDeviceCode = new Map;
|
|
19969
|
+
return {
|
|
19970
|
+
deleteByDeviceCodeHash: async (deviceCodeHash) => {
|
|
19971
|
+
byDeviceCode.delete(deviceCodeHash);
|
|
19972
|
+
},
|
|
19973
|
+
findByDeviceCodeHash: async (deviceCodeHash) => byDeviceCode.get(deviceCodeHash),
|
|
19974
|
+
findByUserCode: async (userCode) => {
|
|
19975
|
+
for (const record of byDeviceCode.values()) {
|
|
19976
|
+
if (record.userCode === userCode)
|
|
19977
|
+
return record;
|
|
19978
|
+
}
|
|
19979
|
+
return;
|
|
19980
|
+
},
|
|
19981
|
+
saveDeviceAuthorization: async (deviceAuthorization) => {
|
|
19982
|
+
byDeviceCode.set(deviceAuthorization.deviceCodeHash, {
|
|
19983
|
+
...deviceAuthorization
|
|
19984
|
+
});
|
|
19985
|
+
},
|
|
19986
|
+
updateStatus: async (deviceCodeHash, status, userSub) => {
|
|
19987
|
+
const record = byDeviceCode.get(deviceCodeHash);
|
|
19988
|
+
if (!record)
|
|
19989
|
+
return;
|
|
19990
|
+
byDeviceCode.set(deviceCodeHash, { ...record, status, userSub });
|
|
19991
|
+
}
|
|
19992
|
+
};
|
|
19993
|
+
};
|
|
19649
19994
|
var createInMemoryOAuthClientStore = (clients) => {
|
|
19650
19995
|
const registry = new Map(clients.map((client) => [client.clientId, client]));
|
|
19651
19996
|
return {
|
|
@@ -19666,6 +20011,7 @@ var createInMemoryOidcRefreshTokenStore = () => {
|
|
|
19666
20011
|
tokens.delete(hash);
|
|
19667
20012
|
}
|
|
19668
20013
|
},
|
|
20014
|
+
getToken: async (tokenHash) => tokens.get(tokenHash),
|
|
19669
20015
|
saveToken: async (token) => {
|
|
19670
20016
|
tokens.set(token.tokenHash, { ...token });
|
|
19671
20017
|
}
|
|
@@ -19693,6 +20039,19 @@ var oauthCodesTable = pgTable("auth_oauth_codes", {
|
|
|
19693
20039
|
scopes: text("scopes").array().notNull(),
|
|
19694
20040
|
user_id: varchar("user_id", { length: ID_LENGTH7 }).notNull()
|
|
19695
20041
|
});
|
|
20042
|
+
var oauthDeviceAuthorizationsTable = pgTable("auth_oauth_device_authorizations", {
|
|
20043
|
+
client_id: varchar("client_id", { length: ID_LENGTH7 }).notNull(),
|
|
20044
|
+
created_at_ms: bigint("created_at_ms", { mode: "number" }).notNull(),
|
|
20045
|
+
device_code_hash: varchar("device_code_hash", {
|
|
20046
|
+
length: ID_LENGTH7
|
|
20047
|
+
}).primaryKey(),
|
|
20048
|
+
expires_at_ms: bigint("expires_at_ms", { mode: "number" }).notNull(),
|
|
20049
|
+
interval_seconds: bigint("interval_seconds", { mode: "number" }).notNull(),
|
|
20050
|
+
scopes: text("scopes").array().notNull(),
|
|
20051
|
+
status: varchar("status", { length: 16 }).notNull(),
|
|
20052
|
+
user_code: varchar("user_code", { length: 16 }).notNull().unique(),
|
|
20053
|
+
user_sub: varchar("user_sub", { length: ID_LENGTH7 })
|
|
20054
|
+
});
|
|
19696
20055
|
var oauthRefreshTokensTable = pgTable("auth_oauth_refresh_tokens", {
|
|
19697
20056
|
claims_json: jsonb("claims_json").$type(),
|
|
19698
20057
|
client_id: varchar("client_id", { length: ID_LENGTH7 }).notNull(),
|
|
@@ -19736,6 +20095,17 @@ var toCodeValues = (code) => ({
|
|
|
19736
20095
|
scopes: code.scopes,
|
|
19737
20096
|
user_id: code.userId
|
|
19738
20097
|
});
|
|
20098
|
+
var toDeviceAuth = (row) => ({
|
|
20099
|
+
clientId: row.client_id,
|
|
20100
|
+
createdAt: row.created_at_ms,
|
|
20101
|
+
deviceCodeHash: row.device_code_hash,
|
|
20102
|
+
expiresAt: row.expires_at_ms,
|
|
20103
|
+
intervalSeconds: row.interval_seconds,
|
|
20104
|
+
scopes: row.scopes,
|
|
20105
|
+
status: row.status,
|
|
20106
|
+
userCode: row.user_code,
|
|
20107
|
+
userSub: row.user_sub ?? undefined
|
|
20108
|
+
});
|
|
19739
20109
|
var toRefresh = (row) => ({
|
|
19740
20110
|
claims: row.claims_json ?? undefined,
|
|
19741
20111
|
clientId: row.client_id,
|
|
@@ -19757,6 +20127,7 @@ var toRefreshValues = (token) => ({
|
|
|
19757
20127
|
user_id: token.userId
|
|
19758
20128
|
});
|
|
19759
20129
|
var createNeonAuthorizationCodeStore = (databaseUrl) => createPostgresAuthorizationCodeStore(createNeonDatabase(databaseUrl));
|
|
20130
|
+
var createNeonDeviceAuthorizationStore = (databaseUrl) => createPostgresDeviceAuthorizationStore(createNeonDatabase(databaseUrl));
|
|
19760
20131
|
var createNeonOAuthClientStore = (databaseUrl) => createPostgresOAuthClientStore(createNeonDatabase(databaseUrl));
|
|
19761
20132
|
var createNeonOidcRefreshTokenStore = (databaseUrl) => createPostgresOidcRefreshTokenStore(createNeonDatabase(databaseUrl));
|
|
19762
20133
|
var createPostgresAuthorizationCodeStore = (db) => ({
|
|
@@ -19768,6 +20139,35 @@ var createPostgresAuthorizationCodeStore = (db) => ({
|
|
|
19768
20139
|
await db.insert(oauthCodesTable).values(toCodeValues(code));
|
|
19769
20140
|
}
|
|
19770
20141
|
});
|
|
20142
|
+
var createPostgresDeviceAuthorizationStore = (db) => ({
|
|
20143
|
+
deleteByDeviceCodeHash: async (deviceCodeHash) => {
|
|
20144
|
+
await db.delete(oauthDeviceAuthorizationsTable).where(eq(oauthDeviceAuthorizationsTable.device_code_hash, deviceCodeHash));
|
|
20145
|
+
},
|
|
20146
|
+
findByDeviceCodeHash: async (deviceCodeHash) => {
|
|
20147
|
+
const [row] = await db.select().from(oauthDeviceAuthorizationsTable).where(eq(oauthDeviceAuthorizationsTable.device_code_hash, deviceCodeHash)).limit(1);
|
|
20148
|
+
return row ? toDeviceAuth(row) : undefined;
|
|
20149
|
+
},
|
|
20150
|
+
findByUserCode: async (userCode) => {
|
|
20151
|
+
const [row] = await db.select().from(oauthDeviceAuthorizationsTable).where(eq(oauthDeviceAuthorizationsTable.user_code, userCode)).limit(1);
|
|
20152
|
+
return row ? toDeviceAuth(row) : undefined;
|
|
20153
|
+
},
|
|
20154
|
+
saveDeviceAuthorization: async (deviceAuthorization) => {
|
|
20155
|
+
await db.insert(oauthDeviceAuthorizationsTable).values({
|
|
20156
|
+
client_id: deviceAuthorization.clientId,
|
|
20157
|
+
created_at_ms: deviceAuthorization.createdAt,
|
|
20158
|
+
device_code_hash: deviceAuthorization.deviceCodeHash,
|
|
20159
|
+
expires_at_ms: deviceAuthorization.expiresAt,
|
|
20160
|
+
interval_seconds: deviceAuthorization.intervalSeconds,
|
|
20161
|
+
scopes: deviceAuthorization.scopes,
|
|
20162
|
+
status: deviceAuthorization.status,
|
|
20163
|
+
user_code: deviceAuthorization.userCode,
|
|
20164
|
+
user_sub: deviceAuthorization.userSub ?? null
|
|
20165
|
+
});
|
|
20166
|
+
},
|
|
20167
|
+
updateStatus: async (deviceCodeHash, status, userSub) => {
|
|
20168
|
+
await db.update(oauthDeviceAuthorizationsTable).set({ status, user_sub: userSub ?? null }).where(eq(oauthDeviceAuthorizationsTable.device_code_hash, deviceCodeHash));
|
|
20169
|
+
}
|
|
20170
|
+
});
|
|
19771
20171
|
var createPostgresOAuthClientStore = (db) => ({
|
|
19772
20172
|
findClient: async (clientId) => {
|
|
19773
20173
|
const [row] = await db.select().from(oauthClientsTable).where(eq(oauthClientsTable.client_id, clientId)).limit(1);
|
|
@@ -19782,6 +20182,10 @@ var createPostgresOidcRefreshTokenStore = (db) => ({
|
|
|
19782
20182
|
deleteForUser: async (userId) => {
|
|
19783
20183
|
await db.delete(oauthRefreshTokensTable).where(eq(oauthRefreshTokensTable.user_id, userId));
|
|
19784
20184
|
},
|
|
20185
|
+
getToken: async (tokenHash) => {
|
|
20186
|
+
const [row] = await db.select().from(oauthRefreshTokensTable).where(eq(oauthRefreshTokensTable.token_hash, tokenHash)).limit(1);
|
|
20187
|
+
return row ? toRefresh(row) : undefined;
|
|
20188
|
+
},
|
|
19785
20189
|
saveToken: async (token) => {
|
|
19786
20190
|
await db.insert(oauthRefreshTokensTable).values(toRefreshValues(token));
|
|
19787
20191
|
}
|
|
@@ -21182,6 +21586,7 @@ export {
|
|
|
21182
21586
|
rolesTable,
|
|
21183
21587
|
roleRoutes,
|
|
21184
21588
|
revokeUserSessions,
|
|
21589
|
+
revokeRefreshToken,
|
|
21185
21590
|
revocableProviderOptions,
|
|
21186
21591
|
resolveSetupSession,
|
|
21187
21592
|
resolveScimOrganization,
|
|
@@ -21213,6 +21618,7 @@ export {
|
|
|
21213
21618
|
oidcProviderRoutes,
|
|
21214
21619
|
oidcProviderOptions,
|
|
21215
21620
|
oauthRefreshTokensTable,
|
|
21621
|
+
oauthDeviceAuthorizationsTable,
|
|
21216
21622
|
oauthCodesTable,
|
|
21217
21623
|
oauthClientsTable,
|
|
21218
21624
|
mfaTotpRoutes,
|
|
@@ -21230,6 +21636,7 @@ export {
|
|
|
21230
21636
|
knownDevicesTable,
|
|
21231
21637
|
jwkThumbprint,
|
|
21232
21638
|
issueTokenSet,
|
|
21639
|
+
issueDeviceAuthorization,
|
|
21233
21640
|
isValidUser,
|
|
21234
21641
|
isValidProviderOption,
|
|
21235
21642
|
isUserSessionId,
|
|
@@ -21246,6 +21653,7 @@ export {
|
|
|
21246
21653
|
isAuthIntent,
|
|
21247
21654
|
isAnonymousSession,
|
|
21248
21655
|
inviteToOrganization,
|
|
21656
|
+
introspectToken,
|
|
21249
21657
|
instantiateUserSession,
|
|
21250
21658
|
hashToken,
|
|
21251
21659
|
hashPassword,
|
|
@@ -21264,11 +21672,13 @@ export {
|
|
|
21264
21672
|
extractPropFromIdentity,
|
|
21265
21673
|
exportAuditCsv,
|
|
21266
21674
|
exchangeToken,
|
|
21675
|
+
exchangeDeviceCode,
|
|
21267
21676
|
exchangeClientCredentials,
|
|
21268
21677
|
evaluatePassword,
|
|
21269
21678
|
endImpersonation,
|
|
21270
21679
|
encryptTotpSecret,
|
|
21271
21680
|
encryptSecret,
|
|
21681
|
+
denyDeviceAuthorization,
|
|
21272
21682
|
deleteWarrant,
|
|
21273
21683
|
defineProvidersConfiguration,
|
|
21274
21684
|
defineAuthSettings,
|
|
@@ -21312,6 +21722,7 @@ export {
|
|
|
21312
21722
|
createPostgresLoginHistoryStore,
|
|
21313
21723
|
createPostgresLockoutStore,
|
|
21314
21724
|
createPostgresKnownDeviceStore,
|
|
21725
|
+
createPostgresDeviceAuthorizationStore,
|
|
21315
21726
|
createPostgresCredentialStore,
|
|
21316
21727
|
createPostgresAuthorizationCodeStore,
|
|
21317
21728
|
createPostgresAuditSink,
|
|
@@ -21337,6 +21748,7 @@ export {
|
|
|
21337
21748
|
createNeonLockoutStore,
|
|
21338
21749
|
createNeonLinkedProviderStores,
|
|
21339
21750
|
createNeonKnownDeviceStore,
|
|
21751
|
+
createNeonDeviceAuthorizationStore,
|
|
21340
21752
|
createNeonDatabase,
|
|
21341
21753
|
createNeonCredentialStore,
|
|
21342
21754
|
createNeonAuthorizationCodeStore,
|
|
@@ -21365,6 +21777,7 @@ export {
|
|
|
21365
21777
|
createInMemoryLockoutStore,
|
|
21366
21778
|
createInMemoryLinkedProviderStores,
|
|
21367
21779
|
createInMemoryKnownDeviceStore,
|
|
21780
|
+
createInMemoryDeviceAuthorizationStore,
|
|
21368
21781
|
createInMemoryCredentialStore,
|
|
21369
21782
|
createInMemoryCheckCache,
|
|
21370
21783
|
createInMemoryAuthorizationCodeStore,
|
|
@@ -21396,6 +21809,7 @@ export {
|
|
|
21396
21809
|
auditEventsTable,
|
|
21397
21810
|
assessRisk,
|
|
21398
21811
|
assessAbuse,
|
|
21812
|
+
approveDeviceAuthorization,
|
|
21399
21813
|
apiKeysTable,
|
|
21400
21814
|
apiKeysRoutes,
|
|
21401
21815
|
apiClientsTable,
|
|
@@ -21432,5 +21846,5 @@ export {
|
|
|
21432
21846
|
AuthIdentityConflictError
|
|
21433
21847
|
};
|
|
21434
21848
|
|
|
21435
|
-
//# debugId=
|
|
21849
|
+
//# debugId=E246ECC6A14E235864756E2164756E21
|
|
21436
21850
|
//# sourceMappingURL=index.js.map
|