Identity & Authentication
mzchat uses a hierarchical cryptographic identity model rooted in Ed25519 keypairs. This ensures that a user’s identity is permanent and portable across servers, while allowing individual devices to be revoked or rotated.
Hierarchical Identity
Section titled “Hierarchical Identity”Root Identity ($K_{id}$)
Section titled “Root Identity ($K_{id}$)”The Root Identity is the canonical, permanent identifier for a user.
- Permanent ID: The Ed25519 public key of $K_{id}$ is the user’s immutable ID network-wide.
- Security: $K_{id}$ is never used for daily chat operations. Its sole purpose is to sign Device Certificates.
- Portability: By importing the $K_{id}$ seed, a user can authorize new devices on any server without losing their global identity.
Device Identities ($K_{dev}$)
Section titled “Device Identities ($K_{dev}$)”Every device generates its own ephemeral Ed25519 keypair.
- Access Control: Active network access is granted via a Device Certificate ($Cert_{dev}$), which is a statement signed by $K_{id}$ binding a $K_{dev}$ public key to a user ID for a specific duration.
- Hardware Isolation: $K_{dev}$ never leaves the device’s secure storage.
Hardware-Backed Security
Section titled “Hardware-Backed Security”On mobile platforms, mzchat leverages the system’s secure enclave (Keychain on iOS, Keystore on Android) to protect sensitive identity data.
Biometric Security
Section titled “Biometric Security”Users can opt-in to Biometric Security, which adds an additional layer of protection:
- Enclave Storage: The $K_{dev}$ secret key and $K_{id}$ (if present) are stored in the system’s hardware-backed secure storage.
- Access Control: Retrieval of these keys requires user authentication via Fingerprint, Face ID, or system PIN.
- Protection: This ensures that even if the mobile operating system is compromised, the cryptographic identity of the user remains inaccessible without physical user presence.
The Chain of Trust
Section titled “The Chain of Trust”Authentication follows a three-step cryptographic validation:
- Request Signature: The client signs a challenge (e.g., a timestamp) using its local $K_{dev}$.
- Certificate Binding: The client attaches the $Cert_{dev}$ signed by $K_{id}$.
- Root Validation: The server verifies that the $Cert_{dev}$ is validly signed by the $K_{id}$ corresponding to the
User.id, and that the request signature matches the public key embedded in the certificate.
This model allows for Offline Revocation: if a device is lost, the user can sign a revocation statement with $K_{id}$ that servers use to immediately invalidate the $Cert_{dev}$.
Session Lifecycle
Section titled “Session Lifecycle”Session state relies on synchronization between the issued JWT and the server’s current permission state.
Token Stale-on-Write
Section titled “Token Stale-on-Write”A token becomes stale whenever a user’s guild membership or role assignments change (e.g., after JoinInvite or CreateGuild).
- Protocol: RPCs that modify authorization state return a new JWT.
- Requirement: Clients must immediately replace their stored
auth_tokenwith the one returned in the response to ensure subsequent actions have the correct permissions.
Event Stream Authorization
Section titled “Event Stream Authorization”The real-time event stream (SubscribeEvents) is authorized at the moment of connection.
- Requirement: If the authentication state changes (new token), the client must abort and restart the event stream. The server does not dynamically update permissions for an established stream.
Refresh Tokens
Section titled “Refresh Tokens”To support long-lived sessions while keeping access tokens short-lived (e.g., 24 hours), mzchat uses Refresh Tokens.
- Issuance: Upon
Register,Login, orJoinInvite, the server returns arefresh_tokenalongside thetoken. - Storage: Clients must store the
refresh_tokensecurely (e.g., localStorage). - Usage: When an API request fails with
Unauthenticated, the client attempts to use theRefreshRPC with therefresh_tokento obtain a new access token. - Rotation: The
RefreshRPC rotates the refresh token. The client must replace the old refresh token with the new one returned in the response. - Revocation: Refresh tokens are stored in the database and can be revoked by deleting the corresponding row. They are linked to a user and device ID.