Skip to content

Builtin Authentication

Builtin authentication provides user management with role-based access control (RBAC) using JWT tokens.

Features

  • User Management: Create, update, and delete users through the web UI
  • Role-Based Access Control: Four roles with different permission levels
  • JWT Authentication: Secure token-based authentication
  • Password Management: Users can change their own passwords; admins can reset any user's password
  • API Key Management: Create and manage API keys for programmatic access with role-based permissions

Roles

RolePermissions
adminFull access including user management
managerCreate, edit, delete, run, and stop DAGs
operatorRun and stop DAGs (execute only)
viewerRead-only access to DAGs and execution history

Configuration

YAML Configuration

yaml
# ~/.config/dagu/config.yaml
auth:
  mode: builtin
  builtin:
    admin:
      username: admin
      # password: optional - auto-generated if not set
    token:
      secret: your-secure-random-secret-key
      ttl: 24h
  # Optional: API token for programmatic access (works alongside JWT)
  token:
    value: your-api-token

Token TTL Format

The ttl field uses Go's duration format. Valid time units are:

UnitDescriptionExample
nsnanoseconds1000000ns
us (or µs)microseconds1000us
msmilliseconds1000ms
sseconds3600s
mminutes60m
hhours24h

Note: Days (d) and weeks (w) are not supported. Use hours instead.

Common TTL examples:

DurationValue
1 hour1h
8 hours8h
24 hours (1 day)24h
7 days168h
30 days720h
365 days8760h

You can also combine units: 1h30m, 2h45m30s

Environment Variables

bash
# Required
export DAGU_AUTH_MODE=builtin
export DAGU_AUTH_TOKEN_SECRET=your-secure-random-secret-key

# Optional - admin credentials
export DAGU_AUTH_ADMIN_USERNAME=admin  # default: admin
export DAGU_AUTH_ADMIN_PASSWORD=       # auto-generated if not set

# Optional - token settings
export DAGU_AUTH_TOKEN_TTL=24h         # default: 24h

dagu start-all

Initial Setup

On first startup with builtin auth enabled:

  1. If no users exist, an admin user is automatically created
  2. If DAGU_AUTH_ADMIN_PASSWORD is not set, a secure password is auto-generated and printed to stdout:
================================================================================
  ADMIN USER CREATED
  Username: admin
  Password: <auto-generated-password>
  NOTE: Please change this password immediately!
================================================================================
  1. Use these credentials to log in and access the user management page

API Access

Login

bash
# Get JWT token
curl -X POST http://localhost:8080/api/v2/auth/login \
  -H "Content-Type: application/json" \
  -d '{"username": "admin", "password": "your-password"}'

# Response:
# {"token": "eyJhbG...", "user": {"id": "...", "username": "admin", "role": "admin"}}

Using the Token

bash
# Include token in Authorization header
curl -H "Authorization: Bearer eyJhbG..." \
  http://localhost:8080/api/v2/dags

Get Current User

bash
curl -H "Authorization: Bearer eyJhbG..." \
  http://localhost:8080/api/v2/auth/me

Change Password (Self)

bash
curl -X POST http://localhost:8080/api/v2/auth/change-password \
  -H "Authorization: Bearer eyJhbG..." \
  -H "Content-Type: application/json" \
  -d '{"currentPassword": "old-pass", "newPassword": "new-pass"}'

User Management (Admin Only)

List Users

bash
curl -H "Authorization: Bearer eyJhbG..." \
  http://localhost:8080/api/v2/users

Create User

bash
curl -X POST http://localhost:8080/api/v2/users \
  -H "Authorization: Bearer eyJhbG..." \
  -H "Content-Type: application/json" \
  -d '{"username": "newuser", "password": "secure-pass", "role": "operator"}'

Update User

bash
curl -X PUT http://localhost:8080/api/v2/users/{user-id} \
  -H "Authorization: Bearer eyJhbG..." \
  -H "Content-Type: application/json" \
  -d '{"role": "manager"}'

Reset User Password (Admin)

bash
curl -X PUT http://localhost:8080/api/v2/users/{user-id}/password \
  -H "Authorization: Bearer eyJhbG..." \
  -H "Content-Type: application/json" \
  -d '{"newPassword": "new-secure-pass"}'

Delete User

bash
curl -X DELETE http://localhost:8080/api/v2/users/{user-id} \
  -H "Authorization: Bearer eyJhbG..."

Disable/Enable User

Disabled users cannot log in or access the API, but their account is preserved:

bash
# Disable a user
curl -X PATCH http://localhost:8080/api/v2/users/{user-id} \
  -H "Authorization: Bearer eyJhbG..." \
  -H "Content-Type: application/json" \
  -d '{"isDisabled": true}'

# Enable a user
curl -X PATCH http://localhost:8080/api/v2/users/{user-id} \
  -H "Authorization: Bearer eyJhbG..." \
  -H "Content-Type: application/json" \
  -d '{"isDisabled": false}'

Note: You can also disable/enable users from the web UI via the user management page. This is useful for revoking access without deleting the user account.

Docker Compose Example

yaml
services:
  dagu:
    image: ghcr.io/dagu-org/dagu:latest
    environment:
      - DAGU_AUTH_MODE=builtin
      - DAGU_AUTH_TOKEN_SECRET=change-me-to-secure-random-string
      # Password auto-generated on first run, printed to stdout
    ports:
      - "8080:8080"
    volumes:
      - dagu-data:/var/lib/dagu

volumes:
  dagu-data:

Important Notes

  • Basic Auth Ignored: When auth.mode is set to builtin, any auth.basic configuration is ignored. A warning will be logged. Use the builtin admin credentials instead.

  • API Token Support: API tokens (auth.token.value) work alongside builtin auth for programmatic access without requiring JWT login.

    yaml
    auth:
      mode: builtin
      builtin:
        token:
          secret: your-jwt-secret
      token:
        value: your-api-token  # Use with: curl -H "Authorization: Bearer your-api-token"

Security Notes

  • Token Secret: Use a strong, random secret (at least 32 characters). This is used to sign JWT tokens.
  • Password Requirements: Minimum 8 characters
  • Token Expiry: Tokens expire after the configured TTL (default: 24 hours)
  • V1 API: The V1 API is disabled when builtin auth is enabled (use V2 API)
  • Terminal Access: The web-based terminal is disabled by default. Enable with terminal.enabled: true only in trusted environments. See Terminal Configuration.
  • Audit Logging: Security events (logins, user changes, API key operations) are logged by default. See Audit Logging.

API Key Management

Builtin authentication includes full API key management capabilities. API keys provide programmatic access with role-based permissions, ideal for CI/CD pipelines, automation scripts, and service-to-service communication.

Quick Start

bash
# Create an API key via the API (requires admin JWT token)
curl -X POST http://localhost:8080/api/v2/api-keys \
  -H "Authorization: Bearer $JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "ci-pipeline", "role": "operator"}'

# Use the API key
curl -H "Authorization: Bearer dagu_your-api-key-here" \
  http://localhost:8080/api/v2/dags

Key Features

  • Role Assignment: Each API key has its own role (admin, manager, operator, viewer)
  • Usage Tracking: See when each key was last used
  • Web UI Management: Create and manage keys from Settings > API Keys
  • Secure Storage: Keys are hashed; the full key is only shown once at creation

For detailed documentation, see API Keys.

OIDC/SSO Login

Builtin authentication supports OIDC/SSO login, allowing users to authenticate via enterprise identity providers (Google, Okta, Auth0, Keycloak, etc.) while maintaining Dagu's user management and RBAC system.

Enabling OIDC

OIDC is automatically enabled when all required fields (clientId, clientSecret, clientUrl, issuer) are configured. No explicit enabled flag is needed.

yaml
auth:
  mode: builtin
  builtin:
    admin:
      username: admin
    token:
      secret: your-jwt-secret
      ttl: 24h
  oidc:
    clientId: your-client-id
    clientSecret: your-client-secret
    clientUrl: https://dagu.example.com
    issuer: https://accounts.google.com
    scopes: ["openid", "profile", "email"]
    # autoSignup defaults to true - users are auto-created on first login
    allowedDomains: ["company.com"]
    whitelist: ["partner@external.com"]
    buttonLabel: "Login with SSO"
    roleMapping:
      defaultRole: viewer  # Role for new users when no mapping matches

Environment Variables

bash
# OIDC configuration (auto-enabled when all required fields are set)
export DAGU_AUTH_OIDC_CLIENT_ID=your-client-id
export DAGU_AUTH_OIDC_CLIENT_SECRET=your-client-secret
export DAGU_AUTH_OIDC_CLIENT_URL=https://dagu.example.com
export DAGU_AUTH_OIDC_ISSUER=https://accounts.google.com

# Optional settings
export DAGU_AUTH_OIDC_AUTO_SIGNUP=true                    # default: true
export DAGU_AUTH_OIDC_DEFAULT_ROLE=viewer                 # default: viewer
export DAGU_AUTH_OIDC_ALLOWED_DOMAINS=company.com,other.com  # comma-separated
export DAGU_AUTH_OIDC_WHITELIST=user@example.com          # comma-separated
export DAGU_AUTH_OIDC_BUTTON_LABEL="Login with SSO"

Configuration Fields

FieldDescriptionDefault
clientIdOAuth2 client ID from your OIDC providerRequired
clientSecretOAuth2 client secretRequired
clientUrlBase URL of your Dagu instanceRequired
issuerOIDC provider URLRequired
scopesOAuth2 scopes to request["openid", "profile", "email"]
autoSignupAuto-create users on first OIDC logintrue
allowedDomainsEmail domains allowed to authenticateAll domains
whitelistSpecific email addresses always allowedNone
buttonLabelText displayed on the SSO login button"Login with SSO"
roleMapping.defaultRoleRole assigned to new users when no mapping matchesviewer

Note: allowedDomains, whitelist, and scopes can be specified as either YAML lists or comma-separated strings. This is especially useful for environment variables.

Auto-Signup

When autoSignup is enabled (the default), users authenticating via OIDC for the first time are automatically created in Dagu with the role specified by roleMapping.defaultRole. This eliminates the need to pre-create user accounts.

When autoSignup is disabled, users must exist in Dagu before they can log in via OIDC.

Domain Filtering

Use allowedDomains to restrict OIDC login to specific email domains:

yaml
oidc:
  allowedDomains: ["company.com", "subsidiary.com"]

Users with emails outside these domains will be denied access.

Email Whitelist

Use whitelist to allow specific email addresses:

yaml
oidc:
  whitelist: ["allowed@example.com", "admin@example.com"]

Access Control Logic:

  • If whitelist is set: only emails in the whitelist are allowed
  • If allowedDomains is set: only emails from those domains are allowed
  • If both are set: email must match whitelist OR domain must match allowedDomains
  • If neither is set: all authenticated emails are allowed
yaml
# Example: Allow company.com domain + specific external partners
oidc:
  allowedDomains: ["company.com"]
  whitelist: ["partner@external.com", "contractor@other.com"]

Role Mapping

Map IdP groups to Dagu roles for automatic role assignment:

yaml
oidc:
  roleMapping:
    defaultRole: viewer           # Role when no mapping matches (default: viewer)
    groupsClaim: groups           # Claim containing user's groups
    groupMappings:
      admins: admin               # IdP group -> Dagu role
      developers: manager
      ops: operator
      everyone: viewer
    roleAttributeStrict: false    # Deny login if no role matched
    skipOrgRoleSync: false        # Sync roles on every login

Role Mapping Options:

FieldDescriptionDefault
defaultRoleRole assigned when no mapping matchesviewer
groupsClaimJWT claim containing group membershipgroups
groupMappingsMap of IdP group names to Dagu rolesNone
roleAttributePathjq expression for advanced role extractionNone
roleAttributeStrictDeny login when no valid role is foundfalse
skipOrgRoleSyncOnly assign role on first loginfalse

Example with jq expression:

yaml
roleMapping:
  defaultRole: viewer
  roleAttributePath: 'if (.groups | contains(["admins"])) then "admin" elif (.groups | contains(["devs"])) then "manager" else "viewer" end'

How It Works

  1. User clicks "Login with SSO" on the login page
  2. Redirected to OIDC provider for authentication
  3. After successful authentication, Dagu validates the token
  4. If autoSignup is enabled and user doesn't exist, a new user is created
  5. Role is determined by roleMapping (if configured) or defaultRole
  6. User receives a JWT token for the Dagu session

Notes

  • OIDC users are managed alongside local users in the same user database
  • OIDC users can also authenticate with their Dagu password if one is set
  • Admin users can manage all users (OIDC and local) from the web UI
  • The callback URL is {clientUrl}/oidc-callback

Comparison with Other Auth Methods

FeatureBasic AuthToken AuthOIDC (standalone)Builtin (Recommended)
User ManagementNoNoNoYes
Role-Based AccessNoNoNoYes
Password ChangeNoNoNoYes
Multiple UsersNoNoYesYes
API Key ManagementNoNoNoYes
SSO/OIDC LoginNoNoYesYes
Role Mapping from IdPNoNoNoYes
Self-HostedYesYesYesYes

Recommendation: Use auth.mode: builtin for production deployments. Enable OIDC under builtin mode for SSO while retaining full user management and RBAC capabilities.

Released under the MIT License.