OIDC Workspace Access
Map identity-provider groups to organization-wide roles or workspace-scoped roles when users sign in with OIDC.
This guide assumes builtin authentication with OIDC is already configured. OIDC/SSO for self-hosted Dagu requires an active self-host license.
Complete builtin admin setup before testing a mapping. Dagu does not allow OIDC login while the user store is empty, so an OIDC-mapped account cannot become the first user or bypass creation of the recovery administrator.
Configuration
The following example gives organization-wide access to Dagu administrators, limits the payments and SRE teams to their workspaces, and gives unmatched users no access to named workspaces:
auth:
mode: builtin
oidc:
role_mapping:
groups_claim: groups
group_mappings:
dagu-org-admins: admin
workspace_mappings:
payments-team:
- workspace: payments
role: developer
sre-team:
- workspace: infra
role: operator
default_workspace_access: none
role_attribute_strict: false
skip_org_role_sync: falseGroup names are exact and case-sensitive. Use the exact strings emitted in the ID token.
Evaluation order
Dagu evaluates mappings in this order:
- A valid
role_attribute_pathresult assigns that global role across all workspaces. - Otherwise, a matching
group_mappingsentry assigns a global role across all workspaces. If several groups match, the highest role wins. - Otherwise, all matching
workspace_mappingsgrants are merged. If several groups grant the same workspace, the highest role wins. - If nothing matches and
role_attribute_strictistrue, login is denied. - If nothing matches and strict mode is off,
default_workspace_accessdetermines the fallback.
Within one mapping type, role priority is admin, manager, developer, operator, then viewer.
Global mappings replace workspace mappings
A role_attribute_path or group_mappings match assigns one role across all workspaces and stops evaluation. For example, a user matching global viewer and workspace payments: developer receives global viewer; the workspace grant is not added. Do not use a catch-all global mapping when workspace isolation is intended.
Unmatched users
When strict mode is off, the fallback behaves as follows:
default_workspace_access | Result when no mapping matches |
|---|---|
all | Apply default_role across all workspaces |
none | Assign global viewer and no named workspace grants |
all is the compatible default only when workspace_mappings is empty. When workspace_mappings is non-empty, default_workspace_access is required and Dagu rejects the configuration if it is omitted. default_role is used only for an unmatched all fallback.
Use none when named workspaces must be isolated by default. Unlabelled DAGs remain governed by the global viewer role, so label resources that require workspace isolation.
Set role_attribute_strict: true when an unmapped user must not be allowed to sign in at all. Strict mode takes precedence over both fallback values.
Test every existing user before enabling strict mode
Strict mode applies on every OIDC login, including users that already exist in Dagu. If their current token no longer contains a matching role or workspace group, login is denied instead of retaining their previously stored authorization.
Workspace grant rules
- Workspace-scoped users always have global role
viewer. admincannot be assigned as a workspace-scoped role.- A group may grant access to multiple workspaces.
- Several groups may grant the same workspace; the highest role wins.
- A workspace does not need to exist when the mapping is configured. The grant remains dormant, login emits a warning, and creating the workspace later activates it.
Example with overlapping grants:
role_mapping:
groups_claim: groups
workspace_mappings:
engineering:
- workspace: platform
role: developer
on-call:
- workspace: platform
role: operator
- workspace: incidents
role: operator
default_workspace_access: noneA user in both groups receives developer in platform and operator in incidents.
Global mapping examples
Use group_mappings for groups that should have organization-wide access:
role_mapping:
groups_claim: groups
group_mappings:
dagu-admins: admin
dagu-auditors: viewer
default_role: viewer
default_workspace_access: noneFor advanced claim structures, role_attribute_path accepts a jq expression:
role_mapping:
role_attribute_path: >-
if (.groups | contains(["dagu-admins"])) then "admin"
elif (.groups | contains(["dagu-developers"])) then "developer"
else empty
endReturning empty allows evaluation to continue to group_mappings and workspace_mappings. Returning a valid role stops evaluation and grants that role globally.
Synchronization and user management
OIDC manages workspace access when workspace_mappings is non-empty or default_workspace_access is explicitly none.
With the default skip_org_role_sync: false:
- Role and workspace access are recomputed at every successful OIDC login.
- Manual API changes to an OIDC user's role or workspace access are overwritten at the next login.
- The users page marks the account Managed by SSO and makes role and workspace access read-only.
- Administrators can still rename, disable, re-enable, or delete the account.
- Existing sessions use the currently stored role and workspace access on their next request.
- An existing user is denied login if strict mapping no longer finds a match.
- If Dagu cannot save changed workspace authorization, login is denied and the previously stored policy remains unchanged.
Dagu learns about an IdP membership change only when an OIDC login runs. Once that login stores the new authorization, all existing Dagu sessions use it on their next request. Until another OIDC login occurs, an existing session can continue using the last stored authorization; the next login normally occurs when its Dagu JWT expires.
Set skip_org_role_sync: true to keep the authorization assigned at the user's first login. Subsequent logins do not update it, and the users page leaves role and workspace access editable.
OIDC users authenticate through the identity provider
OIDC users cannot sign in through the builtin password form, and administrators cannot set or reset their Dagu passwords. Keep recovery access in a separate builtin administrator account.
Configuration reference
| Field | Description | Default |
|---|---|---|
default_role | Role assigned across all workspaces when no mapping matches, strict mode is off, and default_workspace_access is all | viewer |
groups_claim | ID-token claim containing group membership | groups |
group_mappings | IdP group names mapped to global Dagu roles | None |
workspace_mappings | IdP group names mapped to workspace and role grant lists | None |
default_workspace_access | Unmatched-user fallback: all applies default_role globally; none denies access to named workspaces. Required when workspace_mappings is non-empty | all when workspace_mappings is empty |
role_attribute_path | jq expression for extracting a global role | None |
role_attribute_strict | Deny login when neither a global nor workspace mapping matches | false |
skip_org_role_sync | Keep first-login authorization instead of synchronizing on subsequent logins | false |
Environment variables
Workspace mappings use a JSON object whose keys are IdP groups:
export DAGU_AUTH_OIDC_WORKSPACE_MAPPINGS='{"payments-team":[{"workspace":"payments","role":"developer"}]}'
export DAGU_AUTH_OIDC_DEFAULT_WORKSPACE_ACCESS=noneSet both variables together. Supplying workspace mappings without an explicit fallback is rejected.
The JSON value must be one object. Unknown grant fields, malformed JSON, blank group names, empty grant lists, invalid workspace names, duplicate workspaces within a group, invalid roles, and workspace-scoped admin roles are rejected during configuration loading.
See the configuration reference for the remaining OIDC environment variables.
Provider guides
- Test workspace access locally with Keycloak
- Okta group claims
- Microsoft Entra ID group claims
- Keycloak group claims
Rollout checklist
- Create and verify a separate builtin recovery administrator.
- Decode a real test login's ID token and record the exact group values.
- Configure only the groups Dagu needs.
- Explicitly set
default_workspace_accesswhen usingworkspace_mappings, and decide whether unmatched users should receive all workspaces or no named workspaces. - Avoid catch-all global mappings when workspace isolation is required.
- Before enabling strict mode, test every existing OIDC user and confirm each token contains a matching value.
- Test a globally mapped user, each workspace group, overlapping groups, an unmapped user, malformed group claims, and membership revocation.
- Confirm unlabelled resources do not contain data that requires workspace isolation.

