Skip to content

Docs: Document bind-aware gateway/UI authentication posture (PraisonAI PR #1517) #221

@MervinPraison

Description

@MervinPraison

Summary

PraisonAI PR #1517 (merged 2026-04-22) introduces bind-aware authentication posture for both the WebSocket Gateway and the Chainlit UI. Security defaults now change automatically based on the bind interface:

  • Loopback (127.0.0.1, localhost, ::1) → permissive mode (quickstart preserved)
  • External (0.0.0.0, LAN IPs, public IPs) → strict mode (auth token required, admin/admin blocked)

This is a user-facing behaviour change that affects anyone running praisonai gateway start, praisonai chat, praisonai code, praisonai realtime, praisonai agents, or any Chainlit entry point. It also introduces new exceptions, new environment variables, and new helper functions that must be documented.

Note

A follow-up agent will create/update the docs based on this issue. Follow AGENTS.md rules strictly — new content goes in docs/features/, never docs/concepts/.


SDK Ground Truth (read these files first)

Per the AGENTS.md "SDK-First" cycle, read the actual source before writing docs:

Core protocols (Python)

  • src/praisonai-agents/praisonaiagents/gateway/protocols.py
    • AuthMode = Literal["local", "token", "password", "trusted-proxy"]
    • is_loopback(host: str) -> bool
    • resolve_auth_mode(bind_host: str, configured: Optional[AuthMode] = None) -> AuthMode
  • src/praisonai-agents/praisonaiagents/gateway/config.py
    • New field on GatewayConfig: bind_host: Optional[str] = None (defaults to host via __post_init__)

Gateway enforcement (wrapper)

  • src/praisonai/praisonai/gateway/auth.py (NEW FILE)
    • class GatewayStartupError(Exception)
    • assert_external_bind_safe(config: GatewayConfig) -> None
    • get_auth_token_fingerprint(token: str) -> strgw_****XXXX format
    • save_auth_token_to_env(token: str, env_file: Optional[str] = None) -> None → writes to ~/.praisonai/.env with mode 0600
  • src/praisonai/praisonai/gateway/server.py
    • Calls assert_external_bind_safe(self.config) in start()
    • On loopback without token: auto-generates token, logs fingerprint only, persists to ~/.praisonai/.env

UI enforcement (wrapper)

  • src/praisonai/praisonai/ui/_auth.py (NEW FILE)
    • class UIStartupError(Exception)
    • register_password_auth(app, *, bind_host: str) -> None — consolidated from 6 duplicated callbacks
  • Callers (now all use register_password_auth):
    • praisonai/ui/chat.py
    • praisonai/ui/bot.py
    • praisonai/ui/agents.py
    • praisonai/ui/realtime.py
    • praisonai/ui/code.py
    • praisonai/ui/colab_chainlit.py

Tests (reference for behaviour)

  • src/praisonai/tests/unit/gateway/test_bind_aware_auth.py
  • src/praisonai/tests/unit/ui/test_ui_bind_aware_creds.py
  • src/praisonai/tests/integration/gateway/test_bind_aware_e2e.py

Decision: Create New + Update Existing

I checked the existing docs repo. Result:

Target Status Action
docs/gateway.mdx Exists, no auth/security section UPDATE: add "Authentication" section with link to new feature page
docs/features/bot-gateway.mdx Exists UPDATE: cross-link to new auth page
docs/guides/troubleshoot-gateway.mdx Exists UPDATE: add entries for GatewayStartupError and UIStartupError
docs/features/chat.mdx Exists UPDATE: document CHAINLIT_HOST, PRAISONAI_ALLOW_DEFAULT_CREDS, strict-mode behaviour
docs/features/onboard.mdx Exists, already mentions GATEWAY_AUTH_TOKEN UPDATE: link to new auth page; note that token is now auto-persisted to ~/.praisonai/.env with mode 0600
docs/features/gateway-bind-aware-auth.mdx Does NOT exist CREATE new page
docs.json UPDATE: add new page under "Features" group (NOT "Concepts")

Important

Per AGENTS.md §1.8: never place this in docs/concepts/. That folder is human-approved only. Place the new page in docs/features/.


1. CREATE — docs/features/gateway-bind-aware-auth.mdx

Follow the AGENTS.md §2 "Page Structure Template" exactly. Agent-centric, non-developer friendly, progressive disclosure.

Frontmatter

---
title: "Bind-Aware Authentication"
sidebarTitle: "Bind-Aware Auth"
description: "Gateway and UI automatically enforce stricter auth when bound to external interfaces"
icon: "shield"
---

Required content outline

  1. One-sentence intro

    "The gateway and chat UI change security behaviour based on the interface they bind to — permissive on loopback, strict on external."

  2. Hero Mermaid diagram (use the standard color scheme from AGENTS.md §3.1):

    graph LR
        subgraph "Bind-Aware Auth"
            Bind[🔌 Bind Host] --> Check{🔍 Loopback?}
            Check -->|Yes 127.0.0.1| Local[🟢 local mode<br/>no token required]
            Check -->|No 0.0.0.0| Token[🔒 token mode<br/>auth required]
        end
    
        classDef bind fill:#6366F1,stroke:#7C90A0,color:#fff
        classDef decision fill:#F59E0B,stroke:#7C90A0,color:#fff
        classDef permissive fill:#10B981,stroke:#7C90A0,color:#fff
        classDef strict fill:#8B0000,stroke:#7C90A0,color:#fff
    
        class Bind bind
        class Check decision
        class Local permissive
        class Token strict
    
    Loading
  3. Quick Start (Steps component) — agent-centric, per AGENTS.md §1.1 rule 9:

    Step 1: Local development (loopback — permissive)

    from praisonaiagents import Agent
    
    agent = Agent(
        name="Local Agent",
        instructions="You are a helpful assistant.",
    )
    
    # Serve via gateway on loopback — no token needed
    # $ praisonai gateway start --host 127.0.0.1
    agent.start("hello")

    Step 2: External deployment (strict — token required)

    # Option A: Run onboarding (recommended)
    praisonai onboard
    
    # Option B: Set a token explicitly
    export GATEWAY_AUTH_TOKEN=$(openssl rand -hex 16)
    praisonai gateway start --host 0.0.0.0
  4. How It Works — sequence diagram + table:

    sequenceDiagram
        participant User
        participant Gateway
        participant BindAwareAuth
        participant WS as WebSocket Clients
    
        User->>Gateway: praisonai gateway start --host <H>
        Gateway->>BindAwareAuth: assert_external_bind_safe(config)
        alt H is loopback (127.0.0.1, localhost, ::1)
            BindAwareAuth-->>Gateway: OK (permissive, warn if no token)
        else H is external (0.0.0.0, LAN, public)
            alt auth_token set
                BindAwareAuth-->>Gateway: OK (strict)
            else no token
                BindAwareAuth-->>Gateway: raise GatewayStartupError
                Gateway-->>User: exit 1 + fix instructions
            end
        end
        Gateway->>WS: accept connections
    
    Loading
  5. Auth Modes table (from AuthMode literal):

    Mode Meaning Trigger
    local Permissive — no token required Loopback bind (default)
    token Token required (auto-generated if absent on loopback) External bind (default)
    password Username/password auth Chainlit UI
    trusted-proxy Auth handled upstream Reverse proxy setups
  6. Interface detection table (from is_loopback() tests):

    Host is_loopback() Resolved mode
    127.0.0.1 True local
    127.255.255.255 True local
    localhost True local
    ::1 True local
    0.0.0.0 False token
    192.168.1.x False token
    10.0.0.x False token
    8.8.8.8 (public) False token
  7. User interaction flows (required by AGENTS.md §1.1 rule 10):

    • Flow A — "I want a quick local demo": run on 127.0.0.1, no config needed. Token auto-generated, fingerprint logged (gw_****abcd), saved to ~/.praisonai/.env.
    • Flow B — "I want to share on my LAN": run praisonai onboard (30s, 3 prompts) OR export GATEWAY_AUTH_TOKEN=$(openssl rand -hex 16)praisonai gateway start --host 0.0.0.0.
    • Flow C — "I'm deploying to a VPS": same as B, but also set CHAINLIT_USERNAME / CHAINLIT_PASSWORD for the UI, and consider TLS.
    • Flow D — "Lab/demo — I accept the risk of admin/admin on external": export PRAISONAI_ALLOW_DEFAULT_CREDS=1.
  8. Environment variables table (NEW in this PR):

    Variable Scope Effect
    GATEWAY_AUTH_TOKEN Gateway Auth token. Required on external bind. Auto-generated + saved to ~/.praisonai/.env (mode 0600) on loopback when unset.
    CHAINLIT_HOST UI Host the UI binds to (default 127.0.0.1). Drives UI auth mode resolution.
    CHAINLIT_USERNAME UI Username (default admin).
    CHAINLIT_PASSWORD UI Password (default admin).
    PRAISONAI_ALLOW_DEFAULT_CREDS UI Escape hatch. Set to 1/true/yes to allow admin/admin on external bind. Unsafe — demo only.
    CHAINLIT_AUTH_SECRET UI Session secret. Auto-generated if unset (ephemeral per-process).
  9. Error reference (NEW exceptions):

    GatewayStartupError — raised by assert_external_bind_safe() when binding externally without a token:

    Cannot bind to 0.0.0.0 without an auth token.
    Fix:  praisonai onboard         (30 seconds, 3 prompts)
    Or:   export GATEWAY_AUTH_TOKEN=$(openssl rand -hex 16)
    

    UIStartupError — raised by register_password_auth() when admin/admin used on external bind:

    Cannot bind to 0.0.0.0 with default admin/admin credentials.
    Fix:  export CHAINLIT_USERNAME=myuser CHAINLIT_PASSWORD=mypass
    Lab:  export PRAISONAI_ALLOW_DEFAULT_CREDS=1  (demo only)
    
  10. Token fingerprinting — explain that logs now show gw_****XXXX (last 4 chars), never the raw token. Cite get_auth_token_fingerprint().

  11. Which option when — decision diagram (required by AGENTS.md §6.1):

    graph TB
        Q{Where will it run?}
        Q -->|My laptop only| Local[127.0.0.1 — just run it]
        Q -->|LAN for my team| LAN{Have a token?}
        Q -->|Public internet| Public[0.0.0.0 + token + TLS + custom creds]
        LAN -->|No| Onboard[praisonai onboard]
        LAN -->|Yes| Export[export GATEWAY_AUTH_TOKEN=...]
    
        classDef question fill:#F59E0B,stroke:#7C90A0,color:#fff
        classDef safe fill:#10B981,stroke:#7C90A0,color:#fff
        classDef action fill:#189AB4,stroke:#7C90A0,color:#fff
        classDef strict fill:#8B0000,stroke:#7C90A0,color:#fff
    
        class Q,LAN question
        class Local safe
        class Onboard,Export action
        class Public strict
    
    Loading
  12. Best Practices (AccordionGroup, 3–4 items):

    • Prefer praisonai onboard over manual token creation
    • Never commit ~/.praisonai/.env
    • Set custom CHAINLIT_USERNAME/CHAINLIT_PASSWORD before binding externally
    • Use PRAISONAI_ALLOW_DEFAULT_CREDS=1 only for ephemeral demos
  13. Related (CardGroup cols={2}):

    • Link to docs/gateway.mdx
    • Link to docs/features/onboard.mdx
    • Link to docs/guides/troubleshoot-gateway.mdx
    • Link to docs/features/chat.mdx

Writing style reminders (AGENTS.md §6)

  • One-sentence section intros. No "In this section…", "As you can see…", "It's important to note…".
  • Agent-centric: start examples with from praisonaiagents import Agent.
  • Non-developer friendly: make the reader feel "is it this easy?"
  • Active voice, short, concise.

2. UPDATE — docs/gateway.mdx

Add a new "Authentication" section between "How It Works" and "Configuration Options":

  • One-sentence intro: "Authentication posture changes automatically based on the bind interface."
  • Small mermaid diagram (loopback vs external)
  • 2-row quick-reference table (loopback → permissive, external → token required)
  • Link card pointing to the new docs/features/gateway-bind-aware-auth.mdx

Also add bind_host to the GatewayConfig section if it isn't already.


3. UPDATE — docs/guides/troubleshoot-gateway.mdx

Add two new troubleshooting entries:

"GatewayStartupError: Cannot bind to 0.0.0.0 without an auth token"

  • Cause: external bind without GATEWAY_AUTH_TOKEN
  • Fix: praisonai onboard or export GATEWAY_AUTH_TOKEN=$(openssl rand -hex 16)

"UIStartupError: Cannot bind to 0.0.0.0 with default admin/admin credentials"

  • Cause: Chainlit bound externally with default creds
  • Fix: set CHAINLIT_USERNAME / CHAINLIT_PASSWORD, or set PRAISONAI_ALLOW_DEFAULT_CREDS=1 for demos

"My gateway logs show gw_****xxxx instead of the full token"

  • This is intentional — tokens are fingerprinted for safe logging. Retrieve the full token from ~/.praisonai/.env (GATEWAY_AUTH_TOKEN).

4. UPDATE — docs/features/chat.mdx

Add a "Security" or "Auth" subsection covering:

  • CHAINLIT_HOST environment variable (default 127.0.0.1)
  • Bind-aware credential enforcement — admin/admin is blocked on external bind
  • PRAISONAI_ALLOW_DEFAULT_CREDS=1 escape hatch (with a <Warning> callout)
  • The consolidated register_password_auth() (mention, don't deep-dive — user-focused)

5. UPDATE — docs/features/onboard.mdx

Small additions:

  • In the "What Gets Installed" table, note that ~/.praisonai/.env is written with mode 0600.
  • In the ✅ Done panel example, update the token display line to show fingerprint format (gw_****wxyz) consistent with new logging.
  • Add a <Note> linking to the new bind-aware auth page.

6. UPDATE — docs.json

Add the new page under the "Features" group (NOT "Concepts" — see AGENTS.md §1.8):

{
  "group": "Features",
  "pages": [
    // ...existing entries...
    "docs/features/gateway-bind-aware-auth"
  ]
}

Validate the JSON after editing (AGENTS.md §1.9 rule 8).


Acceptance Criteria

  • New file docs/features/gateway-bind-aware-auth.mdx exists and passes AGENTS.md §9 quality checklist
  • Page uses Mintlify components (<Steps>, <AccordionGroup>, <CardGroup>) per AGENTS.md §4.1
  • Hero mermaid diagram uses the AGENTS.md §3.1 color scheme
  • All environment variables documented: GATEWAY_AUTH_TOKEN, CHAINLIT_HOST, CHAINLIT_USERNAME, CHAINLIT_PASSWORD, PRAISONAI_ALLOW_DEFAULT_CREDS, CHAINLIT_AUTH_SECRET
  • Both new exceptions documented with exact fix messages: GatewayStartupError, UIStartupError
  • Token fingerprint format (gw_****XXXX) mentioned
  • ~/.praisonai/.env mode 0600 persistence mentioned
  • Interface detection table includes IPv4 loopback, IPv6 loopback, localhost, external examples
  • "Which option when" decision diagram included
  • docs/gateway.mdx has a new Authentication section linking to the new page
  • docs/guides/troubleshoot-gateway.mdx has new entries for both new errors + fingerprint logging
  • docs/features/chat.mdx documents CHAINLIT_HOST + PRAISONAI_ALLOW_DEFAULT_CREDS
  • docs/features/onboard.mdx cross-links to the new page and notes 0600 perms
  • docs.json updated under Features group (not Concepts), JSON validates
  • No files created or modified under docs/concepts/ (AGENTS.md §1.8 forbids this)
  • All code examples run as-is with real imports (no placeholder values)
  • Agent-centric first example at the top of the new page (AGENTS.md §1.1 rule 9)
  • User interaction flows A–D included (AGENTS.md §1.1 rule 10)

References

  • Source PR: Feature (A): bind-aware gateway auth posture (#1506) PraisonAI#1517
  • Related upcoming work (from PR body): Issues B (magic-link), C (Origin/CSRF), D (UI pairing banner), E (owner-DM pairing buttons) — this page will be the parent for those additions.
  • Follow AGENTS.md in this repo for structure, style, diagram colors, and placement rules.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingclaudeTrigger Claude Code analysisdocumentationImprovements or additions to documentationenhancementNew feature or requestgatewaysecurity

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions