Skip to content

Step-up auth: Require oauth provider for groups [PART 2.0]

What does this MR do and why?

This merge request extends the existing step-up authentication functionality for admin mode to support namespace (group) scope. It implements Part 2.0 of the step-up authentication feature for groups, allowing administrators to require additional authentication before users can access certain group resources or perform specific actions within a group.

The motivation for this change is described in the issue. TLDR: Organizations require fine-grained access control where certain group resources or operations demand higher authentication assurance.

This feature enables:

  • Enhanced security for sensitive groups: Administrators can enforce step-up authentication for groups containing sensitive projects or data
  • Compliance requirements: Meet regulatory requirements that mandate additional authentication for accessing certain resources
  • Flexible security policies: Allow different authentication requirements for different groups based on their security classification
  • The implementation follows the same pattern as the existing admin mode step-up authentication but extends it to the namespace/group level, providing a consistent user experience across different security contexts.

🛠️ with ❤️ at Siemens

References

MR acceptance checklist

Please evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

MR Checklist (@gerardo-navarro)

Screenshots or screen recordings

Scenario: Successful step-up auth challenge

2025-07-23-step-up-auth-for-groups-successful-scenario

This scenario shows what happens when the step-up auth challenge is successful:

  1. The screencast starts with a clean session in a private browser window.
  2. The user performs a normal sign in via the OIDC omniauth provider (this is not the step-up auth).
  3. After the "normal" sign in, the user goes to a step-up auth unprotected group; GitLab behaves as usual and allows the user to access the group and its resources
  4. Now, the user tries to access a step-up auth protected group and is asked for a reauthentication. This reauthentication can only be achieved through a step-up authentication.
  5. The use clicks on the button "OpenID Connect" and is redirected to the IdP server (Keycloak) to perform a step-up authentication. Note: In case of this screencast, the step-up auth method is configured to be a second password prompt, but in production, it would be a more secure auth method, e.g. fingerprint, device trust, etc.
  6. Successful step-up auth challenge implemenation 👍
  7. Now, the user is able to access the group's resources
Click to expand the step-up auth config in `config/gitlab.yml`
- { name: "openid_connect",
    # ...
    args: {
      name: "openid_connect",
      # ...
    },
    step_up_auth: {
      namespace: {
        id_token: {
          required: {
            acr: 'gold' 
          }
        },
        params: {
          claims: { 
            id_token: { 
              acr: { 
                essential: true,
                values: ['gold'] 
              } 
            } 
          }
        }
      }
    }
  }

Scenario: Rejected step-up auth challenge

This scenario shows what happens when the step-up auth challenge is rejected because the user is not able to fulfill the step-up auth criteria , i.e. the required acr value must be gold, but the authorization parameters wants Keycloak to authenticate the user with the acr value silver 💥.

2025-07-24-step-up-auth-rejected

This scenario shows what happens when the step-up auth challenge is successful:

  1. We adjust the gitlab.yml in a way to still require the acr value gold for accessing groups, but we also adjust the step-up auth params and request the acr level silver. This means that the idp will authenticate the user, but only to acr level silver (which is lower than acr level gold).
  2. Then we restart the rails server
  3. Again, the user access the step-up auth protected group and and get lap shows that step up authentication is required.
  4. The user clicks on the button "OpenID Connect" to trigger the step up authentication flow. Note: The IdP checks the user and authenticates the user successfully because the requested acr value silver is the default permission in the test keycloak instance.
  5. User is be directed back to get lap, but without having reached the required ACR value gold. 💥
Click to expand the step-up auth config in `config/gitlab.yml`
- { name: "openid_connect",
    # ...
    args: {
      name: "openid_connect",
      # ...
    },
    step_up_auth: {
      namespace: {
        id_token: {
          required: {
            acr: 'gold' 
          }
        },
        params: {
          claims: { 
            id_token: { 
              acr: { 
                essential: true,
                values: ['silver'] 
              } 
            } 
          }
        }
      }
    }
  }

How to set up and validate locally

Part 1: Configure step-up auth in Keycloak

  1. Please follow the steps described in a previous MR .

Part 2: Prepare your local GitLab gdk instance

  1. In your local gdk instance, add the following omniauth configuation to the config/gitlab.yml, see collapsed section below
  2. Enable the feature flag :omniauth_step_up_auth_for_namespace via the rails console
    Feature.enable(:omniauth_step_up_auth_for_namespace)
  3. Create a simple GitLab group that we want to protect with step-up auth. Also create a subproject that we use for testing purposes.
  4. Set the attribute step_up_auth_required_oauth_provider in the group namespace setting to the value openid_connect (<= the name of the provider we have set up in the gitlab config)
    Group.find(<recently_created_group_ip>).namespace_settings.update(step_up_auth_required_oauth_provider: 'openid_connect')
Click to expand the `config/gitlab.yml`
development:
  <<: *base
  omniauth:
    allow_bypass_two_factor:  ["openid_connect"]
    allow_single_sign_on: ["openid_connect"]
    auto_link_ldap_user: null
    auto_link_saml_user: null
    auto_link_user: ["openid_connect"]
    auto_sign_in_with_provider: 
    block_auto_created_users: false
    external_providers: []

    providers:
    - { name: "openid_connect",
        label: "[OIDC] Keycloak",
        args: {
          name: "openid_connect",
          # strategy_class: "OmniAuth::Strategies::OpenIDConnect",
          scope: ["openid", "profile", "email"],
          response_type: "code",
          issuer: "http://localhost:8080/realms/step-up-auth-gitlab-realm",
          client_auth_method: "query",
          discovery: false,
          uid_field: "preferred_username",
          pkce: true,
          allow_authorize_params: ["claims"],
          client_options: {
            host: "localhost",
            scheme: "http",
            port: "8080",
            identifier: "step-up-auth-gitlab-client",
            secret: "C6S2b1ZkifZa6BI8Jy5K3lz2Eglb4JuQ",
            redirect_uri: "http://gdk.test:3000/users/auth/openid_connect/callback",
            authorization_endpoint: "/realms/step-up-auth-gitlab-realm/protocol/openid-connect/auth",
            token_endpoint: "/realms/step-up-auth-gitlab-realm/protocol/openid-connect/token",
            userinfo_endpoint: "/realms/step-up-auth-gitlab-realm/protocol/openid-connect/userinfo",
            jwks_uri: "http://localhost:8080/realms/step-up-auth-gitlab-realm/protocol/openid-connect/certs",
            end_session_endpoint: "/realms/step-up-auth-gitlab-realm/protocol/openid-connect/logout"
          }
        },
        step_up_auth: {
          admin_mode: {
            # ...
          },
          namespace {
            id_token: {
              required: {
                acr: 'gold' 
              }
            },
            params: {
              claims: { 
                id_token: { 
                  acr: { 
                    essential: true, 
                    values: ['gold'] 
                  } 
                } 
              }
            }
          },          
        }
      }

Part 3: Test the step-up auth for group

  1. Open a private browser window (fresh session)
  2. Go to the usual sign in page: http://gdk.test:3000/users/sign_in
  3. Use the configured Keycloak OIDC omniauth provider to sign in; you will be redirected to Keycloak sign in interface
  4. In Keycloak, submit the username and password; Note: this is the normal sign in for the user (think of it as the first step and not the step-up auth)
  5. After a successful sign in, the user will be redirected to it's dashboard
  6. Go to the step-up auth protected group (created in before).
  7. You should be redirected to an authentication page where you are asked to select
  8. Sign in with the button "[OIDC] Keycloak"; Note: this is a special omniauth sign-in button that will trigger the step-up auth on the side of the IdP
  9. In Keycloak, you will be asked to authenticate for a higher step (acr level gold); Note: this is the additional step that requires higher authentication, i.e. the step-up auth
  10. After the successful second "stepped-up" sign in, the user will be redirected back to the step-up auth protected group and is able to access all aspects of the group

Related to #474650 #556943

Edited by Gerardo Navarro

Merge request reports

Loading