gdc-sdk-node-ts 2.4.36 → 2.4.37

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.
@@ -68,6 +68,28 @@ export type EmployeeDeviceActivationResult = {
68
68
  exchange: SubmitAndPollResult;
69
69
  dcr: SubmitAndPollResult;
70
70
  };
71
+ export type EmployeeDeviceOtpRecoveryInput = Readonly<{
72
+ idToken: string;
73
+ clientInstanceId: string;
74
+ pollOptions?: PollOptions;
75
+ }>;
76
+ export type EmployeeDeviceOtpRecoveryResult = Readonly<{
77
+ activationCode: string;
78
+ licenseId: string;
79
+ employeeRole: string;
80
+ employeeActorIdentifier: string;
81
+ recovery: SubmitAndPollResult;
82
+ }>;
83
+ /** Requests a fresh replacement credential for one OTP-authenticated installation. */
84
+ export declare function recoverEmployeeDeviceWithOtpWithDeps(deps: Readonly<{
85
+ routeCtx: RouteContext;
86
+ input: EmployeeDeviceOtpRecoveryInput;
87
+ identityEmployeeRecoveryPath: (ctx: RouteContext) => string;
88
+ identityEmployeeRecoveryPollPath: (ctx: RouteContext) => string;
89
+ submitAndPollWithBearerToken: (bearerToken: string | undefined, submitPath: string, pollPath: string, payload: {
90
+ thid?: string;
91
+ } & Record<string, unknown>, pollOptions?: PollOptions) => Promise<SubmitAndPollResult>;
92
+ }>): Promise<EmployeeDeviceOtpRecoveryResult>;
71
93
  export type EmployeeDeviceRevocationInput = {
72
94
  licenseId: string;
73
95
  clientId: string;
@@ -56,6 +56,26 @@ export function createProfileDeviceActivationRequest(input) {
56
56
  };
57
57
  return draft;
58
58
  }
59
+ /** Requests a fresh replacement credential for one OTP-authenticated installation. */
60
+ export async function recoverEmployeeDeviceWithOtpWithDeps(deps) {
61
+ const idToken = requiredText(deps.input.idToken, 'fresh OTP identity token');
62
+ const clientInstanceId = requiredText(deps.input.clientInstanceId, 'client instance id');
63
+ const recovery = await deps.submitAndPollWithBearerToken(idToken, deps.identityEmployeeRecoveryPath(deps.routeCtx), deps.identityEmployeeRecoveryPollPath(deps.routeCtx), { thid: `employee-recovery-${createRuntimeUuid()}`, client_instance_id: clientInstanceId }, deps.input.pollOptions);
64
+ const failedStatus = [recovery.submit.status, recovery.poll.status]
65
+ .find(status => status < 200 || status >= 300);
66
+ if (failedStatus !== undefined) {
67
+ throw new Error(`recoverEmployeeDeviceWithOtp: recovery failed (HTTP ${failedStatus}).`);
68
+ }
69
+ const terminal = responseBody(recovery.poll.body);
70
+ const activationCode = findResponseText(terminal, 'activation_code');
71
+ const licenseId = findResponseText(terminal, 'license_id');
72
+ const employeeRole = findResponseText(terminal, 'employee_role');
73
+ const employeeActorIdentifier = findResponseText(terminal, 'employee_same_as');
74
+ if (!activationCode || !licenseId || !employeeRole || !employeeActorIdentifier) {
75
+ throw new Error('recoverEmployeeDeviceWithOtp: incomplete recovery response.');
76
+ }
77
+ return { activationCode, licenseId, employeeRole, employeeActorIdentifier, recovery };
78
+ }
59
79
  export async function revokeEmployeeDeviceWithDeps(deps) {
60
80
  const licenseId = String(deps.input.licenseId || '').trim();
61
81
  const clientId = String(deps.input.clientId || '').trim();
@@ -147,6 +167,44 @@ function resolveDcrPayload(input) {
147
167
  return { ...input.dcrPayload };
148
168
  throw new Error('Device activation requires a device registration built by createProfileDeviceActivationRequest.');
149
169
  }
170
+ function responseBody(value) {
171
+ if (typeof value === 'string') {
172
+ try {
173
+ return responseBody(JSON.parse(value));
174
+ }
175
+ catch {
176
+ return {};
177
+ }
178
+ }
179
+ if (!value || typeof value !== 'object' || Array.isArray(value))
180
+ return {};
181
+ const record = value;
182
+ return record.body && typeof record.body === 'object' && !Array.isArray(record.body)
183
+ ? record.body
184
+ : record;
185
+ }
186
+ function findResponseText(value, key) {
187
+ if (!value || typeof value !== 'object')
188
+ return '';
189
+ if (Array.isArray(value)) {
190
+ for (const child of value) {
191
+ const found = findResponseText(child, key);
192
+ if (found)
193
+ return found;
194
+ }
195
+ return '';
196
+ }
197
+ const record = value;
198
+ const direct = normalizedText(record[key]);
199
+ if (direct)
200
+ return direct;
201
+ for (const child of Object.values(record)) {
202
+ const found = findResponseText(child, key);
203
+ if (found)
204
+ return found;
205
+ }
206
+ return '';
207
+ }
150
208
  function normalizedText(value) {
151
209
  return typeof value === 'string' ? value.trim() : '';
152
210
  }
@@ -9,7 +9,7 @@ import { type IndividualOrganizationConfirmOrderInput, type IndividualOrganizati
9
9
  import { type EnsureFamilyOrganizationRegistrationInput } from './family-organization-registration.js';
10
10
  import { type FamilyOrganizationSearchInput } from './family-organization-search.js';
11
11
  import { type SmartTokenRequestInput } from './smart-token.js';
12
- import { type EmployeeDeviceActivationRequestInput, type EmployeeDeviceActivationResult, type EmployeeDeviceRevocationInput } from './device-activation.js';
12
+ import { type EmployeeDeviceActivationRequestInput, type EmployeeDeviceActivationResult, type EmployeeDeviceOtpRecoveryInput, type EmployeeDeviceOtpRecoveryResult, type EmployeeDeviceRevocationInput } from './device-activation.js';
13
13
  import { type OrganizationLicenseOrderConfirmInput } from './organization-license-order.js';
14
14
  import { type IndividualOrganizationBootstrapInput, type IndividualOrganizationStartResult } from './individual-start.js';
15
15
  import { type CommunicationIngestionInput, type BlockchainArtifactRegistrationInput, type VitalSignBatchCommunicationFromSearchResponseInput, type CommunicationParticipantRuntimeSearchInput, type ClinicalBundleSearchInput, type ClinicalSectionUpdateInput, type ClinicalSummaryReadResult, type ClinicalSummaryRequestInput, type ClinicalSummaryUpdateInput, type GrantProfessionalAccessInput, type GrantProfessionalAccessResult, type DigitalTwinSecondaryUseConsentInput, type DigitalTwinSecondaryUseConsentResult, type DigitalTwinSubjectLinkPurgeInput, type DigitalTwinSubjectLinkPurgeResult, type IndividualMemberLifecycleInput, type IndividualMemberLicenseAddInput, type IndividualMemberLicenseInvitationInput, type IndividualMemberLicenseTransitionInput, type LicenseListRuntimeSearchInput, type LicenseOfferRuntimeSearchInput, type LicenseOrderRuntimeSearchInput, type OrganizationEmployeeCreationInput, type OrganizationEmployeeLicenseAddInput, type OrganizationEmployeeLicenseOfferInput, type OrganizationEmployeeLicenseInvitationInput, type OrganizationEmployeeLifecycleInput, type OrganizationEmployeeSearchInput, type ProfessionalAccessRequestInput, type ProfessionalAccessRequestResult, type RevokeProfessionalAccessInput, type RevokeProfessionalAccessResult, type RelatedPersonUpsertInput } from './resource-operations.js';
@@ -465,6 +465,8 @@ export declare class HttpRuntimeClient implements NodeRuntimeClient {
465
465
  * The implementation is actor-neutral and shares the profile-device flow.
466
466
  */
467
467
  activateEmployeeDeviceWithActivationRequest(input: EmployeeDeviceActivationRequestInput): Promise<EmployeeDeviceActivationResult>;
468
+ /** Obtains a replacement activation credential after fresh OTP verification. */
469
+ recoverEmployeeDeviceWithOtp(input: EmployeeDeviceOtpRecoveryInput & Partial<RouteContext>): Promise<EmployeeDeviceOtpRecoveryResult>;
468
470
  /**
469
471
  * Creates or updates a `RelatedPerson` for non-employee family/caregiver
470
472
  * roles such as a grandfather, guardian, or external caregiver.
@@ -6,7 +6,7 @@ import { confirmIndividualOrganizationOrderWithDeps, } from './individual-onboar
6
6
  import { ensureFamilyOrganizationRegistrationWithDeps, } from './family-organization-registration.js';
7
7
  import { searchFamilyOrganizationWithDeps } from './family-organization-search.js';
8
8
  import { requestSmartTokenWithDeps } from './smart-token.js';
9
- import { activateEmployeeDeviceWithActivationCodeWithDeps, activateEmployeeDeviceWithActivationRequestWithDeps, revokeEmployeeDeviceWithDeps, } from './device-activation.js';
9
+ import { activateEmployeeDeviceWithActivationCodeWithDeps, activateEmployeeDeviceWithActivationRequestWithDeps, recoverEmployeeDeviceWithOtpWithDeps, revokeEmployeeDeviceWithDeps, } from './device-activation.js';
10
10
  import { extractOfferIdFromResponseBody, extractOfferPreviewFromResponseBody, } from './order-offer-summary.js';
11
11
  import { confirmOrganizationLicenseOrderWithDeps } from './organization-license-order.js';
12
12
  import { startIndividualOrganizationWithDeps } from './individual-start.js';
@@ -909,6 +909,17 @@ export class HttpRuntimeClient {
909
909
  async activateEmployeeDeviceWithActivationRequest(input) {
910
910
  return this.activateProfileDeviceWithActivationRequest(input);
911
911
  }
912
+ /** Obtains a replacement activation credential after fresh OTP verification. */
913
+ async recoverEmployeeDeviceWithOtp(input) {
914
+ const routeCtx = this.paths.routeCtxFromInput(input);
915
+ return recoverEmployeeDeviceWithOtpWithDeps({
916
+ routeCtx,
917
+ input,
918
+ identityEmployeeRecoveryPath: this.paths.identityEmployeeRecoveryPath.bind(this.paths),
919
+ identityEmployeeRecoveryPollPath: this.paths.identityEmployeeRecoveryPollPath.bind(this.paths),
920
+ submitAndPollWithBearerToken: this.submitAndPollWithBearerToken.bind(this),
921
+ });
922
+ }
912
923
  /**
913
924
  * Creates or updates a `RelatedPerson` for non-employee family/caregiver
914
925
  * roles such as a grandfather, guardian, or external caregiver.
@@ -109,6 +109,8 @@ export declare class RuntimeClientPaths {
109
109
  digitalTwinCommunicationPollPath(ctx: RouteContext, format: string): string;
110
110
  identityTokenExchangePath(ctx: RouteContext): string;
111
111
  identityTokenExchangePollPath(ctx: RouteContext): string;
112
+ identityEmployeeRecoveryPath(ctx: RouteContext): string;
113
+ identityEmployeeRecoveryPollPath(ctx: RouteContext): string;
112
114
  identityDeviceDcrPath(ctx: RouteContext): string;
113
115
  identityDeviceDcrPollPath(ctx: RouteContext): string;
114
116
  identityDeviceRevokePath(ctx: RouteContext): string;
@@ -1,6 +1,6 @@
1
1
  // Copyright 2026 Antifraud Services Inc. under the Apache License, Version 2.0.
2
2
  import { GwCoreLifecycleAction } from './constants/lifecycle.js';
3
- import { buildHostRegistryPath, buildIdentityDeviceDcrPath, buildIdentityDeviceDcrPollPath, buildIdentityDeviceRevokePath, buildIdentityDeviceRevokePollPath, buildIdentityLicenseIssuePath, buildIdentityLicenseIssuePollPath, buildIdentityOpenIdSmartTokenPath, buildIdentityOpenIdSmartTokenPollPath, buildIdentityTokenExchangePath, buildIdentityTokenExchangePollPath, buildOrganizationDidBindingPath, buildOrganizationDidBindingPollPath, buildV1Path, } from './runtime-paths.js';
3
+ import { buildHostRegistryPath, buildIdentityDeviceDcrPath, buildIdentityDeviceDcrPollPath, buildIdentityDeviceRevokePath, buildIdentityDeviceRevokePollPath, buildIdentityEmployeeRecoveryPath, buildIdentityEmployeeRecoveryPollPath, buildIdentityLicenseIssuePath, buildIdentityLicenseIssuePollPath, buildIdentityOpenIdSmartTokenPath, buildIdentityOpenIdSmartTokenPollPath, buildIdentityTokenExchangePath, buildIdentityTokenExchangePollPath, buildOrganizationDidBindingPath, buildOrganizationDidBindingPollPath, buildV1Path, } from './runtime-paths.js';
4
4
  import { requireHostRouteContext, requireRouteContext, routeCtxFromInput, } from './runtime-route-context.js';
5
5
  export class RuntimeClientPaths {
6
6
  constructor(defaultCtx) {
@@ -123,6 +123,8 @@ export class RuntimeClientPaths {
123
123
  digitalTwinCommunicationPollPath(ctx, format) { return this.v1Path(ctx, 'digitaltwin', format, 'Communication', '_batch-response'); }
124
124
  identityTokenExchangePath(ctx) { return buildIdentityTokenExchangePath(ctx); }
125
125
  identityTokenExchangePollPath(ctx) { return buildIdentityTokenExchangePollPath(ctx); }
126
+ identityEmployeeRecoveryPath(ctx) { return buildIdentityEmployeeRecoveryPath(ctx); }
127
+ identityEmployeeRecoveryPollPath(ctx) { return buildIdentityEmployeeRecoveryPollPath(ctx); }
126
128
  identityDeviceDcrPath(ctx) { return buildIdentityDeviceDcrPath(ctx); }
127
129
  identityDeviceDcrPollPath(ctx) { return buildIdentityDeviceDcrPollPath(ctx); }
128
130
  identityDeviceRevokePath(ctx) { return buildIdentityDeviceRevokePath(ctx); }
@@ -6,6 +6,10 @@ export declare function buildOrganizationDidBindingPath(routeCtx: RouteContext):
6
6
  export declare function buildOrganizationDidBindingPollPath(routeCtx: RouteContext): string;
7
7
  export declare function buildIdentityTokenExchangePath(ctx: RouteContext): string;
8
8
  export declare function buildIdentityTokenExchangePollPath(ctx: RouteContext): string;
9
+ /** Fresh OTP-assisted replacement credential for one existing installation. */
10
+ export declare function buildIdentityEmployeeRecoveryPath(ctx: RouteContext): string;
11
+ /** Poll endpoint paired with employee wallet recovery. */
12
+ export declare function buildIdentityEmployeeRecoveryPollPath(ctx: RouteContext): string;
9
13
  export declare function buildIdentityDeviceDcrPath(ctx: RouteContext): string;
10
14
  export declare function buildIdentityDeviceDcrPollPath(ctx: RouteContext): string;
11
15
  /** Canonical controller operation that reserves an employee seat activation credential. */
@@ -28,6 +28,14 @@ export function buildIdentityTokenExchangePath(ctx) {
28
28
  export function buildIdentityTokenExchangePollPath(ctx) {
29
29
  return buildIdentityAuthPath(ctx, IdentityAuthActions.ExchangeResponse);
30
30
  }
31
+ /** Fresh OTP-assisted replacement credential for one existing installation. */
32
+ export function buildIdentityEmployeeRecoveryPath(ctx) {
33
+ return buildIdentityAuthPath(ctx, '_recover');
34
+ }
35
+ /** Poll endpoint paired with employee wallet recovery. */
36
+ export function buildIdentityEmployeeRecoveryPollPath(ctx) {
37
+ return buildIdentityAuthPath(ctx, '_recover-response');
38
+ }
31
39
  export function buildIdentityDeviceDcrPath(ctx) {
32
40
  return buildIdentityAuthPath(ctx, IdentityAuthActions.Dcr);
33
41
  }
@@ -45,6 +45,7 @@ export type ServerProfileSessionRecord = Readonly<{
45
45
  subjectDid: string;
46
46
  scopes: string[];
47
47
  sealedUnlockedWalletSeed: string;
48
+ sealedUnlockedVpToken?: string;
48
49
  sealedAccessToken: string;
49
50
  expiresAt: string;
50
51
  }>;
@@ -56,7 +57,18 @@ export type ServerProfileStore = Readonly<{
56
57
  getSession(sessionId: string): Promise<ServerProfileSessionRecord | undefined>;
57
58
  putSession(session: ServerProfileSessionRecord): Promise<void>;
58
59
  deleteSession(sessionId: string): Promise<void>;
60
+ /** Required by key rotation so no session can retain the superseded seed. */
61
+ deleteSessionsForProfile?(profileId: string): Promise<void>;
59
62
  }>;
63
+ export type ServerEmployeeProfileOtpRotationInput = Readonly<{
64
+ ownerId: string;
65
+ profileId: string;
66
+ idToken: string;
67
+ newPin: string;
68
+ redirectUris: string[];
69
+ clientName: string;
70
+ }>;
71
+ export type ServerEmployeeProfileOtpRotationResult = ServerProfileRecord;
60
72
  export type ServerProfileEnrollmentInput = Readonly<{
61
73
  /** Stable confidential id of the authenticated portal account that owns and lists this profile. */
62
74
  ownerId: string;
@@ -221,6 +233,13 @@ export declare class ServerProfileSessionManager {
221
233
  private readonly options;
222
234
  constructor(options: ServerProfileSessionManagerOptions);
223
235
  enroll(input: ServerProfileEnrollmentInput): Promise<ServerProfileRecord>;
236
+ /**
237
+ * Rotates an employee wallet after a fresh OTP-authenticated GW recovery.
238
+ * The old PIN and seed are never opened: DCR replaces the installation with
239
+ * newly generated keys, all old BFF sessions are removed, and the new wallet
240
+ * is opened once with the new PIN.
241
+ */
242
+ rotateEmployeeProfileWithOtp(input: ServerEmployeeProfileOtpRotationInput): Promise<ServerEmployeeProfileOtpRotationResult>;
224
243
  /**
225
244
  * Derives only the public enrollment descriptors for a server-governed
226
245
  * recovery seed. This is intended for pre-DCR controller binding requests;
@@ -249,6 +268,12 @@ export declare class ServerProfileSessionManager {
249
268
  submitLegalOrganizationIssueWithBootstrapWallet(input: ServerProfileOrganizationIssueInput): Promise<SubmitAndPollResult>;
250
269
  listProfiles(ownerId: string): Promise<ServerProfileRecord[]>;
251
270
  unlock(input: ServerProfileUnlockInput): Promise<ResolvedServerProfileSession>;
271
+ /**
272
+ * Renews the short SMART bearer while retaining the already-open server
273
+ * wallet session. The caller must supply a fresh authenticated account
274
+ * token; neither the PIN nor wallet keys return to the browser.
275
+ */
276
+ refreshSession(ownerId: string, sessionId: string, idToken: string): Promise<ResolvedServerProfileSession>;
252
277
  resolveSession(ownerId: string, sessionId: string): Promise<ResolvedServerProfileSession>;
253
278
  lock(ownerId: string, sessionId: string): Promise<void>;
254
279
  private createClient;
@@ -100,6 +100,53 @@ export class ServerProfileSessionManager {
100
100
  await this.options.store.putProfile(record);
101
101
  return record;
102
102
  }
103
+ /**
104
+ * Rotates an employee wallet after a fresh OTP-authenticated GW recovery.
105
+ * The old PIN and seed are never opened: DCR replaces the installation with
106
+ * newly generated keys, all old BFF sessions are removed, and the new wallet
107
+ * is opened once with the new PIN.
108
+ */
109
+ async rotateEmployeeProfileWithOtp(input) {
110
+ const previous = await this.requireOwnedProfile(input.ownerId, input.profileId);
111
+ if (previous.actorKind !== ActorKinds.OrganizationEmployee || previous.actorMode !== 'member') {
112
+ throw new Error('OTP wallet rotation is restricted to organization employee profiles.');
113
+ }
114
+ const clientInstanceId = String(previous.clientInstanceId || '').trim();
115
+ if (!clientInstanceId)
116
+ throw new Error('Employee profile has no registered installation id.');
117
+ if (!this.options.store.deleteSessionsForProfile) {
118
+ throw new Error('Employee wallet rotation requires profile-session invalidation support.');
119
+ }
120
+ const client = this.createClient(previous.routeContext, input.idToken);
121
+ const replacement = await client.recoverEmployeeDeviceWithOtp({
122
+ ...previous.routeContext,
123
+ idToken: input.idToken,
124
+ clientInstanceId,
125
+ });
126
+ const profile = await this.enroll({
127
+ ownerId: previous.ownerId,
128
+ profileId: previous.profileId,
129
+ actorKind: previous.actorKind,
130
+ actorMode: previous.actorMode,
131
+ actorDid: previous.actorDid,
132
+ profileDid: previous.profileDid,
133
+ providerDid: previous.providerDid,
134
+ routeContext: previous.routeContext,
135
+ allowedSubjectDids: previous.allowedSubjectDids,
136
+ pin: input.newPin,
137
+ idToken: input.idToken,
138
+ activationCode: replacement.activationCode,
139
+ clientInstanceId,
140
+ redirectUris: input.redirectUris,
141
+ clientName: input.clientName,
142
+ professionalProof: {
143
+ role: replacement.employeeRole,
144
+ sameAs: replacement.employeeActorIdentifier,
145
+ },
146
+ });
147
+ await this.options.store.deleteSessionsForProfile(profile.profileId);
148
+ return profile;
149
+ }
103
150
  /**
104
151
  * Derives only the public enrollment descriptors for a server-governed
105
152
  * recovery seed. This is intended for pre-DCR controller binding requests;
@@ -269,11 +316,69 @@ export class ServerProfileSessionManager {
269
316
  subjectDid: input.subjectDid,
270
317
  scopes: unique(input.scopes),
271
318
  sealedUnlockedWalletSeed: await this.options.sealer.seal(seed, `${sessionId}:unlocked-wallet-seed`),
319
+ ...(vpToken ? {
320
+ sealedUnlockedVpToken: await this.options.sealer.seal(vpToken, `${sessionId}:unlocked-vp-token`),
321
+ } : {}),
272
322
  sealedAccessToken: await this.options.sealer.seal(token.accessToken, `${sessionId}:access-token`),
273
323
  expiresAt: expiresAt.toISOString(),
274
324
  });
275
325
  return this.resolveSession(input.ownerId, sessionId);
276
326
  }
327
+ /**
328
+ * Renews the short SMART bearer while retaining the already-open server
329
+ * wallet session. The caller must supply a fresh authenticated account
330
+ * token; neither the PIN nor wallet keys return to the browser.
331
+ */
332
+ async refreshSession(ownerId, sessionId, idToken) {
333
+ const session = await this.options.store.getSession(sessionId);
334
+ if (!session || session.ownerId !== ownerId)
335
+ throw new Error('Profile session not found.');
336
+ if (new Date(session.expiresAt) <= this.now()) {
337
+ await this.options.store.deleteSession(sessionId);
338
+ throw new Error('Profile session expired.');
339
+ }
340
+ const normalizedIdToken = String(idToken || '').trim();
341
+ if (!normalizedIdToken)
342
+ throw new Error('Profile session refresh requires idToken.');
343
+ const profile = await this.requireOwnedProfile(ownerId, session.profileId);
344
+ this.requireSubject(profile, session.subjectDid);
345
+ const seed = await this.options.sealer.unseal(session.sealedUnlockedWalletSeed, `${sessionId}:unlocked-wallet-seed`);
346
+ const vpToken = session.sealedUnlockedVpToken
347
+ ? await this.options.sealer.unseal(session.sealedUnlockedVpToken, `${sessionId}:unlocked-vp-token`)
348
+ : undefined;
349
+ const walletKeyDerivationId = profile.walletKeyDerivationId || profile.profileId;
350
+ const wallet = await this.createWallet(walletKeyDerivationId, seed);
351
+ const now = this.now();
352
+ const smartTokenEndpoint = [
353
+ this.options.gatewayBaseUrl.replace(/\/+$/, ''),
354
+ buildIdentityOpenIdSmartTokenPath(profile.routeContext),
355
+ ].join('');
356
+ const assertion = await buildWalletClientAssertion(wallet, profile, smartTokenEndpoint, now);
357
+ const token = await this.createClient(profile.routeContext, normalizedIdToken).requestSmartToken({
358
+ ...profile.routeContext,
359
+ actorDid: profile.actorDid,
360
+ subjectDid: session.subjectDid,
361
+ clientId: profile.clientId,
362
+ issuer: profile.clientId,
363
+ audience: smartTokenEndpoint,
364
+ idToken: normalizedIdToken,
365
+ vpToken,
366
+ vpTokenFallback: vpToken ? undefined : 'omit',
367
+ clientAssertion: assertion,
368
+ clientAssertionType: 'private_key_jwt',
369
+ smartTokenKind: 'openid-smart',
370
+ acrValues: profileSmartAcrValues(profile.actorKind),
371
+ scopes: unique(session.scopes),
372
+ tokenCacheKey: `profile-refresh:${sessionId}:${now.getTime()}`,
373
+ });
374
+ if (token.status !== 'fetched' || !token.accessToken)
375
+ throw new Error('SMART token refresh failed.');
376
+ await this.options.store.putSession({
377
+ ...session,
378
+ sealedAccessToken: await this.options.sealer.seal(token.accessToken, `${sessionId}:access-token`),
379
+ });
380
+ return this.resolveSession(ownerId, sessionId);
381
+ }
277
382
  async resolveSession(ownerId, sessionId) {
278
383
  const session = await this.options.store.getSession(sessionId);
279
384
  if (!session || session.ownerId !== ownerId)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gdc-sdk-node-ts",
3
- "version": "2.4.36",
3
+ "version": "2.4.37",
4
4
  "description": "Next-generation Node runtime package for the GDC SDK family",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Antifraud Services Inc.",