Skip to main content
A
Docs

Authentication

JWT-based authentication and role-based access control across all Anar products.

Overview

Every Anar product uses JWT-based authentication with role-based access control (RBAC). The shared library (anar_shared) provides a common auth module so all 13 Python backends enforce the same token format, signing algorithm, and role hierarchy.

Token Format

Anar uses HS256-signed JWTs with the following payload structure:

{
  "sub": "user@example.com",
  "role": "admin",
  "exp": 1739750400
}
FieldTypeDescription
substringSubject identifier (username or email)
rolestringOne of admin, manager, user, or viewer
expintegerUnix timestamp for token expiry

Roles

The platform defines four roles with descending privilege levels:

RolePermissions
adminFull access to all resources, user management, configuration
managerCreate, update, and delete resources within their scope
userRead access and limited write operations (submit requests, upload files)
viewerRead-only access to dashboards and reports

Setting Up Auth in a Product

1. Initialize Auth Functions

Use make_auth to generate a token creator and a FastAPI dependency for extracting the current user from the Authorization header:

from anar_shared import make_auth, make_require_role

create_token, get_current_user = make_auth(
    jwt_secret="your-secret-key",
    jwt_algorithm="HS256",
    jwt_expire_minutes=60,
)

require_role = make_require_role(get_current_user)

2. Protect Endpoints

Apply get_current_user as a dependency to require authentication, or use require_role to enforce specific roles:

from fastapi import APIRouter, Depends

router = APIRouter()

@router.get("/api/v1/resources")
async def list_resources(user=Depends(get_current_user)):
    return {"user": user.sub, "role": user.role}

@router.delete("/api/v1/resources/{id}")
async def delete_resource(id: str, user=Depends(require_role("admin", "manager"))):
    # Only admin and manager can delete
    ...

3. Generate Tokens

Use the create_token function to issue tokens during login or from a management endpoint:

@router.post("/api/v1/auth/token")
async def login(username: str, password: str):
    # Validate credentials against your user store
    user = await authenticate(username, password)
    token = create_token(subject=user.email, role=user.role)
    return {"access_token": token, "token_type": "bearer"}

Making Authenticated Requests

Include the JWT in the Authorization header as a Bearer token:

curl -X GET http://localhost:8001/api/v1/conversations \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."

For service-to-service calls, the AnarServiceClient from the shared library accepts an auth_token parameter:

from anar_shared import AnarServiceClient, ServiceConfig

client = AnarServiceClient(ServiceConfig(
    guard_url="http://localhost:8002",
    auth_token="your-service-token",
))
result = await client.guard_scan("Check this text for PII")

JWT Secret Configuration

Each product reads its JWT secret from an environment variable. The naming convention uses a product-specific prefix:

ProductEnvironment Variable
ChatCHAT_JWT_SECRET or JWT_SECRET
GuardGUARD_JWT_SECRET or JWT_SECRET
VoiceVOICE_JWT_SECRET or JWT_SECRET
AgentsAGENTS_JWT_SECRET
ComplyCOMPLY_JWT_SECRET
EvalEVAL_JWT_SECRET or JWT_SECRET
DocsDOCS_JWT_SECRET or JWT_SECRET
FlowFLOW_JWT_SECRET
InsightsINSIGHTS_JWT_SECRET or JWT_SECRET
TranslateTRANSLATE_JWT_SECRET
MinutesMINUTES_JWT_SECRET
ProcurePROCURE_JWT_SECRET

Production Secrets

Never use the default development secrets in production. Generate a strong random secret with openssl rand -hex 32 and store it in your secrets manager.

Token Data Model

The TokenData model returned by get_current_user has two fields:

class TokenData(BaseModel):
    sub: str        # Subject (user identifier)
    role: str       # Role (defaults to "viewer" if not present in token)

If a token is missing the role claim, it defaults to viewer — the lowest privilege level. If the token is invalid or expired, the middleware returns a 401 Unauthorized response:

{
  "detail": "Invalid authentication token"
}

Role Enforcement Errors

When a user has a valid token but lacks the required role, the middleware returns 403 Forbidden:

{
  "detail": "Role 'user' not authorized. Requires: admin, manager"
}