@@ -19,13 +19,20 @@ const {
1919 mockSetDeploymentAuthCookie,
2020 mockAddCorsHeaders,
2121 mockIsEmailAllowed,
22+ mockGetSession,
2223} = vi . hoisted ( ( ) => ( {
2324 mockMergeSubblockStateWithValues : vi . fn ( ) . mockReturnValue ( { } ) ,
2425 mockMergeSubBlockValues : vi . fn ( ) . mockReturnValue ( { } ) ,
2526 mockValidateAuthToken : vi . fn ( ) . mockReturnValue ( false ) ,
2627 mockSetDeploymentAuthCookie : vi . fn ( ) ,
2728 mockAddCorsHeaders : vi . fn ( ( response : unknown ) => response ) ,
2829 mockIsEmailAllowed : vi . fn ( ) ,
30+ mockGetSession : vi . fn ( ) ,
31+ } ) )
32+
33+ vi . mock ( '@/lib/auth' , ( ) => ( {
34+ auth : { api : { getSession : vi . fn ( ) } } ,
35+ getSession : mockGetSession ,
2936} ) )
3037
3138const mockDecryptSecret = encryptionMockFns . mockDecryptSecret
@@ -285,6 +292,68 @@ describe('Chat API Utils', () => {
285292 expect ( result3 . authorized ) . toBe ( false )
286293 expect ( result3 . error ) . toBe ( 'Email not authorized' )
287294 } )
295+
296+ describe ( 'SSO auth' , ( ) => {
297+ const ssoDeployment = {
298+ id : 'chat-id' ,
299+ authType : 'sso' ,
300+ allowedEmails : [ 'user@example.com' , '@company.com' ] ,
301+ }
302+
303+ const postRequest = {
304+ method : 'POST' ,
305+ cookies : { get : vi . fn ( ) . mockReturnValue ( null ) } ,
306+ } as any
307+
308+ it ( 'rejects when no session is present' , async ( ) => {
309+ mockGetSession . mockResolvedValue ( null )
310+
311+ const result = await validateChatAuth ( 'request-id' , ssoDeployment , postRequest , {
312+ input : 'hello' ,
313+ } )
314+
315+ expect ( result . authorized ) . toBe ( false )
316+ expect ( result . error ) . toBe ( 'auth_required_sso' )
317+ } )
318+
319+ it ( 'ignores body-supplied email and uses the session email' , async ( ) => {
320+ mockGetSession . mockResolvedValue ( { user : { email : 'session@example.com' } } )
321+ mockIsEmailAllowed . mockReturnValue ( true )
322+
323+ await validateChatAuth ( 'request-id' , ssoDeployment , postRequest , {
324+ email : 'attacker@evil.com' ,
325+ input : 'hello' ,
326+ } )
327+
328+ expect ( mockIsEmailAllowed ) . toHaveBeenCalledWith (
329+ 'session@example.com' ,
330+ ssoDeployment . allowedEmails
331+ )
332+ } )
333+
334+ it ( 'authorizes execution when session email is allowlisted' , async ( ) => {
335+ mockGetSession . mockResolvedValue ( { user : { email : 'user@example.com' } } )
336+ mockIsEmailAllowed . mockReturnValue ( true )
337+
338+ const result = await validateChatAuth ( 'request-id' , ssoDeployment , postRequest , {
339+ input : 'hello' ,
340+ } )
341+
342+ expect ( result . authorized ) . toBe ( true )
343+ } )
344+
345+ it ( 'rejects execution when session email is not allowlisted' , async ( ) => {
346+ mockGetSession . mockResolvedValue ( { user : { email : 'stranger@other.com' } } )
347+ mockIsEmailAllowed . mockReturnValue ( false )
348+
349+ const result = await validateChatAuth ( 'request-id' , ssoDeployment , postRequest , {
350+ input : 'hello' ,
351+ } )
352+
353+ expect ( result . authorized ) . toBe ( false )
354+ expect ( result . error ) . toBe ( 'Your email is not authorized to access this chat' )
355+ } )
356+ } )
288357 } )
289358
290359 describe ( 'Execution Result Processing' , ( ) => {
0 commit comments