From 11827760ccabfd5979fbe9ceeda626a7a4c8155a Mon Sep 17 00:00:00 2001 From: dorsha Date: Wed, 17 Jun 2026 14:50:58 +0300 Subject: [PATCH 1/2] feat(tenant): add optional userId/loginId actor to generateSSOConfigurationLink When provided, the SSO Setup Suite session is attributed to that real user (who must exist and belong to the tenant) so actions taken inside the suite are audited against them instead of a temporary user. userId takes precedence over loginId. Backward compatible (trailing optional params). Co-Authored-By: Claude Opus 4.8 (1M context) --- README.md | 14 ++++++++++++++ lib/management/tenant.test.ts | 35 +++++++++++++++++++++++++++++++++++ lib/management/tenant.ts | 7 ++++++- 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 564d23fdf..1ab83e0ea 100644 --- a/README.md +++ b/README.md @@ -679,6 +679,20 @@ const res = await descopeClient.management.tenant.generateSSOConfigurationLink( 60 * 60 * 24, ); console.log(res.adminSSOConfigurationLink); + +// Optionally bind the link to a real user (by userId or loginId) so actions taken inside the +// SSO Suite are audited against that user instead of a temporary one. The user must exist and +// belong to the tenant; userId takes precedence over loginId. +const resWithActor = await descopeClient.management.tenant.generateSSOConfigurationLink( + 'my-tenant-id', + 60 * 60 * 24, + undefined, // ssoId + undefined, // email + undefined, // templateId + undefined, // userId + 'admin@my-tenant.com', // loginId +); +console.log(resWithActor.adminSSOConfigurationLink); ``` ### Manage Password diff --git a/lib/management/tenant.test.ts b/lib/management/tenant.test.ts index 0af3b0623..d455886d9 100644 --- a/lib/management/tenant.test.ts +++ b/lib/management/tenant.test.ts @@ -583,5 +583,40 @@ describe('Management Tenant', () => { response: httpResponse, }); }); + + it('should send the actor userId and loginId when provided', async () => { + const httpResponse = { + ok: true, + json: () => ({ + adminSSOConfigurationLink: 'some link', + }), + clone: () => ({ + json: () => Promise.resolve({ adminSSOConfigurationLink: 'some link' }), + }), + status: 200, + }; + mockHttpClient.post.mockResolvedValue(httpResponse); + + await management.tenant.generateSSOConfigurationLink( + 'test', + 60 * 60 * 24, + undefined, + undefined, + undefined, + 'user-1', + 'admin@aa.com', + ); + + expect(mockHttpClient.post).toHaveBeenCalledWith( + apiPaths.tenant.generateSSOConfigurationLink, + { + tenantId: 'test', + expireTime: 60 * 60 * 24, + userId: 'user-1', + loginId: 'admin@aa.com', + }, + {}, + ); + }); }); }); diff --git a/lib/management/tenant.ts b/lib/management/tenant.ts index 6bfb002dd..6f0d615c4 100644 --- a/lib/management/tenant.ts +++ b/lib/management/tenant.ts @@ -123,11 +123,16 @@ const withTenant = (httpClient: HttpClient) => ({ ssoId?: string, email?: string, templateId?: string, + // When provided, the SSO Setup Suite session is attributed to that real user so actions + // are audited against them instead of a temporary user. The user must exist and belong to + // the tenant. userId takes precedence over loginId. + userId?: string, + loginId?: string, ): Promise> => transformResponse( httpClient.post( apiPaths.tenant.generateSSOConfigurationLink, - { tenantId, expireTime: expireDuration, ssoId, email, templateId }, + { tenantId, expireTime: expireDuration, ssoId, email, templateId, userId, loginId }, {}, ), (data) => data, From 85892871f943e4dadc871c24d202f03b7e349f57 Mon Sep 17 00:00:00 2001 From: dorsha Date: Thu, 18 Jun 2026 11:49:15 +0300 Subject: [PATCH 2/2] refactor(tenant): replace userId/loginId with a single actorId on generateSSOConfigurationLink The SSO Setup Suite link now takes an optional actorId that is recorded as-is as the audit actor for in-suite actions (no user lookup/validation). Replaces the previous userId/loginId params. Co-Authored-By: Claude Opus 4.8 (1M context) --- README.md | 8 +++----- lib/management/tenant.test.ts | 8 +++----- lib/management/tenant.ts | 11 +++++------ 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 1ab83e0ea..ec67f7a9b 100644 --- a/README.md +++ b/README.md @@ -680,17 +680,15 @@ const res = await descopeClient.management.tenant.generateSSOConfigurationLink( ); console.log(res.adminSSOConfigurationLink); -// Optionally bind the link to a real user (by userId or loginId) so actions taken inside the -// SSO Suite are audited against that user instead of a temporary one. The user must exist and -// belong to the tenant; userId takes precedence over loginId. +// Optionally set an actor id, recorded as the audit actor for actions taken inside the SSO +// Suite (instead of the temporary user). It is used as-is for audit attribution and is not validated. const resWithActor = await descopeClient.management.tenant.generateSSOConfigurationLink( 'my-tenant-id', 60 * 60 * 24, undefined, // ssoId undefined, // email undefined, // templateId - undefined, // userId - 'admin@my-tenant.com', // loginId + 'my-admin-actor-id', // actorId ); console.log(resWithActor.adminSSOConfigurationLink); ``` diff --git a/lib/management/tenant.test.ts b/lib/management/tenant.test.ts index d455886d9..dd4f6f657 100644 --- a/lib/management/tenant.test.ts +++ b/lib/management/tenant.test.ts @@ -584,7 +584,7 @@ describe('Management Tenant', () => { }); }); - it('should send the actor userId and loginId when provided', async () => { + it('should send the actorId when provided', async () => { const httpResponse = { ok: true, json: () => ({ @@ -603,8 +603,7 @@ describe('Management Tenant', () => { undefined, undefined, undefined, - 'user-1', - 'admin@aa.com', + 'admin-actor-1', ); expect(mockHttpClient.post).toHaveBeenCalledWith( @@ -612,8 +611,7 @@ describe('Management Tenant', () => { { tenantId: 'test', expireTime: 60 * 60 * 24, - userId: 'user-1', - loginId: 'admin@aa.com', + actorId: 'admin-actor-1', }, {}, ); diff --git a/lib/management/tenant.ts b/lib/management/tenant.ts index 6f0d615c4..7316f523a 100644 --- a/lib/management/tenant.ts +++ b/lib/management/tenant.ts @@ -123,16 +123,15 @@ const withTenant = (httpClient: HttpClient) => ({ ssoId?: string, email?: string, templateId?: string, - // When provided, the SSO Setup Suite session is attributed to that real user so actions - // are audited against them instead of a temporary user. The user must exist and belong to - // the tenant. userId takes precedence over loginId. - userId?: string, - loginId?: string, + // When provided, actorId is recorded as the audit actor for actions performed inside the + // SSO Setup Suite (instead of the temporary user). It is used as-is for audit attribution + // and is not validated. + actorId?: string, ): Promise> => transformResponse( httpClient.post( apiPaths.tenant.generateSSOConfigurationLink, - { tenantId, expireTime: expireDuration, ssoId, email, templateId, userId, loginId }, + { tenantId, expireTime: expireDuration, ssoId, email, templateId, actorId }, {}, ), (data) => data,