Skip to content

Step-up auth: Add omniauth step-up auth for admin mode

  • Please check this box if this contribution uses AI-generated content (including content generated by GitLab Duo features) as outlined in the GitLab DCO & CLA. As a benefit of being a GitLab Community Contributor, you can request access to GitLab Duo.

What does this MR do and why?

Step-up authentication is a security feature that requires additional verification for accessing sensitive data or performing critical actions.

This commit introduces step-up authentication for the admin mode and includes the following aspects:

  • Extend configuration of omniauth providers in GitLab config gitlab.yml to allow the definition of required and included ID token claims.
  • Extract the ID token claims when the user signs in successfully through the omniauth provider
  • Check for required ID token claims and enforc step-up auth before accessing admin area
  • Hide feature behind feature flag :omniauth_step_up_auth_for_admin_mode
  • Extend documentation for step-up auth configuration

The sequence diagram in the collapsed section shows

Click to expand the
sequenceDiagram
    actor user as User
    participant gitlab as GitLab
    participant idp as IdP<br/>(e.g. Keycloak)

    user->>+gitlab: Signs into GitLab through the IdP
    gitlab->>+idp: authorize?...<br/>(without requesting step-up auth)
    Note over gitlab,idp: The step-up auth session hash is not set<br/>because step-up auth has not been initiated.
    idp->>-gitlab: callback? (id token claim does not )...
    Note over gitlab,idp: The step-up auth session does not exist.<br/>Hence, we can skip checking the id token claims<br/>regarding the step-up auth conditions.

    user->>+gitlab: Works in GitLab
    user->>+gitlab: Goes to the admin area<br/>Re-Authentication with step-up is required.
    Note left of gitlab: When accessing a route / resource in the admin area,<br/>we need to check the step-up auth session<br/>if the step-up auth has been successful.


    gitlab->>+idp: authorize?acr_values='gold'&...
    Note over gitlab,idp: The authorization request to the IdP includes<br/>the param that triggers the step-up authentication.<br/><br/>The step-up auth session is set<br/>because step-up auth has been requested.<br/>The step-up session includes<br/>the state of the step-up auth process.
    
    idp->>-gitlab: callback?...
    Note over gitlab,idp: The step-up auth session exists and<br/>the step-up auth state is set to "requested"<br/>(included in the step-up auth session).<br/>We need to check for the step-up auth conditions,<br/>i.e. do the required id token claims exists.

🛠️ with ❤️ at Siemens

References

Please include cross links to any resources that are relevant to this MR This will give reviewers and future readers helpful context to give an efficient review of the changes introduced.

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

Screencast: https://www.loom.com/share/dfc25a15b0944b8cbf03426ce8ab9ed6

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 wants to go to the admin area and is asked for a reauthentication. This reauthentication can only be achieved through a step-up authentication.
  4. 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.
  5. Successful step-up auth challenge implemenation
Click to expand the step-up auth config in `config/gitlab.yml`
step_up_auth: {
  admin_mode: {
    enabled: true,
    id_token: {
      required: {
        acr: 'gold' 
      }
    },
    params: {
      claims: { 
        id_token: { 
          acr: { 
            essential: true, 
            values: ['gold'] 
          } 
        } 
      }
    }
  }
}

Scenario: Failed step-up auth challenge

Screencast: https://www.loom.com/share/ba71ffdbcb0a4f0a9d928a00163d96ca

This scenario shows what happens when the step-up auth challenge fails because the omniauth config is misconfigured, i.e. the required acr value must be gold, but the authorization parameters wants Keycloak to authenticate the user with the acr value silver 💥.

Here are more information regarding the screencast:

  1. After a successful step-up authencation, the admin mode for the user is activated and the user can access the admin area.
  2. Then, we adjust the gitlab.yml to still require the acr value gold for accessing the admin mode, but we remove the section regarding the request query params that are necessary to trigger the step-up auth on the IdP side.
  3. This time, when we want to sign in to the admin area, the user is redirected to the IdP without the request param regarding the desired acr values => the IdP checks the user and authenticates the user successfully because no step-up is requested and needed
  4. The IdP redirects back to the GitLab and GitLab identifies that the user does not have the required acr value "gold" (that is required to access the GitLab admin area) => hence, GitLab shows the alert that a higher auth context (acr) is required, see screenshot
Click to expand the step-up auth config in `config/gitlab.yml`
step_up_auth: {
  admin_mode: {
    enabled: true,
    documentation_link: "https://openid.net/specs/openid-connect-core-1_0.html#IDToken",
    id_token: {
      required: {
        acr: 'gold' 
      }
    }
  }
}

How to set up and validate locally

Part 1: Configure step-up auth in Keycloak

  1. Start local keycloak instance using docker compose, see an examplary docker-compose.yml in collapsed section below
  2. Follow the steps to configure step-up auth in Keycloak; please look into the documentation section (oidc.md) that is part of this MR; this includes:
Click to see `docker-compose.yml`
---

services:
  keycloak:
    image: keycloak/keycloak:25.0
    command: start-dev --log-level="org.keycloak.authentication:TRACE"
    environment:
      KEYCLOAK_ADMIN: admin 
      KEYCLOAK_ADMIN_PASSWORD: admin
    ports:
      - 8080:8080
    volumes:
      - ./keycloak/data:/opt/keycloak/data
Click to see screenshot of my Keycloak configuration grafik

grafik

grafik

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. In GitLab, create a new admin user; Note that the user emails in GitLab and in Keycloak must match
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: {
            enabled: true,
            documentation_link: "https://openid.net/specs/openid-connect-core-1_0.html#IDToken",
            id_token: {
              required: {
                acr: 'gold' 
              }
            },
            params: {
              claims: { 
                id_token: { 
                  acr: { 
                    essential: true, 
                    values: ['gold'] 
                  } 
                } 
              }
            }
          },          
        }
      }
  1. Open the rails console and enable the feature flags :omniauth_step_up_auth_for_admin_mode
Feature.enable(:omniauth_step_up_auth_for_admin_mode)

Part 3: Test the step-up auth for admin mode

  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 reauthentication page for the admin area: http://gdk.test:3000/admin/session/new (this should be possible because the user is also an admin)
  7. Sign in with the button "[OIDC] Keycloak"; Note: this is a sepcial omniauth sign in button (as part of this POC) that will trigger the step-up auth => you will be redirected to Keycloak interface
  8. In Keycloak, you will be asked to authenticate for a higher step; Note: this is the additional step that requires higher authentication, i.e. the step-up auth
  9. After the successful second "stepped-up" sign in, the user will be redirected back to GitLab and the admin mode will be enabled

Related to #474650

Edited by Gerardo Navarro

Merge request reports

Loading