Dashboard Authentication
The Ironflow dashboard protects the Web UI using email and password authentication. This is managed independently of the API Keys used for SDK and worker communication.
Default Credentials
Section titled “Default Credentials”During the Bootstrap Process, Ironflow creates a default administrator:
| Field | Value |
|---|---|
admin@ironflow.local | |
| Password | Randomly generated (see server logs on first boot). |
How It Works
Section titled “How It Works”- Login: The user submits credentials to
POST /api/v1/auth/login. - Session: The server returns a JWT (JSON Web Token) signed with an HMAC-SHA256 secret.
- Storage: The dashboard stores this token as a browser cookie (
ironflow_dashboard_token) and in localStorage. - Expiry: Sessions are valid for 24 hours.
- Validation: On load, if a token exists in localStorage, the dashboard calls
GET /api/v1/auth/validateto verify the JWT is still accepted by the server. If the token is stale (e.g., the signing secret changed), the token is cleared and the user is redirected to the login page. If no token exists, the login page is shown directly.
Authentication Flow
Section titled “Authentication Flow”sequenceDiagram
participant Browser
participant Dashboard as Dashboard (React)
participant Server as Ironflow Server
Note over Server: Startup: load JWT secret from<br/>.ironflow_jwt_secret (or generate + persist)
rect rgb(40, 40, 55)
Note right of Browser: First visit (no token in localStorage)
Dashboard->>Server: GET /api/v1/capabilities
Server-->>Dashboard: { auth_required: true }
Note right of Dashboard: isLoggedIn() = false, skip validate
Dashboard->>Browser: Show login page
Browser->>Server: POST /api/v1/auth/login { email, password }
Server-->>Browser: { token: "eyJ..." }
Browser->>Browser: Store JWT in cookie + localStorage
end
rect rgb(40, 55, 40)
Note right of Browser: Normal usage (JWT valid)
Dashboard->>Server: GET /api/v1/functions<br/>Cookie: ironflow_dashboard_token=eyJ...<br/>X-Ironflow-Environment: env_default
Server->>Server: Verify JWT signature + expiry
Server-->>Dashboard: 200 { functions: [...] }
Note right of Browser: User switches to new project/environment
Dashboard->>Server: GET /api/v1/functions<br/>Cookie: ironflow_dashboard_token=eyJ...<br/>X-Ironflow-Environment: env_myproject_staging
Server->>Server: Same JWT, different env header
Server-->>Dashboard: 200 { functions: [...] }
end
rect rgb(55, 50, 40)
Note right of Browser: Returning after server restart
Dashboard->>Server: GET /api/v1/capabilities
Server-->>Dashboard: { auth_required: true }
Note right of Dashboard: isLoggedIn() = true (localStorage token exists)
Dashboard->>Server: GET /api/v1/auth/validate<br/>Cookie: ironflow_dashboard_token=eyJ...
Server->>Server: Same secret from file, JWT still valid
Server-->>Dashboard: 200 { valid: true }
Note right of Dashboard: Session continues, no re-login needed
end
rect rgb(55, 40, 40)
Note right of Browser: Stale token (secret was reset)
Dashboard->>Server: GET /api/v1/capabilities
Server-->>Dashboard: { auth_required: true }
Note right of Dashboard: isLoggedIn() = true (localStorage token exists)
Dashboard->>Server: GET /api/v1/auth/validate<br/>Cookie: ironflow_dashboard_token=eyJ...
Server-->>Dashboard: 401 (signature mismatch)
Dashboard->>Dashboard: Clear stale token (logout)
Dashboard->>Browser: Redirect to login page
end
JWT Signing Secret Persistence
Section titled “JWT Signing Secret Persistence”The JWT signing secret is resolved at startup with the following precedence:
- Explicit config:
IRONFLOW_JWT_SECRETenv var orauth.jwtSecretin YAML (hex-encoded, minimum 16 bytes). - Persisted file:
.ironflow_jwt_secretnext to the SQLite database, or in the working directory for PostgreSQL deployments. - Auto-generate: If neither exists, a 32-byte random secret is generated and written to the file for next time.
# Via environment variable (hex-encoded, minimum 16 bytes)IRONFLOW_JWT_SECRET="$(openssl rand -hex 32)" ironflow serve# Via ironflow.yamlspec: auth: jwtSecret: ${IRONFLOW_JWT_SECRET}User Management
Section titled “User Management”Once logged in as an admin, you can manage users through the Users page in the dashboard sidebar. You can:
- Add team members by email.
- Assign roles (
viewer,developer,admin). - Revoke access by deleting user accounts.
Dev Mode
Section titled “Dev Mode”For local development, you can bypass dashboard authentication entirely:
ironflow serve --devThis skips the login screen and grants full admin access to the dashboard. See the CLI Reference for details.