05 — Authentication & RBAC

Forge supports multiple authentication methods and has a powerful role-based access control system. This document covers how users authenticate and how permissions work.


Authentication Methods

Method Used for How it works
Session (cookie) Browser UI Login form → session cookie
OAuth2 Bearer Token API clients, scripts Authorization: Bearer <token>
Basic Auth Simple API calls Authorization: Basic base64(user:pass)
LDAP Enterprise directory Bind to LDAP server, map groups
SAML 2.0 Enterprise SSO SAML assertion from Identity Provider
Social Auth GitHub, Google, Azure AD OAuth2 flow with provider
RADIUS Network authentication RADIUS server

Session Authentication (Browser)

The user logs in with username/password and receives two cookies: - awx_sessionid — HttpOnly, Secure. JS cannot read it. - csrftoken — JS reads it and sends it as the X-CSRFToken header on every POST/PATCH/DELETE.

Watch out: - Sessions last 30 minutes (default). Every request resets the timer. - SESSION_COOKIE_SECURE=True — the cookie is only sent over HTTPS. If you're testing on HTTP, login won't work. Set to False for local development.


OAuth2 Token (API)

For scripts, automation, and integrations.

Creating a token

# Via CLI
forge-manage create_oauth2_token --user=admin

# Via API
curl -u admin:password -X POST \
  -H 'Content-Type: application/json' \
  -d '{"scope": "write"}' \
  https://forge.example.com/api/v2/tokens/

Usage

curl -H 'Authorization: Bearer <token>' \
  https://forge.example.com/api/v2/job_templates/

Watch out: - Token scope: read (GET only) or write (everything) - Default token expiry is very long (~1000 years). For security, rotate tokens periodically and delete old ones: forge-manage cleanup_tokens


SSO — LDAP

LDAP is configured via the API: PATCH /api/v2/settings/ldap/

What happens during LDAP login

  1. User enters username/password in the Forge login form
  2. Forge connects to the LDAP server with a service account
  3. Searches for the user's DN based on AUTH_LDAP_USER_SEARCH
  4. Attempts to bind as the user with the entered password
  5. If successful — maps LDAP attributes to Django user fields
  6. Applies organization/team mapping from LDAP groups
  7. Creates/updates the local user record
  8. Creates a session

Watch out


SSO — SAML 2.0

Configured via: PATCH /api/v2/settings/saml/

You need to define: - SP (Service Provider) Entity ID, certificate, and key - IDP (Identity Provider) configuration: entity_id, SSO URL, X.509 certificate - Attribute mapping: which SAML attributes correspond to email, name, etc.

Watch out: - The SAML metadata endpoint is at https://forge.example.com/sso/metadata/saml/ — give this to your IDP for automatic configuration. - SAML requires valid HTTPS certificates on both sides.


SSO — Social Auth (GitHub, Google, Azure AD)

Configured via: PATCH /api/v2/settings/github/ (or google-oauth2/, azuread-oauth2/)

You need: - Client ID and Secret from the OAuth2 provider - Organization/Team mapping (optional)

Watch out: - The callback URL you must register with the provider: https://forge.example.com/sso/complete/github-org/ - GitHub Enterprise has separate configuration with custom URLs.


RBAC — Role-Based Access Control

Concept

Every resource (template, inventory, credential...) has roles. Users and teams are assigned to roles to gain access.

Role Types

Role What it allows
admin_role Full CRUD access to the resource
read_role Read-only access
use_role Use the resource (e.g., a credential in a job)
execute_role Launch/run the template
update_role Trigger updates (project sync, inventory sync)
adhoc_role Run ad-hoc commands on inventory
approval_role Approve workflow approval nodes

System-Wide Roles

Role Scope
system_administrator Full access to EVERYTHING (superuser)
system_auditor Read-only access to EVERYTHING

Hierarchy — How roles are inherited

System Administrator
    └── Organization Admin
        ├── Organization Member → Organization Read
        ├── Project Admin → Project Use, Update
        ├── Inventory Admin → Inventory Use, Ad Hoc, Update
        ├── Credential Admin → Credential Use
        ├── Job Template Admin → Execute
        └── Workflow Admin → Execute

System Auditor
    └── Organization Auditor → Read-only on everything in the org

Key point: If you're an org admin, you automatically get admin access to ALL resources within that organization. You don't need to add roles individually.

Watch out


Practical Examples

Give a user access to run a specific template

# 1. Find the role IDs on the template
curl -u admin:password \
  https://forge.example.com/api/v2/job_templates/5/ \
  | jq '.summary_fields.object_roles'

# 2. Assign execute_role (e.g., ID 43) to user (ID 7)
curl -u admin:password -X POST \
  -H 'Content-Type: application/json' \
  -d '{"id": 7}' \
  https://forge.example.com/api/v2/roles/43/users/

Give a team admin access to an inventory

# Find the admin_role ID on the inventory, then assign the team
curl -u admin:password -X POST \
  -H 'Content-Type: application/json' \
  -d '{"id": 3}' \
  https://forge.example.com/api/v2/roles/55/teams/

Create a read-only auditor user

curl -u admin:password -X POST \
  -H 'Content-Type: application/json' \
  -d '{"username": "auditor", "password": "Pass123!", "is_system_auditor": true}' \
  https://forge.example.com/api/v2/users/

Check what access a user has

# All roles for a user
curl -u admin:password https://forge.example.com/api/v2/users/7/roles/

# Can the user launch a template?
curl -u user7:password https://forge.example.com/api/v2/job_templates/5/launch/
# 200 = yes, 403 = no execute_role

Watch Out — Common Mistakes

  1. Forgotten organization. You create a template but the user can't see it. Check that the user has at least member_role on the organization.

  2. LDAP remove_users: true. This will remove users from the organization if they're not in the LDAP group. The user can lose access to everything. Start with false until you test.

  3. OAuth2 token for SSO users. By default, SSO users CANNOT create OAuth2 tokens. Enable ALLOW_OAUTH2_FOR_EXTERNAL_USERS if needed.

  4. Session timeout. Default is 30 minutes. For users who work longer sessions, increase SESSION_COOKIE_AGE via the API.