@datalayer/personal-agent-protocol 0.3.2 → 0.3.3
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/lib/{chunk-TU6B5MQ7.js → chunk-JIMKKTDT.js} +349 -18
- package/lib/{chunk-TU6B5MQ7.js.map → chunk-JIMKKTDT.js.map} +4 -4
- package/lib/device.d.ts +44 -0
- package/lib/device.d.ts.map +1 -0
- package/lib/device.js +327 -0
- package/lib/device.js.map +1 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +5 -1
- package/lib/reactor.js +1 -1
- package/lib/server.js +1 -1
- package/package.json +1 -1
|
@@ -1299,7 +1299,7 @@ function buildReactorFromPlugins(pluginsInput, options = {}) {
|
|
|
1299
1299
|
// imperative `ctx.contribute` is not knowable before it runs, and the
|
|
1300
1300
|
// graph reads those from the registry instead.
|
|
1301
1301
|
contributesTo: [
|
|
1302
|
-
...new Set((plugin.contributes ?? []).map((
|
|
1302
|
+
...new Set((plugin.contributes ?? []).map((record3) => record3.point.id))
|
|
1303
1303
|
]
|
|
1304
1304
|
};
|
|
1305
1305
|
},
|
|
@@ -1369,8 +1369,8 @@ function buildReactorFromPlugins(pluginsInput, options = {}) {
|
|
|
1369
1369
|
return;
|
|
1370
1370
|
}
|
|
1371
1371
|
const ctx = buildPhaseContext(name, current);
|
|
1372
|
-
for (const
|
|
1373
|
-
contributions.add(name,
|
|
1372
|
+
for (const record3 of current.plugin.contributes ?? []) {
|
|
1373
|
+
contributions.add(name, record3.point, record3.value, record3.options);
|
|
1374
1374
|
}
|
|
1375
1375
|
for (const command of current.plugin.commands ?? []) {
|
|
1376
1376
|
commands.add(name, command);
|
|
@@ -2057,7 +2057,7 @@ function createPapCorePlugin(options = {}) {
|
|
|
2057
2057
|
}
|
|
2058
2058
|
return definePlugin({
|
|
2059
2059
|
name: "@datalayer/personal-agent-protocol-core",
|
|
2060
|
-
version: "0.3.
|
|
2060
|
+
version: "0.3.3",
|
|
2061
2061
|
contributionPoints: [
|
|
2062
2062
|
DiscoveryTransports,
|
|
2063
2063
|
UrlSafetyPolicies,
|
|
@@ -2685,15 +2685,15 @@ function concat(...buffers) {
|
|
|
2685
2685
|
return buf;
|
|
2686
2686
|
}
|
|
2687
2687
|
var NON_ASCII = /[^\x00-\x7f]/;
|
|
2688
|
-
function encode(
|
|
2689
|
-
if (typeof
|
|
2690
|
-
if (NON_ASCII.test(
|
|
2688
|
+
function encode(string3) {
|
|
2689
|
+
if (typeof string3 == "string" && string3.length >= 128) {
|
|
2690
|
+
if (NON_ASCII.test(string3))
|
|
2691
2691
|
throw new TypeError("non-ASCII string encountered in encode()");
|
|
2692
|
-
return encoder.encode(
|
|
2692
|
+
return encoder.encode(string3);
|
|
2693
2693
|
}
|
|
2694
|
-
const bytes = new Uint8Array(
|
|
2695
|
-
for (let i = 0; i <
|
|
2696
|
-
const code =
|
|
2694
|
+
const bytes = new Uint8Array(string3.length);
|
|
2695
|
+
for (let i = 0; i < string3.length; i++) {
|
|
2696
|
+
const code = string3.charCodeAt(i);
|
|
2697
2697
|
if (code > 127)
|
|
2698
2698
|
throw new TypeError("non-ASCII string encountered in encode()");
|
|
2699
2699
|
bytes[i] = code;
|
|
@@ -4122,12 +4122,12 @@ function httpsUrl5(value, label) {
|
|
|
4122
4122
|
return parsed;
|
|
4123
4123
|
}
|
|
4124
4124
|
function validScopes(values) {
|
|
4125
|
-
const
|
|
4125
|
+
const scopes3 = [...new Set(values)];
|
|
4126
4126
|
const token = /^[\x21\x23-\x5b\x5d-\x7e]+$/;
|
|
4127
|
-
if (
|
|
4127
|
+
if (scopes3.length === 0 || scopes3.some((scope) => !token.test(scope))) {
|
|
4128
4128
|
throw new AuthorizationError("invalid_scope", "At least one valid OAuth scope is required");
|
|
4129
4129
|
}
|
|
4130
|
-
return
|
|
4130
|
+
return scopes3;
|
|
4131
4131
|
}
|
|
4132
4132
|
async function buildDirectSignInRequest(options) {
|
|
4133
4133
|
const randomBytes2 = options.randomBytes ?? defaultRandomBytes3;
|
|
@@ -4141,14 +4141,14 @@ async function buildDirectSignInRequest(options) {
|
|
|
4141
4141
|
new Uint8Array(await cryptoApi.subtle.digest("SHA-256", new TextEncoder().encode(verifier)))
|
|
4142
4142
|
);
|
|
4143
4143
|
const endpoint = httpsUrl5(options.authorizationEndpoint, "authorizationEndpoint");
|
|
4144
|
-
const
|
|
4144
|
+
const scopes3 = validScopes(options.scopes);
|
|
4145
4145
|
const clientId = httpsUrl5(options.clientId, "clientId").toString();
|
|
4146
4146
|
const redirectUri = httpsUrl5(options.redirectUri, "redirectUri").toString();
|
|
4147
4147
|
const issuer = httpsUrl5(options.issuer, "issuer").toString().replace(/\/$/, "");
|
|
4148
4148
|
endpoint.searchParams.set("response_type", "code");
|
|
4149
4149
|
endpoint.searchParams.set("client_id", clientId);
|
|
4150
4150
|
endpoint.searchParams.set("redirect_uri", redirectUri);
|
|
4151
|
-
endpoint.searchParams.set("scope",
|
|
4151
|
+
endpoint.searchParams.set("scope", scopes3.join(" "));
|
|
4152
4152
|
endpoint.searchParams.set("state", state);
|
|
4153
4153
|
endpoint.searchParams.set("code_challenge", challenge);
|
|
4154
4154
|
endpoint.searchParams.set("code_challenge_method", "S256");
|
|
@@ -4158,7 +4158,7 @@ async function buildDirectSignInRequest(options) {
|
|
|
4158
4158
|
issuer,
|
|
4159
4159
|
clientId,
|
|
4160
4160
|
redirectUri,
|
|
4161
|
-
scopes:
|
|
4161
|
+
scopes: scopes3,
|
|
4162
4162
|
state: new SecretValue(state),
|
|
4163
4163
|
codeVerifier: new SecretValue(verifier)
|
|
4164
4164
|
};
|
|
@@ -4525,6 +4525,335 @@ var DirectSignInClient = class {
|
|
|
4525
4525
|
}
|
|
4526
4526
|
};
|
|
4527
4527
|
|
|
4528
|
+
// src/device.ts
|
|
4529
|
+
var DEVICE_CODE_GRANT = "urn:ietf:params:oauth:grant-type:device_code";
|
|
4530
|
+
function httpsUrl6(value, label) {
|
|
4531
|
+
let parsed;
|
|
4532
|
+
try {
|
|
4533
|
+
parsed = new URL(value);
|
|
4534
|
+
} catch (cause) {
|
|
4535
|
+
throw new AuthorizationError("invalid_url", `${label} must be an HTTPS URL`, { cause });
|
|
4536
|
+
}
|
|
4537
|
+
if (parsed.protocol !== "https:" || parsed.username || parsed.password) {
|
|
4538
|
+
throw new AuthorizationError("invalid_url", `${label} must be an HTTPS URL`);
|
|
4539
|
+
}
|
|
4540
|
+
return parsed.toString();
|
|
4541
|
+
}
|
|
4542
|
+
function scopes2(values) {
|
|
4543
|
+
const result = [...new Set(values)];
|
|
4544
|
+
const token = /^[\x21\x23-\x5b\x5d-\x7e]+$/;
|
|
4545
|
+
if (result.length === 0 || result.some((scope) => !token.test(scope))) {
|
|
4546
|
+
throw new AuthorizationError("invalid_scope", "At least one valid OAuth scope is required");
|
|
4547
|
+
}
|
|
4548
|
+
return result;
|
|
4549
|
+
}
|
|
4550
|
+
function base64Url6(bytes) {
|
|
4551
|
+
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
4552
|
+
let output = "";
|
|
4553
|
+
for (let index = 0; index < bytes.length; index += 3) {
|
|
4554
|
+
const first = bytes[index] ?? 0;
|
|
4555
|
+
const second = bytes[index + 1];
|
|
4556
|
+
const third = bytes[index + 2];
|
|
4557
|
+
output += alphabet[first >>> 2];
|
|
4558
|
+
output += alphabet[(first & 3) << 4 | (second ?? 0) >>> 4];
|
|
4559
|
+
if (second !== void 0) {
|
|
4560
|
+
output += alphabet[(second & 15) << 2 | (third ?? 0) >>> 6];
|
|
4561
|
+
}
|
|
4562
|
+
if (third !== void 0) output += alphabet[third & 63];
|
|
4563
|
+
}
|
|
4564
|
+
return output;
|
|
4565
|
+
}
|
|
4566
|
+
function opaqueId2(prefix, bytes) {
|
|
4567
|
+
if (bytes.byteLength < 16) {
|
|
4568
|
+
throw new AuthorizationError("weak_entropy", "Device Sign-In requires 128 random bits");
|
|
4569
|
+
}
|
|
4570
|
+
return `${prefix}_${base64Url6(bytes)}`;
|
|
4571
|
+
}
|
|
4572
|
+
function record2(value, label) {
|
|
4573
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
4574
|
+
throw new AuthorizationError("invalid_device_response", `${label} must be an object`);
|
|
4575
|
+
}
|
|
4576
|
+
return value;
|
|
4577
|
+
}
|
|
4578
|
+
function string2(value, label) {
|
|
4579
|
+
if (typeof value !== "string" || !value) {
|
|
4580
|
+
throw new AuthorizationError("invalid_device_response", `${label} must be a non-empty string`);
|
|
4581
|
+
}
|
|
4582
|
+
return value;
|
|
4583
|
+
}
|
|
4584
|
+
function parseDeviceAuthorization(value) {
|
|
4585
|
+
const source = record2(value, "device authorization response");
|
|
4586
|
+
const expiresIn = source.expires_in;
|
|
4587
|
+
const interval = source.interval ?? 5;
|
|
4588
|
+
if (!Number.isInteger(expiresIn) || expiresIn <= 0 || expiresIn > 3600) {
|
|
4589
|
+
throw new AuthorizationError("invalid_device_response", "expires_in must be 1..3600");
|
|
4590
|
+
}
|
|
4591
|
+
if (!Number.isInteger(interval) || interval <= 0 || interval > 300) {
|
|
4592
|
+
throw new AuthorizationError("invalid_device_response", "interval must be 1..300");
|
|
4593
|
+
}
|
|
4594
|
+
const complete = source.verification_uri_complete;
|
|
4595
|
+
if (complete !== void 0 && typeof complete !== "string") {
|
|
4596
|
+
throw new AuthorizationError(
|
|
4597
|
+
"invalid_device_response",
|
|
4598
|
+
"verification_uri_complete must be a string"
|
|
4599
|
+
);
|
|
4600
|
+
}
|
|
4601
|
+
return {
|
|
4602
|
+
deviceCode: new SecretValue(string2(source.device_code, "device_code")),
|
|
4603
|
+
userCode: string2(source.user_code, "user_code"),
|
|
4604
|
+
verificationUri: httpsUrl6(
|
|
4605
|
+
string2(source.verification_uri, "verification_uri"),
|
|
4606
|
+
"verification_uri"
|
|
4607
|
+
),
|
|
4608
|
+
...complete === void 0 ? {} : { verificationUriComplete: httpsUrl6(complete, "verification_uri_complete") },
|
|
4609
|
+
expiresIn,
|
|
4610
|
+
interval
|
|
4611
|
+
};
|
|
4612
|
+
}
|
|
4613
|
+
function isPending(value) {
|
|
4614
|
+
if (typeof value !== "object" || value === null) return false;
|
|
4615
|
+
const pending = value;
|
|
4616
|
+
return pending.kind === "pap.device-sign-in.v1" && pending.deviceCode instanceof SecretValue && pending.expiresAt instanceof Date && pending.nextPollAt instanceof Date && typeof pending.tokenEndpoint === "string" && typeof pending.interval === "number";
|
|
4617
|
+
}
|
|
4618
|
+
var DeviceSignInClient = class {
|
|
4619
|
+
#reactor;
|
|
4620
|
+
#fetch;
|
|
4621
|
+
#maxResponseBytes;
|
|
4622
|
+
constructor(options) {
|
|
4623
|
+
const fetcher = options.fetch ?? globalThis.fetch;
|
|
4624
|
+
if (!fetcher) throw new AuthorizationError("fetch_unavailable", "A fetch implementation is required");
|
|
4625
|
+
const limit = options.maxResponseBytes ?? 100 * 1024;
|
|
4626
|
+
if (!Number.isInteger(limit) || limit <= 0) throw new RangeError("maxResponseBytes must be positive");
|
|
4627
|
+
this.#reactor = options.reactor;
|
|
4628
|
+
this.#fetch = fetcher;
|
|
4629
|
+
this.#maxResponseBytes = limit;
|
|
4630
|
+
}
|
|
4631
|
+
async begin(options) {
|
|
4632
|
+
this.#validateContext(options);
|
|
4633
|
+
const clock = firstContribution(this.#reactor, Clocks, "clock");
|
|
4634
|
+
const random = firstContribution(this.#reactor, RandomSources, "random source");
|
|
4635
|
+
const signer = firstContribution(this.#reactor, Signers, "signer");
|
|
4636
|
+
const endpoint = httpsUrl6(options.deviceAuthorizationEndpoint, "deviceAuthorizationEndpoint");
|
|
4637
|
+
const tokenEndpoint = httpsUrl6(options.tokenEndpoint, "tokenEndpoint");
|
|
4638
|
+
const issuer = httpsUrl6(options.issuer, "issuer").replace(/\/$/, "");
|
|
4639
|
+
const clientId = httpsUrl6(options.clientId, "clientId");
|
|
4640
|
+
const requestedScopes = scopes2(options.scopes);
|
|
4641
|
+
const now = clock.now();
|
|
4642
|
+
const clientAssertion = await signer.sign(
|
|
4643
|
+
this.#claims(clientId, endpoint, now, random.bytes(16)),
|
|
4644
|
+
{ purpose: "client_assertion" }
|
|
4645
|
+
);
|
|
4646
|
+
const response = await this.#request(
|
|
4647
|
+
endpoint,
|
|
4648
|
+
new URLSearchParams({
|
|
4649
|
+
scope: requestedScopes.join(" "),
|
|
4650
|
+
client_id: clientId,
|
|
4651
|
+
client_assertion_type: JWT_CLIENT_ASSERTION,
|
|
4652
|
+
client_assertion: clientAssertion.reveal()
|
|
4653
|
+
}),
|
|
4654
|
+
void 0,
|
|
4655
|
+
options.signal
|
|
4656
|
+
);
|
|
4657
|
+
const payload = await this.#decode(response, "Device authorization");
|
|
4658
|
+
if (!response.ok) throw this.#remoteError(response, payload, "Company refused Device Sign-In");
|
|
4659
|
+
const authorization = parseDeviceAuthorization(payload);
|
|
4660
|
+
const expiresAt = new Date(now.getTime() + authorization.expiresIn * 1e3);
|
|
4661
|
+
const reference = opaqueId2("device", random.bytes(16));
|
|
4662
|
+
const pending = {
|
|
4663
|
+
kind: "pap.device-sign-in.v1",
|
|
4664
|
+
deviceCode: authorization.deviceCode,
|
|
4665
|
+
tokenEndpoint,
|
|
4666
|
+
issuer,
|
|
4667
|
+
clientId,
|
|
4668
|
+
tenantId: options.tenantId,
|
|
4669
|
+
pairwiseUserId: options.pairwiseUserId,
|
|
4670
|
+
sessionId: options.sessionId,
|
|
4671
|
+
scopes: requestedScopes,
|
|
4672
|
+
expiresAt,
|
|
4673
|
+
nextPollAt: new Date(now.getTime() + authorization.interval * 1e3),
|
|
4674
|
+
interval: authorization.interval
|
|
4675
|
+
};
|
|
4676
|
+
const store = firstContribution(this.#reactor, AuthorizationStateStores, "authorization state store");
|
|
4677
|
+
await store.put(reference, pending, { expiresAt });
|
|
4678
|
+
return {
|
|
4679
|
+
reference,
|
|
4680
|
+
userCode: authorization.userCode,
|
|
4681
|
+
verificationUri: authorization.verificationUri,
|
|
4682
|
+
...authorization.verificationUriComplete === void 0 ? {} : { verificationUriComplete: authorization.verificationUriComplete },
|
|
4683
|
+
expiresAt,
|
|
4684
|
+
pollInterval: authorization.interval,
|
|
4685
|
+
requestedScopes
|
|
4686
|
+
};
|
|
4687
|
+
}
|
|
4688
|
+
async poll(reference, signal) {
|
|
4689
|
+
const store = firstContribution(this.#reactor, AuthorizationStateStores, "authorization state store");
|
|
4690
|
+
const pending = await store.take(reference);
|
|
4691
|
+
if (!isPending(pending)) {
|
|
4692
|
+
throw new AuthorizationError(
|
|
4693
|
+
"invalid_or_expired_device_session",
|
|
4694
|
+
"Device Sign-In is unknown, expired, complete, or already being polled"
|
|
4695
|
+
);
|
|
4696
|
+
}
|
|
4697
|
+
const clock = firstContribution(this.#reactor, Clocks, "clock");
|
|
4698
|
+
const now = clock.now();
|
|
4699
|
+
if (now.getTime() >= pending.expiresAt.getTime()) {
|
|
4700
|
+
throw new AuthorizationError("expired_token", "Device Sign-In has expired");
|
|
4701
|
+
}
|
|
4702
|
+
if (now.getTime() < pending.nextPollAt.getTime()) {
|
|
4703
|
+
await store.put(reference, pending, { expiresAt: pending.expiresAt });
|
|
4704
|
+
return { status: "pending", retryAt: pending.nextPollAt, grantedScopes: [], missingScopes: [] };
|
|
4705
|
+
}
|
|
4706
|
+
try {
|
|
4707
|
+
const result = await this.#pollToken(pending, now, signal);
|
|
4708
|
+
if (result.response.ok) return await this.#complete(result.response, result.payload, pending);
|
|
4709
|
+
const source = typeof result.payload === "object" && result.payload !== null ? result.payload : {};
|
|
4710
|
+
const remote = "error" in source ? source.error : void 0;
|
|
4711
|
+
if (remote === "authorization_pending" || remote === "slow_down") {
|
|
4712
|
+
const interval = pending.interval + (remote === "slow_down" ? 5 : 0);
|
|
4713
|
+
const resumed = { ...pending, interval, nextPollAt: new Date(now.getTime() + interval * 1e3) };
|
|
4714
|
+
await store.put(reference, resumed, { expiresAt: pending.expiresAt });
|
|
4715
|
+
return { status: "pending", retryAt: resumed.nextPollAt, grantedScopes: [], missingScopes: [] };
|
|
4716
|
+
}
|
|
4717
|
+
if (remote === "access_denied" || remote === "expired_token") {
|
|
4718
|
+
throw new AuthorizationError(remote, "Device Sign-In ended without authorization");
|
|
4719
|
+
}
|
|
4720
|
+
await store.put(reference, pending, { expiresAt: pending.expiresAt });
|
|
4721
|
+
throw this.#remoteError(result.response, result.payload, "Company refused the device token request");
|
|
4722
|
+
} catch (cause) {
|
|
4723
|
+
if (cause instanceof AuthorizationError && ["access_denied", "expired_token"].includes(cause.code)) {
|
|
4724
|
+
throw cause;
|
|
4725
|
+
}
|
|
4726
|
+
const existing = await store.take(reference);
|
|
4727
|
+
if (existing === void 0) await store.put(reference, pending, { expiresAt: pending.expiresAt });
|
|
4728
|
+
throw cause;
|
|
4729
|
+
}
|
|
4730
|
+
}
|
|
4731
|
+
async #pollToken(pending, now, signal) {
|
|
4732
|
+
const random = firstContribution(this.#reactor, RandomSources, "random source");
|
|
4733
|
+
const signer = firstContribution(this.#reactor, Signers, "signer");
|
|
4734
|
+
const dpop = firstContribution(this.#reactor, DpopProofProviders, "DPoP proof provider");
|
|
4735
|
+
const assertion = await signer.sign(
|
|
4736
|
+
this.#claims(pending.clientId, pending.tokenEndpoint, now, random.bytes(16)),
|
|
4737
|
+
{ purpose: "client_assertion" }
|
|
4738
|
+
);
|
|
4739
|
+
const proof = await dpop.create({
|
|
4740
|
+
method: "POST",
|
|
4741
|
+
url: pending.tokenEndpoint,
|
|
4742
|
+
tenantId: pending.tenantId,
|
|
4743
|
+
subject: pending.pairwiseUserId,
|
|
4744
|
+
issuer: pending.issuer
|
|
4745
|
+
});
|
|
4746
|
+
const response = await this.#request(
|
|
4747
|
+
pending.tokenEndpoint,
|
|
4748
|
+
new URLSearchParams({
|
|
4749
|
+
grant_type: DEVICE_CODE_GRANT,
|
|
4750
|
+
device_code: pending.deviceCode.reveal(),
|
|
4751
|
+
session_id: pending.sessionId,
|
|
4752
|
+
client_id: pending.clientId,
|
|
4753
|
+
client_assertion_type: JWT_CLIENT_ASSERTION,
|
|
4754
|
+
client_assertion: assertion.reveal()
|
|
4755
|
+
}),
|
|
4756
|
+
proof.reveal(),
|
|
4757
|
+
signal
|
|
4758
|
+
);
|
|
4759
|
+
return { response, payload: await this.#decode(response, "Device token") };
|
|
4760
|
+
}
|
|
4761
|
+
async #complete(response, payload, pending) {
|
|
4762
|
+
let token;
|
|
4763
|
+
try {
|
|
4764
|
+
token = parseSessionToken(payload);
|
|
4765
|
+
} catch (cause) {
|
|
4766
|
+
throw new AuthorizationError("invalid_token_response", "Device token response is malformed", {
|
|
4767
|
+
statusCode: response.status,
|
|
4768
|
+
cause
|
|
4769
|
+
});
|
|
4770
|
+
}
|
|
4771
|
+
if (token.tokenType !== "DPoP" || !token.signedIn || token.sessionId !== pending.sessionId) {
|
|
4772
|
+
throw new AuthorizationError(
|
|
4773
|
+
"invalid_token_response",
|
|
4774
|
+
"Device Sign-In must return the signed-in proof-bound Session",
|
|
4775
|
+
{ statusCode: response.status }
|
|
4776
|
+
);
|
|
4777
|
+
}
|
|
4778
|
+
if (token.scopes.some((scope) => !pending.scopes.includes(scope))) {
|
|
4779
|
+
throw new AuthorizationError("scope_escalation", "Company returned an unrequested scope");
|
|
4780
|
+
}
|
|
4781
|
+
if (!token.accountToken) {
|
|
4782
|
+
throw new AuthorizationError("missing_account_token", "Device Sign-In did not return an Account Token");
|
|
4783
|
+
}
|
|
4784
|
+
const random = firstContribution(this.#reactor, RandomSources, "random source");
|
|
4785
|
+
const accountTokenReference = opaqueId2("account", random.bytes(16));
|
|
4786
|
+
const tokens = firstContribution(this.#reactor, TokenStores, "token store");
|
|
4787
|
+
await tokens.put(accountTokenReference, token.accountToken);
|
|
4788
|
+
const { accountToken: _accountToken, ...publicToken } = token;
|
|
4789
|
+
return {
|
|
4790
|
+
status: "complete",
|
|
4791
|
+
token: publicToken,
|
|
4792
|
+
accountTokenReference,
|
|
4793
|
+
grantedScopes: publicToken.scopes,
|
|
4794
|
+
missingScopes: pending.scopes.filter((scope) => !publicToken.scopes.includes(scope))
|
|
4795
|
+
};
|
|
4796
|
+
}
|
|
4797
|
+
#claims(clientId, audience, now, entropy2) {
|
|
4798
|
+
const iat = Math.floor(now.getTime() / 1e3);
|
|
4799
|
+
return { iss: clientId, sub: clientId, aud: audience, iat, exp: iat + 60, jti: opaqueId2("jti", entropy2) };
|
|
4800
|
+
}
|
|
4801
|
+
#validateContext(options) {
|
|
4802
|
+
if (!options.tenantId || options.tenantId.length > 256) throw new RangeError("Invalid tenantId");
|
|
4803
|
+
const identifiers = [
|
|
4804
|
+
["pairwiseUserId", options.pairwiseUserId],
|
|
4805
|
+
["sessionId", options.sessionId]
|
|
4806
|
+
];
|
|
4807
|
+
for (const [label, value] of identifiers) {
|
|
4808
|
+
if (!/^[A-Za-z0-9_-]{1,256}$/.test(value)) {
|
|
4809
|
+
throw new AuthorizationError("invalid_context", `Invalid ${label}`);
|
|
4810
|
+
}
|
|
4811
|
+
}
|
|
4812
|
+
}
|
|
4813
|
+
async #request(url, body, dpop, signal) {
|
|
4814
|
+
try {
|
|
4815
|
+
return await this.#fetch(url, {
|
|
4816
|
+
method: "POST",
|
|
4817
|
+
headers: { Accept: "application/json", ...dpop === void 0 ? {} : { DPoP: dpop } },
|
|
4818
|
+
body,
|
|
4819
|
+
credentials: "omit",
|
|
4820
|
+
redirect: "error",
|
|
4821
|
+
...signal === void 0 ? {} : { signal }
|
|
4822
|
+
});
|
|
4823
|
+
} catch (cause) {
|
|
4824
|
+
throw new AuthorizationError("request_failed", "Device Sign-In request failed", { cause });
|
|
4825
|
+
}
|
|
4826
|
+
}
|
|
4827
|
+
async #decode(response, label) {
|
|
4828
|
+
if (response.headers.get("content-type")?.split(";", 1)[0]?.trim() !== "application/json") {
|
|
4829
|
+
throw new AuthorizationError("invalid_content_type", `${label} endpoint must return JSON`, {
|
|
4830
|
+
statusCode: response.status
|
|
4831
|
+
});
|
|
4832
|
+
}
|
|
4833
|
+
const body = await response.text();
|
|
4834
|
+
if (new TextEncoder().encode(body).byteLength > this.#maxResponseBytes) {
|
|
4835
|
+
throw new AuthorizationError("response_too_large", `${label} response exceeds size limit`, {
|
|
4836
|
+
statusCode: response.status
|
|
4837
|
+
});
|
|
4838
|
+
}
|
|
4839
|
+
try {
|
|
4840
|
+
return parseJsonStrict(body);
|
|
4841
|
+
} catch (cause) {
|
|
4842
|
+
throw new AuthorizationError("invalid_json", `${label} endpoint returned invalid JSON`, {
|
|
4843
|
+
statusCode: response.status,
|
|
4844
|
+
cause
|
|
4845
|
+
});
|
|
4846
|
+
}
|
|
4847
|
+
}
|
|
4848
|
+
#remoteError(response, payload, message2) {
|
|
4849
|
+
const source = typeof payload === "object" && payload !== null ? payload : {};
|
|
4850
|
+
const remote = "error" in source ? source.error : void 0;
|
|
4851
|
+
return new AuthorizationError(typeof remote === "string" ? remote : "http_error", message2, {
|
|
4852
|
+
statusCode: response.status
|
|
4853
|
+
});
|
|
4854
|
+
}
|
|
4855
|
+
};
|
|
4856
|
+
|
|
4528
4857
|
// src/discovery.ts
|
|
4529
4858
|
function normalizeDomain(domain2) {
|
|
4530
4859
|
const value = domain2.replace(/\.$/, "").toLowerCase();
|
|
@@ -4857,7 +5186,9 @@ export {
|
|
|
4857
5186
|
validateDirectSignInCallback,
|
|
4858
5187
|
AuthorizationCodeGrant,
|
|
4859
5188
|
DirectSignInClient,
|
|
5189
|
+
DEVICE_CODE_GRANT,
|
|
5190
|
+
DeviceSignInClient,
|
|
4860
5191
|
discoverCompany,
|
|
4861
5192
|
AgentIdentityClient
|
|
4862
5193
|
};
|
|
4863
|
-
//# sourceMappingURL=chunk-
|
|
5194
|
+
//# sourceMappingURL=chunk-JIMKKTDT.js.map
|