Authentication
Realtime V3 uses Inline Protocol authorization keys. A permanent key is associated with an account session after login. A temporary key carries ordinary application traffic only after the server binds it to an authorized permanent key. These keys are secret credentials; the production RSA ring contains public verification keys, not account credentials. This page covers V3 credential ownership. Realtime V2, Bot API tokens, and MCP OAuth use separate authentication paths.
About this page
For V3 client authors implementing login and a protected credential store. You need a trusted server key ring, an account able to complete login, and storage that coordinates rotation with logout. Follow creation → binding → persistence → revocation; the outcome is authorized application access with recoverable credentials.
Applies to: Realtime V3; TypeScript SDK. See the version and example baseline before choosing a package.
Figure: Application access begins after login and temporary-key binding.
permanent handshake → login authorized ──────────────┐
├→ bind → application RPCs
temporary handshake ────────────────────────────────┘The two handshakes establish separate keys. Binding joins temporary traffic authority to the account session established through the permanent key.
Create and authorize a permanent key
- Start a V3 handshake using a trusted, pinned server RSA public-key ring. The handshake creates a permanent authorization key and a server salt. It does not sign the user in.
- On that encrypted permanent-key connection, start a login. Native login uses
authBeginwith an email address or phone number and returns a challenge ID, delivery channel, expiry, and retry delay. Complete it withauthComplete(challenge_id, code, ...). The response is eitherauthorizedorinvite_required; handle both states. Hosted browser login is a separateauthBeginBrowserandauthBrowserStatusflow bound to the same permanent key. - Treat
authorizedas the point at which the server associates the permanent key with a user and account session. Login errors, an expired challenge, orinvite_requireddo not grant ordinary RPC access.
The login request and result messages define the fields. The TypeScript V3 client exposes beginLogin and completeLogin; the server auth operations enforce the permanent-key requirement.
Bind a temporary key
Create a fresh temporary key with a V3 handshake, then prove possession of the permanent key when binding it. The proof includes the temporary authorization key, session, nonce, and expiry. The server accepts application RPCs only after it has bound the temporary key to the authorized user's account session. A cryptographically valid but unbound temporary key cannot call ordinary RPCs.
Temporary keys have a 24-hour lifetime. The TypeScript and Rust clients treat 80% of that lifetime, measured against authenticated server time, as the rotation boundary. At that boundary, stop admitting new application work, make a fresh temporary key, bind it, and reconnect. A stored temporary key is probed on reconnect before reuse; an invalidated key is replaced through the permanent authority. If the permanent key or account session is revoked, replace credentials through login rather than retrying the old key.
Persist credentials
Persist the permanent key and any bound temporary key in a protected credential store.
The exported InlineProtocolV3Credentials type requires permanent: InlineProtocolAuthorization and accepts optional temporary: InlineProtocolAuthorization. Import it from @inline-chat/realtime-sdk; the canonical declaration defines the complete shape.
InlineProtocolAuthorization contains the secret key bytes, key ID, server salt, temporary flag, and optional expiry. The high-level InlineSdkClient selects V3 through inlineProtocol: { credentials, onCredentials }. Its onCredentials callback must persist a replacement credential set before the SDK makes the replacement authenticated session visible. The storage owner must reject a late write after logout begins; otherwise an in-flight rotation can restore credentials that logout removed. See the SDK credential options and V3 transport rotation path.
Do not log authorization-key bytes or serialize them into diagnostics. Closing a client connection disposes that connection; it does not revoke or clear durable credentials.
Revoke and recover
The high-level TypeScript SDK's logout() requires a durable credentialOwner. It attempts remote LOG_OUT, closes the client, and clears host-owned local credentials even when the remote outcome cannot be confirmed. Its result distinguishes confirmed, notSent, and commitUnknown; commitUnknown means the remote revocation must not be assumed. The SDK logout contract and result type define these outcomes.
On the server, revoking a permanent authorization invalidates its bound temporary keys; an expired temporary key is removed from the temporary-key store. Application dispatch also checks the current key binding and account session. See the authorization-key store and application admission. Keep local credential erasure and confirmed remote revocation distinct when reporting logout to a user.
For carrier and record details, see Protocol. For reconnect outcomes and mutation retries, see Realtime and RPC semantics.
Summary
A handshake creates a key; login grants permanent authority; binding admits temporary-key traffic. Persist replacements before use. Report local erasure separately from remote revocation, and use RPC outcome rules when logout completion is uncertain.