docs: Clarify groups_attribute placement for SAML group sync
What does this MR do?
GitLab reads groups_attribute at the provider level of
gitlab_rails['omniauth_providers'], as a sibling of name and label. Placed inside the
provider's args hash it is never read, so SAML group sync does not run. Nothing surfaces
the mistake: users sign in normally, the assertion still carries the groups, and no error or
warning is written.
The documentation does not state the rule. doc/integration/saml.md says to "add a
groups_attribute: element to your SAML settings", which does not distinguish the provider
level from args. doc/user/group/saml_sso/group_sync.md shows a correct example but does
not name the rule the example embodies, so a reader adapting their own configuration has
nothing to check against. There is no troubleshooting entry for the resulting symptom.
This MR:
- Adds a placement callout in
doc/integration/saml.mdwheregroups_attributeis introduced, covering the rest of the provider-level family too (required_groups,external_groups,admin_groups,auditor_groups). - Names the placement rule beside the existing GitLab Self-Managed configuration example in
doc/user/group/saml_sso/group_sync.md. - Adds a troubleshooting entry in
doc/user/group/saml_sso/troubleshooting.mdfor the symptom "group links configured, assertion carries the groups, nothing syncs", with the cause, the fix, and a log check to confirm the fix took.
Why the behavior is silent
On master:
lib/gitlab/auth/saml/config.rbresolves the setting asdef groups; options[:groups_attribute]; end, whereoptionsisGitlab::Auth::OAuth::Provider.config_for(@provider), the provider hash itself. A key insideargsis therefore unreachable.ee/lib/ee/gitlab/auth/saml/config.rbgatesgroup_sync_enabled?ongroups.present?.ee/lib/gitlab/auth/saml/membership_updater.rbenqueuesAuth::SamlGroupSyncWorkeronly when that gate passes. There is no else branch and no log line, so a misplaced key produces no output at all.
Reproduction
The behavior follows from the master source quoted above and does not turn on a release. I
also confirmed it by measurement, on a GitLab 19.x Enterprise Edition Linux package
installation with an Ultimate license, against a single SAML provider emitting a multi-valued
groups attribute, with seven SAML group links configured across several top-level groups.
Configuration that does not work:
gitlab_rails['omniauth_providers'] = [
{
name: 'saml',
label: 'Example SSO',
args: {
assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml/callback',
idp_cert_fingerprint: '43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8',
idp_sso_target_url: 'https://idp.example.com/protocol/saml',
issuer: 'https://gitlab.example.com',
name_identifier_format: 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',
groups_attribute: 'groups'
}
}
]Observed: sign-in succeeds and creates the account. The assertion carries the groups
attribute with the expected values. audit_json.log records the system_access sign-in entry
and contains no Auth::SamlGroupSyncWorker entries. Group memberships are unchanged. No error
is shown to the user and no warning is logged.
Configuration that works, differing only in where groups_attribute sits:
gitlab_rails['omniauth_providers'] = [
{
name: 'saml',
label: 'Example SSO',
groups_attribute: 'groups',
args: {
assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml/callback',
idp_cert_fingerprint: '43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8',
idp_sso_target_url: 'https://idp.example.com/protocol/saml',
issuer: 'https://gitlab.example.com',
name_identifier_format: 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress'
}
}
]Observed after sudo gitlab-ctl reconfigure and the same sign-in: memberships appear exactly
as the group links define them, Auth::SamlGroupSyncWorker entries appear in
audit_json.log, and a later group removal at the identity provider propagates to GitLab
membership removal at the next sign-in.
Related issues
Related to #534702 Related to #388185
#388185 proposes defaulting the value so the setting is harder to get wrong, and states that
groups_attribute "can be misplaced". This MR documents the current behavior and does not
close that proposal.
Author's checklist
- Optional. Consider taking the GitLab Technical Writing Fundamentals course.
- Follow the:
- If you're adding a new page, add the product availability details under the H1 topic title.
- If you are a GitLab team member, request a review based on:
- The documentation page's metadata.
- The associated Technical Writer.
If you are a GitLab team member and only adding documentation, do not add any of the following labels:
~"frontend"~"backend"~"type::bug"~"database"
These labels cause the MR to be added to code verification QA issues.
Reviewer's checklist
Documentation-related MRs should be reviewed by a Technical Writer for a non-blocking review, based on Documentation Guidelines and the Style Guide.
If you aren't sure which tech writer to ask, use roulette or ask in the #docs Slack channel.
- If the content requires it, ensure the information is reviewed by a subject matter expert.
- Technical writer review items:
- Ensure docs metadata is present and up-to-date.
- Ensure the appropriate labels are added to this MR.
- Ensure a release milestone is set.
- If relevant to this MR, ensure content topic type principles are in use, including:
- The headings should be something you'd do a Google search for. Instead of
Default behavior, say something likeDefault behavior when you close an issue. - The headings (other than the page title) should be active. Instead of
Configuring GDK, say something likeConfigure GDK. - Any task steps should be written as a numbered list.
- If the content still needs to be edited for topic types, you can create a follow-up issue with the docs-technical-debt label.
- The headings should be something you'd do a Google search for. Instead of
- Review by assigned maintainer, who can always request/require the reviews above. Maintainer's review can occur before or after a technical writer review.
AI-Generated Content Disclosure: This MR was prepared with assistance from Claude Code. Every
factual claim was verified against master source, both configurations were confirmed on a
GitLab Self-Managed instance, and the wording was checked against the documentation style
guide.