Skip to content

Commit f63cd9f

Browse files
authored
Merge pull request #2 from chatbotkit/next
Release template-chat-auth
2 parents 7ecdd1e + 40c6efc commit f63cd9f

File tree

1 file changed

+44
-1
lines changed

1 file changed

+44
-1
lines changed

actions/conversation.jsx

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,51 @@ import authOptions from '@/lib/auth-options'
77
import { streamComplete } from '@chatbotkit/react/actions/complete'
88
import { ChatBotKit } from '@chatbotkit/sdk'
99

10+
import crypto from 'node:crypto'
11+
1012
const cbk = new ChatBotKit({
1113
secret: process.env.CHATBOTKIT_API_SECRET,
1214
})
1315

16+
/**
17+
* @note Namespace for generating deterministic UUID v5 fingerprints from user
18+
* emails. This ensures the same email always produces the same fingerprint
19+
* without leaking PII.
20+
*/
21+
const CONTACT_NAMESPACE = 'e676f123-b5eb-4c44-a80b-8aa0e723cfe6'
22+
23+
/**
24+
* Generates a deterministic UUID v5 from an email address and namespace.
25+
*
26+
* @param {string} email - The email to derive a fingerprint from
27+
* @returns {string} A deterministic UUID v5 string
28+
*/
29+
function generateFingerprint(email) {
30+
const namespaceBytes = Buffer.from(CONTACT_NAMESPACE.replace(/-/g, ''), 'hex')
31+
32+
const hash = crypto
33+
.createHash('sha1')
34+
.update(namespaceBytes)
35+
.update(email.toLowerCase())
36+
.digest()
37+
38+
// Set version to 5 (SHA-1 based)
39+
hash[6] = (hash[6] & 0x0f) | 0x50
40+
41+
// Set variant to RFC 4122
42+
hash[8] = (hash[8] & 0x3f) | 0x80
43+
44+
const hex = hash.toString('hex').slice(0, 32)
45+
46+
return [
47+
hex.slice(0, 8),
48+
hex.slice(8, 12),
49+
hex.slice(12, 16),
50+
hex.slice(16, 20),
51+
hex.slice(20, 32),
52+
].join('-')
53+
}
54+
1455
/**
1556
* Parses the CHATBOTKIT_BOT_IDS environment variable into an array of bot IDs.
1657
*
@@ -45,14 +86,16 @@ async function requireSession() {
4586
/**
4687
* Ensures a ChatBotKit contact exists for the authenticated user.
4788
*
48-
* Uses the user's email as a stable identifier via `contact.ensure()`.
89+
* Generates a deterministic UUID v5 fingerprint from the user's email so the
90+
* fingerprint is stable and doesn't leak raw PII.
4991
*
5092
* @returns {Promise<string>} The contact ID
5193
*/
5294
export async function ensureContact() {
5395
const session = await requireSession()
5496

5597
const { id } = await cbk.contact.ensure({
98+
fingerprint: generateFingerprint(session.user.email),
5699
email: session.user.email,
57100
name: session.user.name || '',
58101
})

0 commit comments

Comments
 (0)