1+ import { createHash } from 'crypto'
12import { db } from '@sim/db'
23import { chat , workflow } from '@sim/db/schema'
34import { eq } from 'drizzle-orm'
@@ -9,6 +10,10 @@ import { hasAdminPermission } from '@/lib/workspaces/permissions/utils'
910
1011const logger = createLogger ( 'ChatAuthUtils' )
1112
13+ function hashPassword ( encryptedPassword : string ) : string {
14+ return createHash ( 'sha256' ) . update ( encryptedPassword ) . digest ( 'hex' ) . substring ( 0 , 8 )
15+ }
16+
1217/**
1318 * Check if user has permission to create a chat for a specific workflow
1419 * Either the user owns the workflow directly OR has admin permission for the workflow's workspace
@@ -77,43 +82,61 @@ export async function checkChatAccess(
7782 return { hasAccess : false }
7883}
7984
80- const encryptAuthToken = ( chatId : string , type : string ) : string => {
81- return Buffer . from ( `${ chatId } :${ type } :${ Date . now ( ) } ` ) . toString ( 'base64' )
85+ function encryptAuthToken ( chatId : string , type : string , encryptedPassword ?: string | null ) : string {
86+ const pwHash = encryptedPassword ? hashPassword ( encryptedPassword ) : ''
87+ return Buffer . from ( `${ chatId } :${ type } :${ Date . now ( ) } :${ pwHash } ` ) . toString ( 'base64' )
8288}
8389
84- export const validateAuthToken = ( token : string , chatId : string ) : boolean => {
90+ export function validateAuthToken (
91+ token : string ,
92+ chatId : string ,
93+ encryptedPassword ?: string | null
94+ ) : boolean {
8595 try {
8696 const decoded = Buffer . from ( token , 'base64' ) . toString ( )
87- const [ storedId , _type , timestamp ] = decoded . split ( ':' )
97+ const parts = decoded . split ( ':' )
98+ const [ storedId , _type , timestamp , storedPwHash ] = parts
8899
89100 if ( storedId !== chatId ) {
90101 return false
91102 }
92103
93104 const createdAt = Number . parseInt ( timestamp )
94105 const now = Date . now ( )
95- const expireTime = 24 * 60 * 60 * 1000 // 24 hours
106+ const expireTime = 24 * 60 * 60 * 1000
96107
97108 if ( now - createdAt > expireTime ) {
98109 return false
99110 }
100111
112+ if ( encryptedPassword ) {
113+ const currentPwHash = hashPassword ( encryptedPassword )
114+ if ( storedPwHash !== currentPwHash ) {
115+ return false
116+ }
117+ }
118+
101119 return true
102120 } catch ( _e ) {
103121 return false
104122 }
105123}
106124
107- export const setChatAuthCookie = ( response : NextResponse , chatId : string , type : string ) : void => {
108- const token = encryptAuthToken ( chatId , type )
125+ export function setChatAuthCookie (
126+ response : NextResponse ,
127+ chatId : string ,
128+ type : string ,
129+ encryptedPassword ?: string | null
130+ ) : void {
131+ const token = encryptAuthToken ( chatId , type , encryptedPassword )
109132 response . cookies . set ( {
110133 name : `chat_auth_${ chatId } ` ,
111134 value : token ,
112135 httpOnly : true ,
113136 secure : ! isDev ,
114137 sameSite : 'lax' ,
115138 path : '/' ,
116- maxAge : 60 * 60 * 24 , // 24 hours
139+ maxAge : 60 * 60 * 24 ,
117140 } )
118141}
119142
@@ -145,7 +168,7 @@ export async function validateChatAuth(
145168 const cookieName = `chat_auth_${ deployment . id } `
146169 const authCookie = request . cookies . get ( cookieName )
147170
148- if ( authCookie && validateAuthToken ( authCookie . value , deployment . id ) ) {
171+ if ( authCookie && validateAuthToken ( authCookie . value , deployment . id , deployment . password ) ) {
149172 return { authorized : true }
150173 }
151174
0 commit comments