Architecture
Path-based SSO
Production setups usually protect only /user/login/sso on the web server.
sequenceDiagram
participant Browser
participant WebServer
participant Login as LoginController
participant Lookup as ServerVariableLookup
participant Validator as LoginValidatorSso
Browser->>WebServer: GET /user/login/sso
WebServer->>Login: Request with REMOTE_USER
Login->>Lookup: getAuthenticationNameFromServer
Lookup-->>Login: authname
Note over Login: Optional realm split / domain strip
Login->>Validator: setAuthname + processLogin
Validator-->>Login: Drupal user or failure
alt Success
Login-->>Browser: user_login_finalize + redirect
else Failure or missing REMOTE_USER
Login-->>Browser: sso_stop cookie + redirect to login
end
Access is anonymous-only (LoginController::access). Authenticated users get
403. The route is ldap_sso.login_controller, no_cache: TRUE.
Processing steps in LoginController::login:
- Read
ssoVariablevialdap_sso.server_variable. - If
ssoSplitUserRealm, splituser@realm. - If
ssoRemoteUserStripDomainName, strip@or\domain forms. - Call
ldap_authentication.login_validator_sso(LoginValidatorSso::processLogin()). - On success:
user_login_finalize(), optional status message, redirect to?destinationor<front>. - On failure: set
sso_stop, show an error, redirect toward login. - Always clear
sso_login_running.
Seamless SSO
When seamlessLogin is TRUE, LdapSsoBootSubscriber runs early on
KernelEvents::REQUEST (priority 30).
sequenceDiagram
participant Browser
participant Boot as LdapSsoBootSubscriber
participant Login as LoginController
Browser->>Boot: Anonymous GET /some/path
alt CLI, logged in, seamless off, excluded, or sso_stop
Boot-->>Browser: Continue normal request
else Should SSO
Boot-->>Browser: 302 /user/login/sso?destination=... + sso_login_running
Browser->>Login: GET /user/login/sso
Note over Login: Same path-based flow
Login-->>Browser: Session + redirect to destination
end
Skips when:
PHP_SAPI === 'cli'- User already authenticated
seamlessLoginis false- Path or host is excluded (defaults + config)
- Cookie
sso_stopis present - Cookie
sso_login_runningis present (abort to avoid loops)
Hardcoded excluded paths:
/admin/config/search/clean-urls/check/user/login/sso/user/login/user/logout/user
Logout
ldap_sso_user_logout() in ldap_sso.module:
- If seamless login is on, set
sso_stop(lifetime fromcookieExpire). - If
redirectOnLogout, send aRedirectResponsetologoutRedirectPath.
Key classes
| Class | Path |
|---|---|
Drupal\ldap_sso\Controller\LoginController |
src/Controller/LoginController.php |
Drupal\ldap_sso\LdapSsoBootSubscriber |
src/LdapSsoBootSubscriber.php |
Drupal\ldap_sso\ServerVariableLookup |
src/ServerVariableLookup.php |
Drupal\ldap_sso\RedirectResponseWithCookie |
src/RedirectResponseWithCookie.php |
Drupal\ldap_sso\Form\LdapSsoAdminForm |
src/Form/LdapSsoAdminForm.php |
Drupal\ldap_authentication\Controller\LoginValidatorSso |
(ldap_authentication) |
Services
Defined in ldap_sso.services.yml:
| Service ID | Class |
|---|---|
logger.channel.ldap_sso |
Logger channel |
ldap_sso.boot |
LdapSsoBootSubscriber (event subscriber) |
ldap_sso.server_variable |
ServerVariableLookup |
External dependency used by the controller:
ldap_authentication.login_validator_sso.