Skip to content

Authentication Backends

Dashboard authentication is pluggable through the AuthBackend protocol.

Auth Flow

sequenceDiagram
    participant U as User Browser
    participant M as AuthGateMiddleware
    participant B as AuthBackend
    participant A as Dashboard App

    U->>M: HTTP request
    M->>B: authenticate(request)
    alt authenticated
        B-->>M: user
        M->>A: forward request
        A-->>U: page response
    else not authenticated
        B-->>M: None
        M-->>U: redirect /login (or HX-Redirect)
    end

JWTAuthBackend

JWTAuthBackend validates Authorization: Bearer <token> headers with PyJWT.

from asyncmq.contrib.dashboard.admin import AsyncMQAdmin
from asyncmq.contrib.dashboard.admin.backends.jwt import JWTAuthBackend

backend = JWTAuthBackend(
    secret="change-me-with-at-least-32-bytes",
    algorithms=["HS256"],
    audience=None,
    issuer=None,
    user_claim="sub",
    user_name_claim="name",
    admin_claim="is_admin",
    roles_claim="roles",
    leeway=0,
)

admin = AsyncMQAdmin(enable_login=True, backend=backend)

Behavior:

  • authenticate() decodes token and returns a dashboard User or None.
  • Tokens must carry is_admin=true by default, or the dashboard authorization gate rejects the authenticated user.
  • Admin claims must be booleans or documented truthy strings such as "true"; object and list claim values fail closed.
  • Role-based deployments can use roles claims with AsyncMQAdmin(require_admin=False, required_roles=("ops",)).
  • Role claims must be a string or a list of role values; object claims are not interpreted as roles.
  • login() returns informational HTML (JWT issuance is external to AsyncMQ).
  • logout() redirects to /login.

Install dependency:

pip install pyjwt

Token Creation Example

import jwt

payload = {
    "sub": "ops-user",
    "name": "Ops User",
    "is_admin": True,
    "roles": ["asyncmq:admin"],
}
token = jwt.encode(payload, "change-me-with-at-least-32-bytes", algorithm="HS256")
print(token)

Use in request header:

Authorization: Bearer <token>

Hardening Checklist for JWT

  1. Use a secret of at least 32 bytes for HS256; AsyncMQ rejects shorter HS* secrets.
  2. Set audience and issuer if tokens come from a central IdP.
  3. Keep token lifetimes short and rotate signing keys.
  4. Terminate TLS before any dashboard path.

SimpleUsernamePasswordBackend

Session-backed auth using a synchronous verify(username, password) callback.

from asyncmq.contrib.dashboard.admin import AsyncMQAdmin
from asyncmq.contrib.dashboard.admin.backends.simple_user import (
    SimpleUsernamePasswordBackend,
)
from asyncmq.contrib.dashboard.admin.protocols import User


def verify(username: str, password: str) -> User | None:
    if username == "admin" and password == "secret":
        return User(id="admin", name="Admin", is_admin=True, roles=["asyncmq:admin"])
    return None


backend = SimpleUsernamePasswordBackend(verify=verify)
admin = AsyncMQAdmin(enable_login=True, backend=backend)

Mount Prefix and Auth Redirects

When mounting under a prefix, build app links with with_url_prefix=True to keep login/logout and sidebar links correct.

from fastapi import FastAPI
from asyncmq.contrib.dashboard.admin import AsyncMQAdmin

app = FastAPI()
admin = AsyncMQAdmin(enable_login=True, backend=backend)
app.mount("/ops", admin.get_asgi_app(with_url_prefix=True))

Security Checklist

  • Enforce HTTPS.
  • Rotate JWT/session secrets.
  • Keep auth backend errors opaque to clients.
  • Require explicit admin or operator roles for dashboard users.
  • Restrict dashboard exposure to trusted operator networks.
  • Review /audit regularly for sensitive actions.