Describe the bug
When using an authentication source based on UserPassOrgBase (e.g. ldap:LdapMulti) with remember.organization.enabled => true, the "Remember my organization" checkbox is shown and checked, but the <authsource>-organization cookie is never sent to the browser on a successful login. The organization choice is therefore not remembered on the next visit.
To Reproduce
- Configure an
ldap:LdapMulti authsource with remember.organization.enabled => true, remember.organization.checked => true, username_organization_method => none and a mapping of two orgs.
- Open the login page, select an organization, tick "Remember my organization", log in.
- Inspect the
Set-Cookie headers on the core/loginuserpassorg POST response.
Expected: a Set-Cookie: <authsource>-organization=<org>; expires=<1 year>; ... header.
Actual: only the standard SimpleSAML and SimpleSAMLAuthToken session cookies are sent; no -organization cookie.
Root cause
In modules/core/src/Controller/Login.php, handleLogin() collects the organization cookie into a local $cookies[] array, calls $source::handleLogin(...), and only attaches the cookies to the response at the very end of the method (foreach ($cookies ...) { $t->headers->setCookie(...) } return $t;).
On a successful authentication, UserPassOrgBase::handleLogin() (and the LdapMulti override) calls Auth\Source::completeAuth($state), which redirects and does not return. The foreach block and return $t that attach the cookies are therefore never executed, so the Set-Cookie header is never generated. The cookie is only ever attached on the failure path, where the template is re-rendered — which is why the choice is never remembered after a successful login.
Environment
- SimpleSAMLphp 2.x (master / 2.5.x-dev; the code path is identical in shipped 2.x releases)
- simplesamlphp-module-ldap 2.0.x (
ldap:LdapMulti)
- PHP 8.2
Suggested fix
The cookies must be emitted before $source::handleLogin() is invoked, since that call redirects and never returns on success.
Option A: emit the collected cookies onto the outgoing response right before the try { $source::handleLogin(...) } call instead of at the end of the method, keeping the Symfony Cookie abstraction.
Option B: set the organization cookie directly after it is rendered, before the redirect:
setcookie(
$source->getAuthId() . '-organization',
$organization,
[
'expires' => $expire,
'path' => '/',
'secure' => true,
'httponly' => true,
'samesite' => $sameSiteNone ?? 'Lax',
],
);
The same structural issue affects the remember-username cookie, which should be moved together with the organization cookie.
Describe the bug
When using an authentication source based on
UserPassOrgBase(e.g.ldap:LdapMulti) withremember.organization.enabled => true, the "Remember my organization" checkbox is shown and checked, but the<authsource>-organizationcookie is never sent to the browser on a successful login. The organization choice is therefore not remembered on the next visit.To Reproduce
ldap:LdapMultiauthsource withremember.organization.enabled => true,remember.organization.checked => true,username_organization_method => noneand amappingof two orgs.Set-Cookieheaders on thecore/loginuserpassorgPOST response.Expected: a
Set-Cookie: <authsource>-organization=<org>; expires=<1 year>; ...header.Actual: only the standard
SimpleSAMLandSimpleSAMLAuthTokensession cookies are sent; no-organizationcookie.Root cause
In
modules/core/src/Controller/Login.php,handleLogin()collects the organization cookie into a local$cookies[]array, calls$source::handleLogin(...), and only attaches the cookies to the response at the very end of the method (foreach ($cookies ...) { $t->headers->setCookie(...) } return $t;).On a successful authentication,
UserPassOrgBase::handleLogin()(and theLdapMultioverride) callsAuth\Source::completeAuth($state), which redirects and does not return. Theforeachblock andreturn $tthat attach the cookies are therefore never executed, so theSet-Cookieheader is never generated. The cookie is only ever attached on the failure path, where the template is re-rendered — which is why the choice is never remembered after a successful login.Environment
ldap:LdapMulti)Suggested fix
The cookies must be emitted before
$source::handleLogin()is invoked, since that call redirects and never returns on success.Option A: emit the collected cookies onto the outgoing response right before the
try { $source::handleLogin(...) }call instead of at the end of the method, keeping the SymfonyCookieabstraction.Option B: set the organization cookie directly after it is rendered, before the redirect:
The same structural issue affects the remember-username cookie, which should be moved together with the organization cookie.