Appearance
Identity verification
By default, anyone visiting your page is anonymous to the chat. To bind a chat to a real account in your system, sign the user's id with a per-widget secret on your server.
When to use
- You have a logged-in product and want to carry that identity into chat.
- You need returning visitors to land in the same conversation history across devices.
- You gate operator workflows on verified identity.
If your visitors are anonymous, skip this and use the Pre-chat form instead.
How it works
- Inviaro generates a
widget_secretper widget connection, stored encrypted at rest. You read it once from the admin and put it in your server's environment. - When rendering the page for a logged-in user, your server computes
user_hash = hmac_sha256(user_id, widget_secret)and embeds the digest in the page HTML. - The widget sends
user_idanduser_hashon every inbound message. - Inviaro recomputes the digest with the stored secret and compares timing-safely. On match, the contact is marked verified.
- On mismatch, the auth claim is silently dropped. Chat continues anonymously without an error to the visitor.
Server-side examples
Node
js
const crypto = require('node:crypto');
function inviaroUserHash(userId) {
if (!userId) throw new Error('userId required');
return crypto
.createHmac('sha256', process.env.INVIARO_WIDGET_SECRET)
.update(userId)
.digest('hex');
}
app.get('/api/me', (req, res) => {
const user = req.session.user;
res.json({
id: user.id,
email: user.email,
name: user.name,
inviaroUserHash: inviaroUserHash(user.id)
});
});PHP
php
function inviaro_user_hash(string $userId): string {
return hash_hmac('sha256', $userId, getenv('INVIARO_WIDGET_SECRET'));
}Python
python
import hmac, hashlib, os
def inviaro_user_hash(user_id: str) -> str:
secret = os.environ['INVIARO_WIDGET_SECRET'].encode()
return hmac.new(secret, user_id.encode(), hashlib.sha256).hexdigest()Ruby
ruby
require 'openssl'
def inviaro_user_hash(user_id)
OpenSSL::HMAC.hexdigest('sha256', ENV.fetch('INVIARO_WIDGET_SECRET'), user_id.to_s)
endGo
go
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"os"
)
func InviaroUserHash(userId string) string {
h := hmac.New(sha256.New, []byte(os.Getenv("INVIARO_WIDGET_SECRET")))
h.Write([]byte(userId))
return hex.EncodeToString(h.Sum(nil))
}Wiring the page
html
<script>
window.InviaroSettings = {
key: 'wt_...',
origin: 'https://yourdomain.com',
userId: '<%= current_user.id %>',
userHash: '<%= inviaro_user_hash(current_user.id) %>',
userEmail: '<%= current_user.email %>',
userName: '<%= current_user.name %>'
};
</script>
<script src="https://widget.inviaro.com/v1.js" async></script>Runtime updates
When a visitor logs in mid-session in a single-page app:
js
Inviaro('identify', {
userId: 'usr_42',
userHash: 'a1b2c3...',
email: 'amar@example.com',
name: 'Amar'
});When they log out:
js
Inviaro('logout');Security
- The
widget_secretlives only on your server. Never put it in client JavaScript. - Authenticate the request before signing. Never expose an unauthenticated endpoint that returns
user_hashfor arbitrary inputs. - Use a stable
user_id(UUID or database primary key). Treat it as a stable identifier, not an email or username. - Rotate the secret if it leaks. Old digests fail verification immediately.
WARNING
Do not compute the hash in client-side JavaScript. The secret would be extractable on first page load.
Verification result
When verification succeeds:
- The contact's
is_verifiedfield becomestruein the inbox. - Returning visits with the same
user_idare folded into the same contact, preserving conversation history across logins on different browsers or devices.
When verification fails:
- The contact stays anonymous.
- Chat itself continues working.
- A warning is logged server-side for your support team.