Skip to main content
Version: 5.21.0

User authorization

Before working with the chat, you must authorize the user. Without authorize(...), messages will not be sent.

Call order

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
)
FieldTypeRequiredDescription
identifierStringYesUnique, stable user ID
nameString?NoDisplay name for the operator
dataMap<String, String>?NoArbitrary string data for the operator (see below)
identifier contract

At the input, the SDK checks client.identifier.isNotBlank() and throws IllegalArgumentException for an empty string before any server request.

danger

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.

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.

KeyPurposeExample
clientIdExternal client identifier in your CRM."7281"
clientPhonePhone in E.164 format (if allowed by policy)."+71234567890"
clientEmailClient email."user@example.com"
firstMessageText 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"
externalContactsJSON string with additional contacts / routing markers."""{"channel":"mobile_app"}"""
departmentQueue / department where the dialog should be routed."support"
languagePreferred client language."en"

Serialize structured data (e.g., externalContacts) as a JSON string.

ChatAuth model

FieldTypeRequiredDescription
tokenString?NoAuthorization token issued by your backend
schemeString?NoAuthorization scheme
methodChatAuthTypeNo (default HEADERS)How authorization data is transmitted
signatureString?NoSignature issued by your backend
isEncryptedBooleanNo (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

ValueDescription
HEADERStoken is sent in the HTTP Authorization header, scheme — in the additional X-Auth-Schema header (default)
COOKIESThe 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.

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)

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 / locationEncryptionWhat is storedCleared by logout()
1edna.chatcenter.ui.internal.utils.EncryptedPrefStoreEncryptedSharedPreferences AES256-SIV / AES256-GCM, MasterKey in the Android KeystoreCore SDK state: device_address, drafts, UI settings✅ Yes
2edna.chatcenter.ui.eternal.utils.EncryptedPrefStoreSame encryptiondevice_uid, backup copy of FCM/HCM tokens (for migration and recovery)❌ No
3edna.chatcenter.ui.cloudMessagesPreferencesNo encryption (MODE_PRIVATE)Active FCM/HCM push tokens❌ No
4SQLite in-memory (DatabaseHolder)Message history, files, statuses, quick replies✅ Yes (and automatically — on process termination)
5RAM (ServiceLocator)ChatUser, ChatAuth✅ Yes (also reset on process restart)

Important implications for the integrator:

  • ChatUser / ChatAuth are not persisted across process restarts — after a restart, the app must call authorize(...) 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.
API < 23 — no encryption

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.

Backup and device-to-device transfer

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

MethodWhen 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()
FCM/HCM tokens and 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.

Changing the user

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.