@datalayer/agent-runtimes 1.3.112 → 1.3.113
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.
|
@@ -133,6 +133,8 @@ export declare class PactPersonalAgent {
|
|
|
133
133
|
}): Promise<Reply | StepUp>;
|
|
134
134
|
private verifyReceipt;
|
|
135
135
|
requestSignIn(user: string, scopes: string[]): Promise<SignIn>;
|
|
136
|
+
/** Ask once whether the person approved: the scopes granted, or `undefined` while pending. */
|
|
137
|
+
pollSignIn(user: string, signIn: SignIn): Promise<string[] | undefined>;
|
|
136
138
|
/** Poll until the person approved; the scopes they actually granted. */
|
|
137
139
|
finishSignIn(user: string, signIn: SignIn, intervalMs?: number, attempts?: number): Promise<string[]>;
|
|
138
140
|
}
|
|
@@ -315,42 +315,48 @@ export class PactPersonalAgent {
|
|
|
315
315
|
reference,
|
|
316
316
|
};
|
|
317
317
|
}
|
|
318
|
-
/**
|
|
319
|
-
async
|
|
318
|
+
/** Ask once whether the person approved: the scopes granted, or `undefined` while pending. */
|
|
319
|
+
async pollSignIn(user, signIn) {
|
|
320
320
|
const card = this.card;
|
|
321
321
|
const deviceCode = this.pending.get(signIn.reference);
|
|
322
322
|
if (!deviceCode) {
|
|
323
323
|
throw new PactError('no sign-in pending under this reference');
|
|
324
324
|
}
|
|
325
|
+
const answer = await this.fetch(card.delegation.tokenUrl, {
|
|
326
|
+
method: 'POST',
|
|
327
|
+
headers: {
|
|
328
|
+
Authorization: `Bearer ${await this.jwt(user)}`,
|
|
329
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
330
|
+
},
|
|
331
|
+
body: new URLSearchParams({
|
|
332
|
+
grant_type: DEVICE_CODE_GRANT,
|
|
333
|
+
device_code: deviceCode,
|
|
334
|
+
client_id: this.options.issuer,
|
|
335
|
+
}).toString(),
|
|
336
|
+
});
|
|
337
|
+
const body = await answer.json();
|
|
338
|
+
if (body.error === 'authorization_pending' || body.error === 'slow_down') {
|
|
339
|
+
return undefined;
|
|
340
|
+
}
|
|
341
|
+
if (body.error) {
|
|
342
|
+
this.pending.delete(signIn.reference);
|
|
343
|
+
throw new PactError(`the sign-in ended: ${body.error}`);
|
|
344
|
+
}
|
|
345
|
+
const granted = String(body.scope ?? '')
|
|
346
|
+
.split(' ')
|
|
347
|
+
.filter(Boolean);
|
|
348
|
+
await this.delegations().put(card.interfaceUrl, user, body.access_token, granted);
|
|
349
|
+
this.pending.delete(signIn.reference);
|
|
350
|
+
return granted;
|
|
351
|
+
}
|
|
352
|
+
/** Poll until the person approved; the scopes they actually granted. */
|
|
353
|
+
async finishSignIn(user, signIn, intervalMs = 5000, attempts = 120) {
|
|
325
354
|
for (let i = 0; i < attempts; i++) {
|
|
326
|
-
const
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
Authorization: `Bearer ${await this.jwt(user)}`,
|
|
330
|
-
'Content-Type': 'application/x-www-form-urlencoded',
|
|
331
|
-
},
|
|
332
|
-
body: new URLSearchParams({
|
|
333
|
-
grant_type: DEVICE_CODE_GRANT,
|
|
334
|
-
device_code: deviceCode,
|
|
335
|
-
client_id: this.options.issuer,
|
|
336
|
-
}).toString(),
|
|
337
|
-
});
|
|
338
|
-
const body = await answer.json();
|
|
339
|
-
if (body.error === 'authorization_pending' ||
|
|
340
|
-
body.error === 'slow_down') {
|
|
341
|
-
await new Promise(resolve => setTimeout(resolve, intervalMs));
|
|
342
|
-
continue;
|
|
355
|
+
const granted = await this.pollSignIn(user, signIn);
|
|
356
|
+
if (granted) {
|
|
357
|
+
return granted;
|
|
343
358
|
}
|
|
344
|
-
|
|
345
|
-
this.pending.delete(signIn.reference);
|
|
346
|
-
throw new PactError(`the sign-in ended: ${body.error}`);
|
|
347
|
-
}
|
|
348
|
-
const granted = String(body.scope ?? '')
|
|
349
|
-
.split(' ')
|
|
350
|
-
.filter(Boolean);
|
|
351
|
-
await this.delegations().put(card.interfaceUrl, user, body.access_token, granted);
|
|
352
|
-
this.pending.delete(signIn.reference);
|
|
353
|
-
return granted;
|
|
359
|
+
await new Promise(resolve => setTimeout(resolve, intervalMs));
|
|
354
360
|
}
|
|
355
361
|
throw new PactError('the person did not sign in in time');
|
|
356
362
|
}
|
|
@@ -122,7 +122,7 @@ export async function signRequest(request, signer, options) {
|
|
|
122
122
|
label,
|
|
123
123
|
nonce: options.nonce ?? generateNonce(),
|
|
124
124
|
signatureAgentKey: label,
|
|
125
|
-
additionalComponents: (options.components ?? ['@method', '@path']).filter(name => name !== '@authority'),
|
|
125
|
+
additionalComponents: (options.components ?? ['@method', '@path', '@query']).filter(name => name !== '@authority'),
|
|
126
126
|
});
|
|
127
127
|
return {
|
|
128
128
|
'Signature-Agent': agentHeader,
|
|
@@ -486,6 +486,27 @@ export interface AppPapSpec {
|
|
|
486
486
|
connections: AppPapConnectionSpec[];
|
|
487
487
|
company: AppPapCompanySpec;
|
|
488
488
|
}
|
|
489
|
+
/**
|
|
490
|
+
* A business the application asks for each person over PACT 1.0
|
|
491
|
+
* (AGENT_PROTOCOLS PI-01): its domain, and the audience its Provider
|
|
492
|
+
* assigned. Always in each person's own name; never a credential.
|
|
493
|
+
*/
|
|
494
|
+
export interface AppPactConnectionSpec {
|
|
495
|
+
/** Stable within the application: `support`. */
|
|
496
|
+
id: string;
|
|
497
|
+
/** The business's domain: `example.com`; its card is at `/.well-known/agent-card.json`. */
|
|
498
|
+
brand: string;
|
|
499
|
+
/** The audience the Brand's Provider assigned (PACT §3.1). */
|
|
500
|
+
audience: string;
|
|
501
|
+
/** `read`: asks as the application alone; `write`: also for the person, delegated. */
|
|
502
|
+
access: 'read' | 'write';
|
|
503
|
+
/** The Brand's scopes it may ask the person for: `orders:read`. */
|
|
504
|
+
scopes: string[];
|
|
505
|
+
}
|
|
506
|
+
/** PACT: the businesses it asks for each person. */
|
|
507
|
+
export interface AppPactSpec {
|
|
508
|
+
connections: AppPactConnectionSpec[];
|
|
509
|
+
}
|
|
489
510
|
/** When an application acts alone, and when it asks. */
|
|
490
511
|
export interface AppRuleSpec {
|
|
491
512
|
/** The action, in the words a person reads. */
|
|
@@ -1044,6 +1065,8 @@ export interface AppSpec {
|
|
|
1044
1065
|
connections: AppConnectionSpec[];
|
|
1045
1066
|
/** Personal Agent Protocol; absent, the application has none. */
|
|
1046
1067
|
pap?: AppPapSpec;
|
|
1068
|
+
/** PACT: the businesses it asks for each person (AGENT_PROTOCOLS PI-01). */
|
|
1069
|
+
pact?: AppPactSpec;
|
|
1047
1070
|
rules: AppRuleSpec[];
|
|
1048
1071
|
permissions: AppPermissionsSpec;
|
|
1049
1072
|
interface: AppInterfaceSpec;
|