Customer identity
Log chat customers in with a JWT signed by your server so their conversations follow them across devices. Getting the signing secret, building the token, calling login on each SDK, describing customers, and logging out.
Chat starts anonymous: Kustomer knows the browser or device, not the person. When your user signs in to your site or app, log them in to chat too, so Kustomer attaches the conversation to their customer profile and shows them the same conversations on every device.
first chat message1. Visitor chats. Chat starts anonymous: Kustomer knows this browser, not the person. When the visitor first chats, Kustomer creates a customer for them, and the conversation lives on that anonymous customer.
- ◆event onConversationCreate
The token is signed with a secret only your server holds, so a visitor can't claim to be someone else, even though the chat key in your page is public.
1. Get the chat secret
The secret comes from an admin-only endpoint. Call it once and store the result in your server's secrets manager:
get/v1/auth/customer/settings
curl "https://acme.api.kustomerapp.com/v1/auth/customer/settings" \
-H "Authorization: Bearer $KUSTOMER_ADMIN_KEY"The key needs the org.admin.apps role, which org.admin includes. The secret is in the response at data.attributes.secret.
2. Sign a token
The JWT is signed with HS256 and has two claims:
import jwt from 'jsonwebtoken'
export function kustomerChatToken(user) {
return jwt.sign(
{ externalId: user.id, iat: Math.floor(Date.now() / 1000) },
process.env.KUSTOMER_CHAT_SECRET,
{ algorithm: 'HS256', header: { alg: 'HS256', typ: 'JWT' } },
)
}Serve it from an authenticated endpoint, for example POST /api/kustomer-token, and mint a fresh token each time: the 15-minute window means you can't cache them. A complete Express example is in kustomer/web-chat-sdk-samples.
3. Log in
Call login right after your user signs in, and skip it when isLoggedIn says they already are.
async function identifyChat(user) {
Kustomer.isLoggedIn({ externalId: user.id }, async function (loggedIn) {
if (loggedIn) return
const { token } = await fetch('/api/kustomer-token', { method: 'POST' }).then((r) => r.json())
Kustomer.login({ jwtToken: token }, function (res, error) {
if (error) return console.error(error)
console.log('Chat identified as', res.customerId)
})
})
}The response is { identified, customerId, email, externalId }, and the widget fires onLogin. With Core, use KustomerCore.login and KustomerCore.isLoggedIn the same way.
if !Kustomer.isLoggedIn(userEmail: nil, userId: user.id) {
Kustomer.logIn(jwt: tokenFromServer) { result in
if case .failure(let error) = result { print("Login failed: \(error)") }
}
}The identity is kept in the keychain across launches. A successful login clears the local conversation cache and rebuilds the chat UI.
val kustomer = Kustomer.getInstance()
if (kustomer.isLoggedIn(userId = user.id).dataOrNull != true) {
kustomer.logIn(tokenFromServer) { result ->
if (result is KusResult.Error) Log.e("Kustomer", "Login failed", result.exception)
}
}logIn also has a suspend overload. isLoggedIn(userEmail, userId) is synchronous.
if (!(await KustomerChat.isLoggedIn('userId', user.id))) {
await KustomerChat.logIn(tokenFromServer)
}Describe the customer
Once a customer is identified, add details agents should see. These write to the customer's profile in Kustomer.
Kustomer.describeCustomer(
{
attributes: { sharedPhones: ['+15555550123'] },
customAttributes: { loyaltyTierStr: 'gold', lifetimeValueNum: 1840 },
},
function (res, error) {},
)Kustomer.chatProvider.describeCurrentCustomer(
sharedPhones: ["+15555550123"],
custom: ["loyaltyTierStr": "gold", "lifetimeValueNum": 1840]
)Kustomer.getInstance().describeCustomer(
KusCustomerDescribeAttributes(
sharedPhones = listOf(KusPhone("+15555550123")),
custom = mapOf("loyaltyTierStr" to "gold", "lifetimeValueNum" to 1840),
),
) { }await KustomerChat.describeCustomer(
{ sharedPhones: ['+15555550123'] },
{ loyaltyTierStr: 'gold', lifetimeValueNum: 1840 },
)To set attributes on a conversation instead, use describeConversation with the conversation ID.
Log out
Log out of chat whenever your user signs out, so the next person on the device starts fresh:
Logging out clears the chat session and cached conversations from the device. It doesn't end or delete conversations in Kustomer.