doc/administration/geo/replication/single_sign_on.md
{{< details >}}
{{< /details >}}
This documentation only discusses Geo-specific SSO considerations and configuration. For more information on general authentication, see GitLab authentication and authorization.
Instance-wide SAML must be working on your primary Geo site.
You only configure SAML on the primary site. Configuring gitlab_rails['omniauth_providers'] in gitlab.rb in a secondary site has no effect. The secondary site authenticates against the SAML provider configured on the primary site. Depending on the URL type of the secondary site, additional configuration might be needed on the primary site.
How you configure instance-wide SAML differs depending on your secondary site configuration. Determine if your secondary site uses a:
external_url exactly matches the external_url of the primary site.If you have configured SAML on the primary site correctly, then it should work on the secondary site without additional configuration.
[!note] When proxying is enabled, SAML can only be used to sign in the secondary site if your SAML Identity Provider (IdP) allows an application to have multiple callback URLs configured. Check with your IdP provider support team to confirm if this is the case.
If a secondary site uses a different external_url to the primary site, then configure your SAML Identity Provider (IdP) to allow the secondary site's SAML callback URL. For example, to configure Okta:
https://gitlab-primary.example.com/users/auth/saml/callback. If it is not, enter your primary site's SAML callback URL into this field.https://gitlab-secondary.example.com/users/auth/saml/callback. You can set Index to anything.You must not specify assertion_consumer_service_url in the SAML provider configuration in gitlab_rails['omniauth_providers'] in gitlab.rb of the primary site. For example:
gitlab_rails['omniauth_providers'] = [
{
name: "saml",
label: "Okta", # optional label for login button, defaults to "Saml"
args: {
idp_cert_fingerprint: "B5:AD:AA:9E:3C:05:68:AD:3B:78:ED:31:99:96:96:43:9E:6D:79:96",
idp_sso_target_url: "https://<dev-account>.okta.com/app/dev-account_gitlabprimary_1/exk7k2gft2VFpVFXa5d1/sso/saml",
issuer: "https://<gitlab-primary>",
name_identifier_format: "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"
}
}
]
This configuration causes:
/users/auth/saml/callback as their assertion consumer service (ACS) URL.You can check this by visiting each site's /users/auth/saml/metadata path. For example, visiting https://gitlab-primary.example.com/users/auth/saml/metadata may respond with:
<md:EntityDescriptor ID="_b9e00d84-d34e-4e3d-95de-122e3c361617" entityID="https://gitlab-primary.example.com"
xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
<md:SPSSODescriptor AuthnRequestsSigned="false" WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat>
<md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://gitlab-primary.example.com/users/auth/saml/callback" index="0" isDefault="true"/>
<md:AttributeConsumingService index="1" isDefault="true">
<md:ServiceName xml:lang="en">Required attributes</md:ServiceName>
<md:RequestedAttribute FriendlyName="Email address" Name="email" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" isRequired="false"/>
<md:RequestedAttribute FriendlyName="Full name" Name="name" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" isRequired="false"/>
<md:RequestedAttribute FriendlyName="Given name" Name="first_name" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" isRequired="false"/>
<md:RequestedAttribute FriendlyName="Family name" Name="last_name" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" isRequired="false"/>
</md:AttributeConsumingService>
</md:SPSSODescriptor>
</md:EntityDescriptor>
Visiting https://gitlab-secondary.example.com/users/auth/saml/metadata may respond with:
<md:EntityDescriptor ID="_bf71eb57-7490-4024-bfe2-54cec716d4bf" entityID="https://gitlab-primary.example.com"
xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
<md:SPSSODescriptor AuthnRequestsSigned="false" WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat>
<md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://gitlab-secondary.example.com/users/auth/saml/callback" index="0" isDefault="true"/>
<md:AttributeConsumingService index="1" isDefault="true">
<md:ServiceName xml:lang="en">Required attributes</md:ServiceName>
<md:RequestedAttribute FriendlyName="Email address" Name="email" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" isRequired="false"/>
<md:RequestedAttribute FriendlyName="Full name" Name="name" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" isRequired="false"/>
<md:RequestedAttribute FriendlyName="Given name" Name="first_name" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" isRequired="false"/>
<md:RequestedAttribute FriendlyName="Family name" Name="last_name" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" isRequired="false"/>
</md:AttributeConsumingService>
</md:SPSSODescriptor>
</md:EntityDescriptor>
The Location attribute of the md:AssertionConsumerService field points to gitlab-secondary.example.com.
After configuring your SAML IdP to allow the secondary site's SAML callback URL, you should be able to sign in with SAML on your primary site as well as your secondary site.
If you have configured SAML on the primary site correctly, then it should work on the secondary site without additional configuration.
If you use an OpenID Connect (OIDC) OmniAuth provider, in most cases, it should work without an issue:
If you use LDAP on your primary site, the same LDAP configuration also applies to the secondary site because the secondary proxies requests related to authentication to the primary.
To prepare for disaster recovery scenarios, you should set up secondary LDAP servers on each secondary site. In this case, when you promote the secondary, users will be able to authenticate using the replica LDAP service. Otherwise, if the LDAP service connected to the primary site is not available to the promoted secondary site, users won't be able to perform Git operations over HTTP(s) on the secondary site using HTTP basic authentication. However, users can still use Git with SSH and personal access tokens, unless their account is locked from multiple failed login attempts when the LDAP service is unavailable.
[!note] It is possible for all secondary sites to share an LDAP server, but additional latency can be an issue. Also, consider what LDAP server is available in a disaster recovery scenario if a secondary site is promoted to be a primary site.
Check your LDAP service documentation for instructions on how to set up replication in your LDAP service. The process differs depending on the software or service used. For example, OpenLDAP provides this replication documentation.