Authentication
Auth is always on. A fresh installation already requires a credential: out of the box the master key is the dev value meow and the JWT secret is meow_jwt, so the project works immediately but is never silently wide open.
Going to production is changing those two defaults in your config.py:
API_KEY = "a-very-long-and-alphanumeric-secret"JWT_SECRET = "yet-another-very-long-and-alphanumeric-secret"That is the whole story. The rest of this page explains what each one does.
The two credentials
Section titled “The two credentials”Every request is authenticated from a single credential, sent as an Authorization: Bearer <credential> header (or an access_token cookie in the browser). That credential is one of two things:
| Credential | Who it is | Use for |
|---|---|---|
Master API key (API_KEY) |
The admin user | Machine-to-machine calls |
| JWT | Any user, with their roles | Browsers and per-user sessions |
Master API key
Section titled “Master API key”API_KEY maps to a single, all-powerful admin user. Send it as-is:
let response = await fetch("http://localhost:1865/me", { headers: { "Authorization": "Bearer meow" }})console.log(response.status, await response.json())import requests
response = requests.get( "http://localhost:1865/me", headers={"Authorization": "Bearer meow"},)print(response.status_code, response.json())Without a valid credential you get:
403 {"detail": "Invalid Credentials"}A JSON Web Token is a short-lived, per-user credential. It carries the user id and their roles, so no shared secret ever reaches the browser, and a stolen token expires on its own (JWT_EXPIRE_MINUTES, default 1 day).
The Cat verifies JWTs it signed with JWT_SECRET. It does not ship a built-in username/password login: minting a token is a login flow, and login flows are plugins. The simple_oauth plugin is the reference OAuth login you clone and point at Google, Auth0 or your own identity provider. Once logged in, the token is set as the access_token cookie and every following request is authenticated as that user.
Securing custom endpoints
Section titled “Securing custom endpoints”Endpoints you add in plugins are open by default. Gate them by role right on the decorator:
from cat import endpoint, user
@endpoint.get("/admin/stuff", role="admin")async def stuff(): return {"hi": user.name}See Authorization for the role= semantics.
Use secure protocols
Section titled “Use secure protocols”The final step is putting the Cat behind a reverse proxy with automatic TLS. Most open-source proxies manage certificates for you via Let’s Encrypt. Set HTTPS_PROXY_MODE = True in config.py so redirects behave correctly behind the proxy.