אימות זהות
זהו אדם מחובר ושחזרו את היסטוריית השיחות שלו בין מכשירים, באמצעות חתימה שה-backend שלכם שולט בה.
למה לאמת#
כברירת מחדל ה-SDK אנונימי: הוא מייצר visitor_id יציב ושומר אותו ב-keystore של הפלטפורמה. זה מספיק לשיחה אחת במכשיר אחד. כדי לזהות משתמש מסוים, לשחזר היסטוריה בהתחברות מחדש או במכשיר אחר, ולקשור באופן אמין שיחה לפרופיל איש קשר, ה-backend צריך הוכחה שהלקוח הוא מי שהוא טוען שהוא. אם ה-SDK פשוט היה שולח "אני משתמש 42", כל אחד יכול היה להתחזות למזהה אחר ולקרוא צ׳אט של מישהו אחר — ולכן Respondo דורש חתימה קריפטוגרפית, userHash, שרק ה-backend שלכם יכול לייצר.
קבלת סוד הזהות#
ה-identity_secret הוא מחרוזת סודית הקשורה לסוכן שלכם (עובד ה-AI שאליו מחובר ערוץ הווידג׳ט שלכם). צרו אותו בלוח הבקרה תחת Channels → Widget → Identity verification. מכיוון שהוא יושב על הסוכן, כל ערוץ שמבוסס על אותו סוכן — גם וידג׳ט הווב וגם ה-SDK הנייד — חולק את אותו סוד. הוא מעניק את הזכות לחתום על זהויות, ולכן הוא חייב להתקיים רק ב-backend שלכם ולעולם אסור שיישלח באפליקציה.
נוסחת ה-userHash#
userHash הוא HMAC-SHA256 על מחרוזת זהות חתומה אחת, מקודד כ-hex באותיות קטנות:
userHash = HMAC_SHA256( identity_secret, payload )
payload = userId // אם userId מוגדר
= email // אחרת, אם email מוגדר
= (invalid) // אם שניהם ריקים, אין מה לחתום- הסוד הוא ה-מפתח של ה-HMAC; מחרוזת הזהות היא ה- הודעה — לא להפך.
- חתמו על מחרוזת אחת בדיוק — ה-
userIdהגולמי (או האימייל), ללא salt וללא עטיפת JSON. - אם אתם מעבירים גם
userIdוגם email, חתמו על ה-userId(יש לו עדיפות). - הפלט הוא hex (64 תווים עבור SHA-256), לא base64.
דוגמאות צד שרת#
חשבו את החתימה ב-backend שלכם ומסרו את ה- userHash המוכן לאפליקציה.
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
)
// HMAC_SHA256(identity_secret, userId) כ-hex באותיות קטנות.
func ComputeUserHash(identitySecret, userID string) string {
mac := hmac.New(sha256.New, []byte(identitySecret))
mac.Write([]byte(userID))
return hex.EncodeToString(mac.Sum(nil))
}const crypto = require("crypto");
// מחזירה את ה-userHash שיש להעביר ל-Respondo.identify בלקוח הנייד.
function computeUserHash(identitySecret, userId) {
return crypto
.createHmac("sha256", identitySecret)
.update(userId, "utf8")
.digest("hex");
}import hmac
import hashlib
# מחזירה את ה-userHash שיש להעביר ל-Respondo.identify בלקוח הנייד.
def compute_user_hash(identity_secret: str, user_id: str) -> str:
return hmac.new(
identity_secret.encode(),
user_id.encode(),
hashlib.sha256,
).hexdigest()<?php
// מחזירה את ה-userHash שיש להעביר ל-Respondo.identify בלקוח הנייד.
function computeUserHash(string $identitySecret, string $userId): string {
return hash_hmac('sha256', $userId, $identitySecret);
}כיצד ה-hash מגיע ל-Respondo#
/identity שצריך לקרוא לו ואין מה לרשום. userHash הוא שדה שנוסע בתוך הבקשות שה-SDK כבר שולח.שני מקטעים, ורק הראשון הוא באחריותכם לבנות:
- ה-backend שלכם → האפליקציה שלכם. אתם מוסרים את ה-hash בכל דרך שנוחה לכם. הזול ביותר הוא שדה נוסף בתשובת ההתחברות/האתחול שאתם ממילא מחזירים — בלי סבב בקשות נוסף. endpoint ייעודי ב-backend שלכם (למשל
POST /myapp/identityשמחזיר{ userId, userHash }) עובד באותה מידה. Respondo לא מארחת את ה-endpoint הזה — אתם מממשים אותו. - האפליקציה שלכם → Respondo. מטופל עבורכם. ברגע שאתם קוראים ל-
identify, ה-SDK מצרף את ה-hash לכל בקשה רלוונטית וה-backend מאמת אותו מחדש בכל פעם.
POST /api/v1/chat body identity.userHash
GET /api/v1/chat/resume query user_hash
GET /api/v1/chat/history query user_hash
GET /api/v1/chat/ws frames user_hash (subscribe/identify JSON frames after connect — not in the handshake URL)
GET /api/v1/widget/tours query user_hash
GET /api/v1/widget/checklists query user_hash
POST /api/v1/widget/push/register body user_hashה-hash נבדק מחדש בכל בקשה, ולא מוחלף פעם אחת עבור סשן שלם — בדיוק זה מה שהופך userId גנוב לחסר תועלת בפני עצמו.
identify לעולם לא נקרא, והצ׳אט רץ אנונימית. זו התנהגות צפויה ולא שגיאה של Respondo — 404 בנתיב שלכם הוא משימה פתוחה בצד שלכם, לא אינטגרציה שבורה.העברת הזהות ל-SDK#
משכו את הזהות החתומה מה-backend שלכם, ואז העבירו את ה- userHash אל identify בכל פלטפורמה:
Respondo.identify(
RespondoIdentity(userId = "42", email = "user@example.com", userHash = hash),
)Respondo.identify(
RespondoIdentity(userId: "42", email: "user@example.com", userHash: hash)
)Respondo.identify(RespondoIdentity(
userId: '42', email: 'user@example.com', userHash: hash,
));התנהגות עם userHash שגוי#
כאשר האימות מופעל על הסוכן והחתימה חסרה או שגויה, ה-backend מבצע הורדה שקטה למצב אנונימי: הצ׳אט עדיין עובד, ה- visitor_id נשמר, והשיחה נקשרת לאיש הקשר האנונימי — אך אין קישור לפרופיל ואין היסטוריה חוצה-מכשירית. אם משתמש "אינו מזוהה", כמעט תמיד מדובר בחתימה: בדקו שחתמתם על ה- userId (לא אימייל או JSON), השתמשתם ב- identity_secret הנכון, והפקתם hex באותיות קטנות. אם ה- identity_secret של הסוכן ריק, האימות כבוי ו- userId / אימייל מתקבלים כמות שהם.
החלפת ה- identity_secret היא למעשה מעבר חד: כל hash שהופק עם הסוד הישן מפסיק להתאמת מיידית, כך שמשתמשים שכבר מחוברים נופלים בשקט למצב אנונימי עד שה-backend שלכם מחשב מחדש ומספק שוב את ה- userHash שלהם עם הסוד החדש. החליפו את הסוד רק כאשר תוכלו לעדכן את צד החתימה באותו חלון זמן.