User authorization
Before working with the chat, you must authorize the user. Without authorize(...), messages will not be sent.
The auth parameter is optional (ChatAuth?): pass null if custom server-side authorization is not used. The values of ChatAuth fields are coordinated with edna support.
Call authorize(...) after init(...), or after onInitComplete for initAsync (see Lifecycle).
If you use push, pass the FCM/HCM token via setFCMToken(...) / setHCMToken(...) before authorize(...) — the token will then be sent to the server immediately during device registration. See Notifications setup.
Main method
Minimal call (without custom server-side authorization):
chatCenterUI.authorize(
ChatUser(identifier = "YOUR_USER_UUID"),
null
)
Full form with all parameters:
import edna.chatcenter.core.ChatAuthType
import edna.chatcenter.core.config.ChatAuth
import edna.chatcenter.core.config.ChatUser
val accessTokenFromBackend: String? = "YOUR_ACCESS_TOKEN"
val signatureFromBackend: String? = "YOUR_SIGNATURE"
chatCenterUI.authorize(
ChatUser(
identifier = "YOUR_USER_UUID", // required — stable non-empty user ID
name = "John Doe", // optional
data = mapOf("department" to "support") // optional — data for the operator
),
ChatAuth(
token = accessTokenFromBackend,
scheme = "retail",
method = ChatAuthType.HEADERS, // HEADERS (default) or COOKIES
signature = signatureFromBackend,
isEncrypted = false // true if identifier is encrypted by your backend
)
)
ChatUser model
data class ChatUser(
val identifier: String,
val name: String? = null,
val data: Map<String, String>? = null
)
| Field | Type | Required | Description |
|---|---|---|---|
identifier | String | Yes | Unique, stable user ID |
name | String? | No | Display name for the operator |
data | Map<String, String>? | No | Arbitrary string data for the operator (see below) |
identifier contractAt the input, the SDK checks client.identifier.isNotBlank() and throws IllegalArgumentException for an empty string before any server request.
identifier must be unique, persistent, and resistant to guessing. Do not use phone numbers, emails, or other personal data in plaintext. If you cannot avoid them, use RSA encryption and set isEncrypted = true.
Recommended keys for data: Map<String, String>
The SDK passes data to the server unchanged — key handling is determined by the queue settings in edna and your backend. The names below are a convention for uniform interpretation.
| Key | Purpose | Example |
|---|---|---|
clientId | External client identifier in your CRM. | "7281" |
clientPhone | Phone in E.164 format (if allowed by policy). | "+71234567890" |
clientEmail | Client email. | "user@example.com" |
firstMessage | Text of the first message for auto-opening the dialog. The SDK passes the value as-is; auto-send is performed on the edna side and depends on queue settings. | "Hello, I have a question about order 12345" |
externalContacts | JSON string with additional contacts / routing markers. | """{"channel":"mobile_app"}""" |
department | Queue / department where the dialog should be routed. | "support" |
language | Preferred client language. | "en" |
Serialize structured data (e.g., externalContacts) as a JSON string.
ChatAuth model
| Field | Type | Required | Description |
|---|---|---|---|
token | String? | No | Authorization token issued by your backend |
scheme | String? | No | Authorization scheme |
method | ChatAuthType | No (default HEADERS) | How authorization data is transmitted |
signature | String? | No | Signature issued by your backend |
isEncrypted | Boolean | No (default false) | true if ChatUser.identifier is encrypted by your backend. The SDK does not encrypt anything itself — the flag only hints to the server how to interpret identifier |
ChatAuthType
| Value | Description |
|---|---|
HEADERS | token is sent in the HTTP Authorization header, scheme — in the additional X-Auth-Schema header (default) |
COOKIES | The same values are sent in the HTTP Cookie header as Authorization=<token>; X-Auth-Schema=<scheme> |
Complete example (Kotlin and Java)
The SDK passes token into the Authorization header unchanged — if your backend requires the Bearer prefix, add it yourself to the token value.
- Kotlin
- Java
val user = ChatUser(
identifier = "YOUR_USER_UUID",
data = mapOf("department" to "support")
)
val auth = ChatAuth(
token = "YOUR_ACCESS_TOKEN",
scheme = "retail",
signature = "YOUR_SIGNATURE"
)
chatCenterUI.authorize(user, auth)
import java.util.HashMap;
import java.util.Map;
import edna.chatcenter.core.config.ChatUser;
import edna.chatcenter.core.config.ChatAuth;
import edna.chatcenter.core.ChatAuthType;
import edna.chatcenter.ui.visual.core.ChatCenterUI;
Map<String, String> userData = new HashMap<>();
userData.put("department", "support");
ChatUser chatUser = new ChatUser(
"YOUR_USER_UUID",
null,
userData
);
ChatAuth chatAuth = new ChatAuth(
"YOUR_ACCESS_TOKEN",
"retail",
ChatAuthType.HEADERS,
"YOUR_SIGNATURE",
false
);
chatCenterUI.authorize(chatUser, chatAuth);
User data storage
The SDK stores session data in three different places — this affects what survives logout(), what ends up in cloud backup, and where push tokens live.
| # | File / location | Encryption | What is stored | Cleared by logout() |
|---|---|---|---|---|
| 1 | edna.chatcenter.ui.internal.utils.EncryptedPrefStore | EncryptedSharedPreferences AES256-SIV / AES256-GCM, MasterKey in the Android Keystore | Core SDK state: device_address, drafts, UI settings | ✅ Yes |
| 2 | edna.chatcenter.ui.eternal.utils.EncryptedPrefStore | Same encryption | device_uid, backup copy of FCM/HCM tokens (for migration and recovery) | ❌ No |
| 3 | edna.chatcenter.ui.cloudMessagesPreferences | No encryption (MODE_PRIVATE) | Active FCM/HCM push tokens | ❌ No |
| 4 | SQLite in-memory (DatabaseHolder) | — | Message history, files, statuses, quick replies | ✅ Yes (and automatically — on process termination) |
| 5 | RAM (ServiceLocator) | — | ChatUser, ChatAuth | ✅ Yes (also reset on process restart) |
Important implications for the integrator:
ChatUser/ChatAuthare not persisted across process restarts — after a restart, the app must callauthorize(...)again.- Message history lives only in process memory. After app kill / restart, it will be loaded from the server again on the next
authorize(...)— it does not remain on the device.
On devices with Android < 6.0 (API < 23), EncryptedSharedPreferences is unavailable: the SDK falls back to regular MODE_PRIVATE prefs without encryption. If your threat model requires no sensitive data on disk on older devices, account for this in minSdk.
The EncryptedSharedPreferences encryption key lives in the Android Keystore of a specific device and is not transferred via cloud backup. If the encrypted prefs end up in a backup, the SDK will not be able to decrypt them on restore — a crash on read. Exclusion rules for fullBackupContent and dataExtractionRules are in Advanced settings → App backup settings.
Logout
| Method | When to use |
|---|---|
logout() | User sign-out |
deauthorizeUser() | Sign-out from the authorized zone (PIN) |
logout() — full sign-out
Clears the local SDK DB and the main prefs storage (file #1 in the "User data storage" table) — device_address, drafts, UI settings. ChatUser / ChatAuth are removed from memory.
If the WebSocket connection is active, it additionally sends CLIENT_OFFLINE to the server and closes the socket. With an inactive connection, server notification and full cleanup are deferred until the next connection. In the special case where logout() is called during an active handshake (state REGISTERING_DEVICE), part of the cleanup happens immediately — the rest completes on the next reconnect.
The SDK does not send a separate REST request to unregister the device from push.
deauthorizeUser() — user reset only
Locally removes only ChatUser and ChatAuth. The DB and SharedPreferences are untouched, and the server-side session is not closed. Used for blocking the UI with a PIN without losing history; a repeated authorize(...) with the same identifier resumes the same session.
// Full local data cleanup
chatCenterUI.logout()
// Local removal of ChatUser/ChatAuth (the server-side session is not closed)
chatCenterUI.deauthorizeUser()
logout()logout() does not clear push tokens — they live in files #2 (...eternal.utils.EncryptedPrefStore) and #3 (...cloudMessagesPreferences) from the table above; neither is touched by the standard cleanup. On the next getFCMToken(), the SDK reads the token from the unencrypted file #3, and if absent, falls back to the encrypted file #2.
If your sign-out scenario requires "forgetting the device" completely, after logout():
- Invalidate the token on the push provider side:
FirebaseMessaging.getInstance().deleteToken()(FCM) or its HMS equivalent; - If needed, overwrite the token in the SDK with an empty string:
ChatCenterUI.setFCMToken("", context).
An SDK-side fix is on the roadmap; watch the Changelog.
When authorize(...) is called with a different identifier, the SDK initiates logout() of the previous user itself and defers the new registration until logout completes (internally, registration is automatically invoked again). So an explicit logout() before changing users is not required, but authorize() in this scenario returns control before registration has actually happened — observe the state via ChatCenterUIListener / ChatState if your app behavior depends on session readiness.