From 2c5c15c4a8f72cbb50860ce02c8621372a5fa684 Mon Sep 17 00:00:00 2001 From: Deepak Prabhakara Date: Thu, 15 Jan 2026 00:27:05 +0000 Subject: [PATCH 1/3] added ttlInMinutes config --- lib/response.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/response.ts b/lib/response.ts index a63a5ae..5a08850 100644 --- a/lib/response.ts +++ b/lib/response.ts @@ -325,6 +325,7 @@ const createSAMLResponse = async ({ privateKey, publicKey, flattenArray = false, + ttlInMinutes, }: { audience: string; issuer: string; @@ -334,6 +335,7 @@ const createSAMLResponse = async ({ privateKey: string; publicKey: string; flattenArray?: boolean; + ttlInMinutes?: number; }): Promise => { const authDate = new Date(); const authTimestamp = authDate.toISOString(); @@ -341,7 +343,7 @@ const createSAMLResponse = async ({ authDate.setMinutes(authDate.getMinutes() - 5); const notBefore = authDate.toISOString(); - authDate.setMinutes(authDate.getMinutes() + 10); + authDate.setMinutes(authDate.getMinutes() + (ttlInMinutes || 10)); const notAfter = authDate.toISOString(); const nodes = { From 3199b1c17174ba85c1a718e973b8d72015fb2267 Mon Sep 17 00:00:00 2001 From: Deepak Prabhakara Date: Thu, 15 Jan 2026 07:59:17 +0000 Subject: [PATCH 2/3] added tests --- test/lib/response.spec.ts | 68 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/test/lib/response.spec.ts b/test/lib/response.spec.ts index c04a406..bb079ee 100644 --- a/test/lib/response.spec.ts +++ b/test/lib/response.spec.ts @@ -392,3 +392,71 @@ it('parse should throw error if rawAssertion is empty', async function () { assert.strictEqual((error as Error).message, 'rawAssertion is required.'); } }); + +it('Should create a SAML response with default ttlInMinutes', async function () { + const json = { + audience: 'http://sp.example.com/demo1/metadata.php', + issuer: 'http://idp.example.com/metadata.php', + acsUrl: 'http://sp.example.com/demo1/index.php?acs', + claims: { + raw: { + 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier': + '_ce3d2948b4cf20146dee0a0b3dd6f69b6cf86f62d7', + }, + }, + requestId: 'ONELOGIN_4fee3b046395c4e751011e97f8900b5273d56685', + privateKey: oktaPrivateKey, + publicKey: oktaPublicKey, + }; + + const response = await createSAMLResponse(json); + + // Extract NotOnOrAfter and NotBefore from the Conditions element + const notOnOrAfterMatch = response.match(/NotOnOrAfter="([^"]+)"/); + const notBeforeMatch = response.match(/NotBefore="([^"]+)"/); + + assert.ok(notOnOrAfterMatch, 'NotOnOrAfter attribute should exist'); + assert.ok(notBeforeMatch, 'NotBefore attribute should exist'); + + const notOnOrAfter = new Date(notOnOrAfterMatch[1]); + const notBefore = new Date(notBeforeMatch[1]); + + // The difference should be exactly ttlInMinutes + const diffInMinutes = (notOnOrAfter.getTime() - notBefore.getTime()) / (1000 * 60); + assert.strictEqual(diffInMinutes, 10); +}); + +it('Should create a SAML response with custom ttlInMinutes', async function () { + const ttlInMinutes = 30; + const json = { + audience: 'http://sp.example.com/demo1/metadata.php', + issuer: 'http://idp.example.com/metadata.php', + acsUrl: 'http://sp.example.com/demo1/index.php?acs', + claims: { + raw: { + 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier': + '_ce3d2948b4cf20146dee0a0b3dd6f69b6cf86f62d7', + }, + }, + requestId: 'ONELOGIN_4fee3b046395c4e751011e97f8900b5273d56685', + privateKey: oktaPrivateKey, + publicKey: oktaPublicKey, + ttlInMinutes, + }; + + const response = await createSAMLResponse(json); + + // Extract NotOnOrAfter and NotBefore from the Conditions element + const notOnOrAfterMatch = response.match(/NotOnOrAfter="([^"]+)"/); + const notBeforeMatch = response.match(/NotBefore="([^"]+)"/); + + assert.ok(notOnOrAfterMatch, 'NotOnOrAfter attribute should exist'); + assert.ok(notBeforeMatch, 'NotBefore attribute should exist'); + + const notOnOrAfter = new Date(notOnOrAfterMatch[1]); + const notBefore = new Date(notBeforeMatch[1]); + + // The difference should be exactly ttlInMinutes + const diffInMinutes = (notOnOrAfter.getTime() - notBefore.getTime()) / (1000 * 60); + assert.strictEqual(diffInMinutes, ttlInMinutes); +}); From 1a75031165074418575f7fe31ee3cb6a28855abf Mon Sep 17 00:00:00 2001 From: Deepak Prabhakara Date: Thu, 15 Jan 2026 07:59:36 +0000 Subject: [PATCH 3/3] tweak --- test/lib/response.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/lib/response.spec.ts b/test/lib/response.spec.ts index bb079ee..ac01244 100644 --- a/test/lib/response.spec.ts +++ b/test/lib/response.spec.ts @@ -421,7 +421,7 @@ it('Should create a SAML response with default ttlInMinutes', async function () const notOnOrAfter = new Date(notOnOrAfterMatch[1]); const notBefore = new Date(notBeforeMatch[1]); - // The difference should be exactly ttlInMinutes + // The difference should be exactly 10 minutes const diffInMinutes = (notOnOrAfter.getTime() - notBefore.getTime()) / (1000 * 60); assert.strictEqual(diffInMinutes, 10); });