'use strict'; const test = require('node:test'); const assert = require('node:assert/strict'); const { signHS256, verifyHS256 } = require('../src/jwt'); const { createIdentity } = require('../src/identity'); const SECRET = 'test-inbox-secret'; function decode(jwt) { return JSON.parse(Buffer.from(jwt.split('.')[1], 'base64url').toString('utf8')); } test('jwt: sign/verify roundtrip + tamper detection', () => { const token = signHS256({ external_user_id: 'cust-1', email: 'a@b.c' }, SECRET, 60); const payload = verifyHS256(token, SECRET); assert.equal(payload.external_user_id, 'cust-1'); assert.equal(payload.email, 'a@b.c'); const [h, c, s] = token.split('.'); const tampered = `${h}.${c}.${s.slice(0, -1)}x`; assert.equal(verifyHS256(tampered, SECRET), null); assert.equal(verifyHS256(token, 'wrong-secret'), null); }); test('identity: dev mode issues LibreDesk widget JWT', async () => { const identity = createIdentity({ libredeskInboxSecret: SECRET, identityDevMode: true, identityTtlSec: 120, siteJwtSecret: '', memberRpcUrl: '', rpcTimeoutMs: 1000, }); const out = await identity.issue({ email: 'Customer@Example.com', externalUserId: 'cust-9', firstName: 'Jan' }); const claims = decode(out.userJWT); assert.equal(claims.external_user_id, 'cust-9'); assert.equal(claims.email, 'customer@example.com'); assert.equal(claims.first_name, 'Jan'); assert.ok(claims.exp > Math.floor(Date.now() / 1000)); }); test('identity: site token mode verifies HS256 and resolves email via RPC', async () => { const siteToken = signHS256({ userId: 12345, type: 2, tenantId: 't1' }, 'site-secret', 60); const rpc = { calls: [], async call(addr, method, params) { this.calls.push({ addr, method, params }); return { result: { email: 'buyer@example.nl' } }; }, }; const identity = createIdentity( { libredeskInboxSecret: SECRET, identityDevMode: false, identityTtlSec: 60, siteJwtSecret: 'site-secret', memberRpcUrl: 'jsonrpc://member:1', rpcTimeoutMs: 1000, }, { rpc } ); const out = await identity.issue({ token: siteToken }); const claims = decode(out.userJWT); assert.equal(claims.external_user_id, '12345'); assert.equal(claims.email, 'buyer@example.nl'); assert.equal(rpc.calls[0].method, '/customer/getBasicByCustomerId'); assert.equal(rpc.calls[0].params[0].customerId, '12345'); }); test('identity: rejects bad site token and unknown origin mode', async () => { const identity = createIdentity( { libredeskInboxSecret: SECRET, identityDevMode: false, identityTtlSec: 60, siteJwtSecret: 'site-secret', memberRpcUrl: '', rpcTimeoutMs: 1000 }, { rpc: { call: async () => ({}) } } ); await assert.rejects(() => identity.issue({ token: 'not-a-jwt' }), /invalid or expired/); await assert.rejects(() => identity.issue({ email: 'x@y.z' }), /token is required/); });