/** @jest-environment node */ import { createHash } from 'crypto' import { consumeDingtalkSessionTicket, createDingtalkSessionTicket, } from '@/lib/dingtalk-session-ticket' describe('DingTalk one-time session ticket', () => { const originalUseRedis = process.env.USE_REDIS const originalRedisUrl = process.env.REDIS_URL beforeEach(() => { process.env.USE_REDIS = 'false' delete process.env.REDIS_URL }) afterAll(() => { if (originalUseRedis === undefined) delete process.env.USE_REDIS else process.env.USE_REDIS = originalUseRedis if (originalRedisUrl === undefined) delete process.env.REDIS_URL else process.env.REDIS_URL = originalRedisUrl }) test('必须匹配原内网地址和浏览器绑定值,且只能消费一次', async () => { const binding = 'binding-for-original-browser' const ticketId = await createDingtalkSessionTicket({ userId: 'user-1', redirectPath: '/admin?tab=users', targetOrigin: 'http://192.168.58.20:4320', handoffId: 'handoff-1', handoffBindingHash: createHash('sha256').update(binding).digest('hex'), }) await expect( consumeDingtalkSessionTicket(ticketId, { expectedTargetOrigin: 'http://192.168.58.20:4320', expectedHandoffBinding: 'other-browser-binding', }), ).resolves.toBeNull() await expect( consumeDingtalkSessionTicket(ticketId, { expectedTargetOrigin: 'http://192.168.58.20:4321', expectedHandoffBinding: binding, }), ).resolves.toBeNull() await expect( consumeDingtalkSessionTicket(ticketId, { expectedTargetOrigin: 'http://192.168.58.20:4320', expectedHandoffBinding: binding, }), ).resolves.toMatchObject({ userId: 'user-1', redirectPath: '/admin?tab=users', targetOrigin: 'http://192.168.58.20:4320', }) await expect( consumeDingtalkSessionTicket(ticketId, { expectedTargetOrigin: 'http://192.168.58.20:4320', expectedHandoffBinding: binding, }), ).resolves.toBeNull() }) test('现有仅写 Cookie 的会话票据仍能正常消费', async () => { const ticketId = await createDingtalkSessionTicket({ redirectPath: '/performance-survey', cookies: ['next-auth.session-token=test-token; Path=/; HttpOnly'], }) await expect(consumeDingtalkSessionTicket(ticketId)).resolves.toMatchObject({ redirectPath: '/performance-survey', cookies: ['next-auth.session-token=test-token; Path=/; HttpOnly'], }) }) })