Step-up auth: Expiration validation - Basic core and UI [PART 1]
-
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 receive complimentary access to GitLab Duo.
What does this MR do and why?
Step-up auth: Add basic OIDC expiration validation
Currently, step-up authentication sessions do not validate OIDC token expiration claims. This means that sessions can remain active even after the underlying OIDC ID token has expired, leading to potential security issues.
This commit introduces basic expiration validation. It implements extraction and validation of OIDC token expiration claims to ensure step-up sessions respect Identity Provider timeframes.
- Extract exp claim from OIDC ID tokens during authentication flow
- Store expiration timestamps in step-up session data
- Add expiry validator to check session validity
- Provide comprehensive test coverage for expiration scenarios
Changelog: other
References
Screenshots or screen recordings
Scenario: Step-up auth session expires after 15 seconds
Screen_Recording_2025-08-08_at_08.47.12
The screencast demonstrates the following authentication flow:
-
Keycloack configuration: Show the key confguration settings for testing the expiration date, e.g.
Max Age
setting in the browser auth flow,Access Token Lifespan
in the realm settings is set to 15 seconds => these are important for the local testing guide below - Step-up auth sign in: After the initial sign in, the user wants to access the admin mode and is redirected to the IdP (Keycloak) in order to perform the step up auth challenge
-
Admin mode / area during the lifespan: After the step-up auth challenge has succeeded, the user has 15 seconds to access in the admin area (watch the timer
😉 ) - Step-up auth session expires: After the 15 seconds, the user is "kicked out" of the admin area and receives the notice that the step-up auth session has expired, see screenshot below.
- Expiration Validation • After reloading the page • User should be logged out or required to re-authenticate • This occurs because the step-up authentication has expired
How to set up and validate locally
Part 1: Configure step-up auth in Keycloak
- Follow the steps to set up step-up authentication in Keycloak; Note: Usually the default expiration time for a Keycloak is set to 5 Min. But, this is too long for testing.
- For testing purposes, we want to reduce the expiration time to 15 - 30 seconds for easier testing (so that we do not need to wait that long).. We can do this in Keycloak by navigating to the realm settings, going to the tab
Tokens
and ther you will find the settingAccess Token Lifespan
. Set it to 15 seconds. See screenshot below. - Ensure the in the broswer auth flow, the "Max Age" for the step-up auth condition is set to 10 (=> which means that step-up authentiocatoin weill be triggered shortly after in keycloak)
Part 2: Prepare your local GitLab gdk instance
-
Please follow the steps described in another MR to enable admin mode, create an admin user, enable feature flag and configure the step-up auth setting properly in the
gitlab.yml
. - As part of this MR, I recommend using the step up of configuration from the collapse section below.
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']
}
}
}
}
},
}
}
Part 3: Test the expriation validation
- Access admin area: Sign in and navigate to admin area - you'll be redirected to Keycloak for step-up auth, then back to GitLab.
-
Test expiration validation:
- Stay in the admin area and wait 15+ seconds for the token to expire (Note: We have set up the 15 second lifespan as part of a previous step)
- Refresh the page or navigate to another admin page
- Expected: You should be logged out from the admin area with an expiration notice (as shown in the screencast)
-
Verify expiration behavior:
-
✅ Sessions expire after configured time (15 seconds) -
✅ Users see expiration notice and are redirected -
✅ Non-admin areas remain accessible after step-up expiration -
✅ Re-authentication works properly after expiration
-
The core validation is that the StepUpSessionExpiryValidator
correctly detects expired OIDC tokens and transitions step-up sessions to expired state, forcing re-authentication for protected areas.
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.
Related to #545965