Skip to content

Authentication Setup

Mozaiks uses a pluggable auth adapter system that works with any auth provider.

Quick Start

Demo Mode (No Auth)

For local development or demos, disable auth entirely:

AUTH_ENABLED=false

All requests become anonymous users. No tokens required.

For local user-to-user testing, such as DM notifications, keep auth disabled but assign each browser profile a different dev persona. The no-auth dependency accepts these request-scoped overrides only when AUTH_ENABLED=false:

  • Header: X-Mozaiks-Dev-User-Id: dev_alice
  • Cookie: mozaiks_dev_user_id=dev_alice
  • Query param for one-off API calls: ?dev_user_id=dev_alice

Optional comma-separated overrides are also supported:

  • X-Mozaiks-Dev-Roles, mozaiks_dev_roles, or dev_roles
  • X-Mozaiks-Dev-Scopes, mozaiks_dev_scopes, or dev_scopes

Browser workflow:

document.cookie = "mozaiks_dev_user_id=dev_alice; path=/";
document.cookie = "mozaiks_dev_roles=admin,user; path=/";

Use another browser profile or incognito window with mozaiks_dev_user_id=dev_bob. Sending a DM from dev_alice to dev_bob can create a notification for Bob; sending to yourself will not, because the messaging module excludes the sender from recipient_ids.


Provider Setup

Supabase

SUPABASE_URL=https://xyzcompany.supabase.co

That's it. The adapter auto-detects from SUPABASE_URL and constructs the JWKS endpoint automatically.

Optional: For local development with Supabase, add the JWT secret:

SUPABASE_JWT_SECRET=your-jwt-secret


Keycloak

KEYCLOAK_URL=https://keycloak.example.com
KEYCLOAK_REALM=myrealm
KEYCLOAK_CLIENT_ID=my-app  # optional, for audience validation

Auth0

AUTH_PROVIDER=jwt
MOZAIKS_OIDC_AUTHORITY=https://your-tenant.auth0.com
AUTH_AUDIENCE=your-api-identifier
AUTH_SCOPES_FORMAT=array

Set AUTH_JWKS_URL and AUTH_ISSUER only when you want to override OIDC discovery explicitly.


Generic OIDC (Okta, Azure AD, etc.)

AUTH_PROVIDER=jwt
MOZAIKS_OIDC_AUTHORITY=https://your-provider
AUTH_AUDIENCE=your-api

For providers that require a tenant segment in the discovery URL, set:

MOZAIKS_OIDC_TENANT_ID=your-tenant-or-directory-id

You can also bypass authority composition with:

MOZAIKS_OIDC_DISCOVERY_URL=https://your-provider/.well-known/openid-configuration

Explicit overrides remain supported:

AUTH_JWKS_URL=https://your-provider/.well-known/jwks.json
AUTH_ISSUER=https://your-provider/

Claim Mappings

Different providers put user data in different JWT claims. Configure as needed:

Variable Default Description
AUTH_USER_ID_CLAIM sub Claim containing user ID
AUTH_EMAIL_CLAIM email Claim containing email
AUTH_NAME_CLAIM name Claim containing display name
AUTH_ROLES_CLAIM roles Claim containing user roles
AUTH_SCOPES_CLAIM scp Claim containing scopes
AUTH_SCOPES_FORMAT space space (Azure) or array (Auth0)

Auto-Detection

If AUTH_PROVIDER is not set, the system auto-detects based on environment variables:

If this is set... Provider used
AUTH_ENABLED=false none
SUPABASE_URL supabase
KEYCLOAK_URL + KEYCLOAK_REALM keycloak
AUTH_JWKS_URL + AUTH_ISSUER jwt
MOZAIKS_OIDC_AUTHORITY or MOZAIKS_OIDC_DISCOVERY_URL jwt
Nothing none (demo mode)

Custom Adapter

Register your own auth provider:

from mozaiksai.core.auth.adapters import register_adapter, UserClaims, BaseAuthAdapter

class MyAuthAdapter(BaseAuthAdapter):
    name = "my-provider"

    async def validate_token(self, token: str) -> UserClaims:
        # Your validation logic
        decoded = my_validate(token)
        return UserClaims(
            user_id=decoded["sub"],
            email=decoded.get("email"),
            roles=decoded.get("roles", []),
            scopes=[],
            raw_claims=decoded,
            provider=self.name,
        )

    def is_enabled(self) -> bool:
        return bool(os.getenv("MY_AUTH_SECRET"))

# Register before app startup
register_adapter("my-provider", MyAuthAdapter)

Then set:

AUTH_PROVIDER=my-provider
MY_AUTH_SECRET=...


WebSocket Auth

WebSocket connections extract tokens from query params by default:

ws://localhost:8000/ai/ws/workflow?access_token=eyJ...

To disable (in production behind reverse proxy):

MOZAIKS_WS_ALLOW_QUERY_TOKEN=false