Skip to main content
Version: 0.8

SSO group to role mappings

Audience: TokenTimer Enterprise system administrators configuring SSO against an existing IdP.

Group-to-role mappings let you assign TokenTimer roles to users based on their IdP group membership. They live under System Settings → Single Sign-On in the dashboard and are evaluated on every SSO login.

Concepts

TermMeaning
Provider slugStable identifier for the SSO provider row (e.g. entra, okta). Each mapping is bound to one slug.
IdP groupThe string TokenTimer matches against the user's group claims (case-insensitive).
Roleadmin, workspace_manager, or viewer.
WorkspaceRequired when admin is not the role, but accepts NULL to make the grant global across every workspace. admin is always system-wide and rejects a workspace_id.
PriorityInteger in [1, 1000], default 100. Display ordering only today; reserved for future tie-breaking. Out-of-range values are rejected.

Decision rules

  1. Group names are lowercased before comparison so DevOps and devops match the same mapping.
  2. Highest role wins per workspace for workspace_manager and viewer mappings. The SSO admin role is system-wide: it sets users.is_admin and grants Workspace Manager (not workspace Admin) on every existing workspace at login.
  3. Global non-admin mappings. A workspace_manager or viewer mapping with workspace_id = NULL (UI: "All workspaces") grants that role across every workspace. It still loses to a more specific same-workspace mapping at higher precedence.
  4. Admin is sticky. Removing the mapping does not demote an existing system admin. Revoke from Workspaces → Members → System admin (requires an authenticated system admin).
  5. Strict membership sync (opt-in; global default in System Settings → Single Sign-On, or per-provider override) revokes SSO-derived workspace memberships that are no longer mapped. Manual invitations (source=manual) are never revoked.
  6. System-admin expansion adds missing workspace_manager access on every workspace and may raise viewer to workspace_manager where needed. It never downgrades an existing workspace admin membership and never revokes manual memberships.

Worked example: bind devops to admin

  1. Open System Settings then Single Sign-On.
  2. Click Add mapping.
  3. Fill in:
    • Provider: your OIDC provider slug (e.g. keycloak)
    • IdP group: devops
    • Role: Admin (system-wide)
    • Workspace: leave blank (admin role is global)
  4. Save. The next login from a devops-group user will promote them to system admin (users.is_admin = TRUE).

They join the shared Default workspace as manager, not workspace owner, unless they are the first user on an empty install (creates Default as owner). System admin and workspace owner are documented in the Authentication model.

Worked example: workspace-scoped viewer

  1. Click Add mapping.
  2. Provider: your SAML provider slug, IdP group: eng-london, Role: Viewer, Workspace: London.
  3. Save. London engineers logged in via SAML now have read-only access to the London workspace.

Worked example: separate teams per workspace

IdP groupRoleWorkspace
tt-platform-adminsadmin (global)-
devopsworkspace_managerInfrastructure
security-teamworkspace_managerSecurity
data-engworkspace_managerData
everyoneviewerInfrastructure

A user in both devops and everyone ends up as workspace_manager on Infrastructure thanks to the highest-role-wins rule.

Worked example: global viewer (every workspace)

  1. Add mapping.
  2. Provider: your OIDC provider slug, IdP group: staff, Role: Viewer, Workspace: leave blank ("All workspaces").
  3. Save. Every user in the staff group gets read-only access to every workspace on their next login.
info

The Group mappings UI defaults the workspace dropdown to the first workspace and shows a warning banner if you explicitly pick "All workspaces", because it is a powerful blast radius. The warning is informational; the mapping still saves.

Strict membership sync

Strict sync removes SSO-derived memberships when the IdP no longer asserts the mapped group. Enable it globally under System Settings → Single Sign-On → Installation-wide SSO policy, or override per provider under Manage SSO providers → Advanced (inherit / enabled / disabled). Helm / env equivalent: SSO_STRICT_MEMBERSHIP_SYNC=true.

What gets revoked:

  • Workspace memberships with source='sso' whose workspace is not in the current resolution.

What does NOT get revoked:

  • Manual invitations (source='manual').
  • System admin (sticky for safety).

Audit log: each revocation writes one row of action MEMBERSHIP_SYNCED_FROM_SSO with metadata.change = 'revoked', metadata.reason = 'strict_membership_sync'.

Bootstrap admin groups (IaC shortcut)

config.bootstrap_admin_groups (or config.admin_groups) on a provider row supplies a deploy-time shortcut for the common "this AD group is admin" case, useful for IaC pipelines that need to seed admin access before any human ever logs in:

"config": {
"bootstrap_admin_groups": "tt-platform-admins,sre-leads"
}

They are injected as virtual admin / workspace_id=NULL mappings at resolution time. They are not stored in the group mappings table. Anything more nuanced (workspace-scoped, viewer/manager roles) belongs in System Settings → Single Sign-On.

Audit log actions

ActionEmitted when
SSO_GROUP_MAPPING_CREATEDAdmin adds a mapping from the UI/API.
SSO_GROUP_MAPPING_UPDATEDAdmin edits a mapping.
SSO_GROUP_MAPPING_DELETEDAdmin deletes a mapping.
MEMBERSHIP_SYNCED_FROM_SSOA login resulted in an actual change to users.is_admin or workspace_memberships. One row per change. Idempotent: a login that resolves to the same grants as last time does not emit rows.
LOGIN_SUCCESS (metadata)idp_groups_seen, idp_groups_sample (up to 20 group values), matched_groups (array), matched_groups_count, admin_granted, workspace_grants_count, workspace_revocations_count.

Troubleshooting

Users in my admin group aren't getting admin.

Check the LOGIN_SUCCESS audit row. idp_groups_seen shows how many groups the IdP emitted; idp_groups_sample lists up to 20 raw values TokenTimer parsed from the assertion. matched_groups shows how many matched a mapping. If idp_groups_seen is 0, your IdP isn't emitting groups, or the claim path is wrong. Check Claim mapping.

For Entra SAML, group claims often carry object IDs (GUIDs), not display names. Map the exact string from idp_groups_sample, and sign out and back in after editing a mapping.

For Keycloak, groups are not in the token until you add a Group Membership mapper on the OIDC client and assign users to groups in the realm. Follow Option B in the Keycloak guide (sections 4 and 9), then log out and sign in again. Quick SQL check:

SELECT metadata->>'idp_groups_seen', metadata->'matched_groups'
FROM audit_events
WHERE action = 'LOGIN_SUCCESS' AND metadata->>'method' = 'oidc'
ORDER BY id DESC LIMIT 1;

Also confirm the mapping uses System Admin (global) (workspace_id NULL) for system-wide admin, not workspace-scoped manager/viewer roles only.

Strict-sync removed a user's manual workspace membership.

Strict-sync only touches rows where source='sso'. If a manual row was removed, check the audit log for MEMBERSHIP_REMOVED from a human admin. The schema guarantees manual rows are skipped.

Admin role is gone after disabling a mapping.

It shouldn't be. Admin is sticky on this code path. If a user lost admin through SSO sync, the audit row MEMBERSHIP_SYNCED_FROM_SSO will show change = 'admin_revoked' (impossible by design; please file a bug).