A credential is anything that proves who is making a request. Livqeno uses four kinds. Each has its own job, and none can create or pretend to be another. Knowing which is which is the key to keeping your app safe.
In a normal app, they flow like this:
- You log in to the dashboard (a dashboard session) and create an API key.
- Your backend stores the API key and uses it to make tokens.
- Your users' apps get only a chat token or an RTC token, for one user and a short time.
| Credential | Used by | Gives access to |
|---|---|---|
| Dashboard login (session) | A developer | Their whole account |
| Project API key | Your backend | One project, in one environment |
| Chat token | One user | Chat, for a short time |
| RTC token | One participant | One room |
Each one is signed or stored differently. Chat tokens also carry a fixed
aud: "raven-chat", so a dashboard login can never be reused on chat.
Your app can't pretend to be another user
For every write, Livqeno takes the user's identity from the signed credential, never from the request body.
For example, alice opens her browser's dev tools and edits a chat request
to send a message as bob:
- If a browser sends
senderId: 'someone-else', there's no error. The value is just ignored. The message is still saved as fromalice, because her chat token says she isalice. - Your server (with the API key) can act for any user. That's how your backend posts on someone's behalf, and it's why the API key must never reach a browser. See Authentication.
Two checks on every request
When a user's app asks to do something in chat (like post in a conversation), both checks must pass:
- What the token allows. Its scopes come from a role and can only be made smaller, never bigger.
- What the user is a member of. Checked on the server every time. A list cached in the client is never trusted.
See Chat → Authorization and Roles & Permissions.
How secrets are stored
- API key secrets are hashed, never stored as plain text, and can't be recovered. You see them once.
- Webhook signing secrets and moderation-hook secrets are stored encrypted with AES-256-GCM (we need them to sign deliveries), and never shown again after you create them.
- Dashboard passwords are hashed with bcrypt. Two-factor seeds are encrypted the same way as signing secrets, and recovery codes are stored only as hashes.
- Server SDKs keep the API key in a private field. It never shows up in
JSON.stringify(),repr(),toString(),var_dump(), logs, or error messages. See the TypeScript, Python, Go, Java and PHP SDKs.
Dashboard accounts
-
Two-factor authentication. Turn on an authenticator app under Settings → Security. Sign-in then asks for a 6-digit code (or one of ten single-use recovery codes) after your password or GitHub/Google sign-in. Each code is accepted once, and a sign-in attempt ends after five wrong codes. Turning two-factor off needs a current code and your password.
-
Require it per project. Owners and admins can turn on Require two-factor authentication in project settings. Members without it are refused on every project page and API route until they turn it on.
-
Every session ends when it should. Signing out ends that session. Resetting your password ends every session of the account. A suspended account loses its sessions and its projects' API keys at once.
-
Storage credentials never reach the browser. The browser gets a signed URL for one file, valid for a few minutes.
-
Files are stored under random names, never the name the user uploaded. This blocks path-traversal tricks.
See Attachments.
Known limitation: webhook URLs
A webhook URL is the address on your backend where Livqeno sends events.
Livqeno blocks webhook URLs that obviously point at internal addresses. But it does not look up DNS, so a hostname that points to a private IP still gets through. See Webhooks → Security.
Reporting a vulnerability
Email security@livqeno.com with what you found. It stays private between you and the Livqeno security team. We'll follow up with next steps, and thank you once a fix ships.
No reply within a couple of business days? Send a follow-up. Your first email probably didn't arrive.
Next steps
- Security (authentication): what to do in your own code: where to store keys, how to mint tokens safely.
- Browser security & CORS: allowed origins for web apps.
- Production checklist: the security items to tick before launch.