Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for IdP initiated proxy SLO #1553

Open
wants to merge 16 commits into
base: master
Choose a base branch
from

Conversation

m0ark
Copy link
Contributor

@m0ark m0ark commented Jan 6, 2022

Problem

SimpleSAMLphp was not designed to support protocol proxy setups. Fortunately it supports a lot of those use cases.
One particular feature that has always been missing in proxy scenarios is the capability to properly propagate logout (SLO) requests coming from an upstream identity provider. This is because of SimpleSAMLphp IdPs using its SPs as authentication sources. In case of an IdP initiated logout the proxy SP is notified about the logout request and terminates its session properly without knowing about components it has been used by and thus cannot propagate the logout request to.
The result of this behaviour is the users IdP receiving a logout response telling the SLO has properly finished but the proxy IdP(s) still having an active session.

This issue has been discussed in #65 and @relaxnow made a great job implementing a first draft to tackle it (relaxnow@35cffcc).
Nevertheless this implementation was way too tightly coupled to SAML components and lacked a proper differentiation between multiple identity providers.

Solution

This patch is based on the work of @relaxnow and adds a small framework for adding IdP initiated proxy SLO capabilities. It also implements the framework for SAML SPs and SAML/ADFS IdPs to support proxy SLO flows using frontend channels.
It should be possible to add proxy SLO capabilities to other IdP/SP protocol implementations (e.g. OIDC, CAS) using this framework without much of a hassle.

To not break the current behaviour proxy SLO has to be activated by setting
‘proxyLogoutEnable’ => true
in each SP configuration.

Components of the framework

registerAsConsumerLogoutCallback
To be called by an authentication source consumer (e.g. IdP). The callback should handle everything that is needed to logout the consumer from its own perspective. In case of an IdP this could be logging out of all associated SPs; in case of a PHP application this could terminate the application local session.
hasAsConsumerLogoutCallbacks
Check if authentication source consumer logout callbacks have been registered for this source.
callAsConsumerLogoutCallbacks
To be called by a regular authentication source logout routine (e.g. SAML SP SLO handler) to trigger execution of the registered logout callbacks.
handleAsConsumerLogoutCallbacks
Only used by callAsConsumerLogoutCallbacks and the returnTo page that is called in case of the callback not returning immediately (e.g. redirecting, etc).

Copy link
Member

@thijskh thijskh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi! Thanks for the thorough PR.

I have not reviewed it line by line (yet), did add a few observations. And I notice the base branch is simplesamlphp-1.19. It seems unlikely that we'd merge such a feature there and rather target master.

lib/SimpleSAML/IdP.php Outdated Show resolved Hide resolved
modules/saml/lib/Auth/Source/SP.php Outdated Show resolved Hide resolved
@m0ark
Copy link
Contributor Author

m0ark commented Jan 19, 2022

Thanks for your first review.
I implemented this change using the version we used in production. So I just wanted to discuss the probability of having the PR accepted first before putting in more effort and porting this change to master.

Copy link
Member

@thijskh thijskh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've checked the code and believe it to be OK. However, I don't have a lot of experience with the scenario in question nor do I have a representative environment. So I'd like to add the caveat that I have not verified it to actually work myself. If you use this in actual production I'd be quite confident to merge it though.

Did you give any consideration as to whether at least some basic tests could be added for this?

lib/SimpleSAML/Auth/Source.php Outdated Show resolved Hide resolved
lib/SimpleSAML/Auth/Source.php Outdated Show resolved Hide resolved
lib/SimpleSAML/Auth/Source.php Outdated Show resolved Hide resolved
$lr->setInResponseTo($message->getId());

if ($numLoggedOut < count($sessionIndexes)) {
\SimpleSAML\Logger::warning('Logged out of ' . $numLoggedOut . ' of ' . count($sessionIndexes) . ' sessions.');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this a warning?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's just a copy of the working code of saml2-logout.php.
I think it is not expected to have any active session indexes left of the current SLO request after reaching this point.

@m0ark
Copy link
Contributor Author

m0ark commented Jan 24, 2022

Thank you for your thorough review and your helpful annotations.

Do you have any pointers on where to add tests for this code?

For an environment just create a simple SAML proxy and trigger an IdP initiated SLO request.
Without enabling this feature the logout request will not propagate to the proxy IdP component.

image

@tvdijen
Copy link
Member

tvdijen commented Jan 25, 2022

Also closes #1565

@tvdijen tvdijen closed this Jan 25, 2022
@tvdijen tvdijen reopened this Jan 25, 2022
@tvdijen tvdijen linked an issue Jan 25, 2022 that may be closed by this pull request
@tvdijen tvdijen changed the base branch from simplesamlphp-1.19 to master January 26, 2022 00:02
@codecov
Copy link

codecov bot commented Jan 26, 2022

Codecov Report

Merging #1553 (bcb357c) into master (b7e26e3) will decrease coverage by 0.24%.
The diff coverage is 1.47%.

Additional details and impacted files
@@             Coverage Diff              @@
##             master    #1553      +/-   ##
============================================
- Coverage     44.09%   43.85%   -0.25%     
- Complexity     3680     3696      +16     
============================================
  Files           156      156              
  Lines         10889    10951      +62     
============================================
+ Hits           4802     4803       +1     
- Misses         6087     6148      +61     

@@ -484,9 +520,11 @@ public function handleLogoutRequest(array &$state, ?string $assocId): void
$id = Auth\State::saveState($state, 'core:Logout:afterbridge');
$returnTo = Module::getModuleURL('core/idp/resumelogout.php', ['id' => $id]);

$this->authSource->logout($returnTo);
if (!$skipAsLogout) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to see strict comparison here


if ($assocId !== null) {
if ($assocId !== null || $skipAsLogout) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And here

@tvdijen
Copy link
Member

tvdijen commented Jan 26, 2022

I hope I didn't break anything, but I've rebased the lot against master..

@thijskh
Copy link
Member

thijskh commented Jan 26, 2022

I think the rebasing was not entirely accurate, at least i've spotted the reintroduction of this code: https://github.com/simplesamlphp/simplesamlphp/pull/1553/files#diff-60baa677d9f59b02cd5b3bbd371583dc05eccd0cb0bb74f2003398031fd84f8dR109-R111

@tvdijen
Copy link
Member

tvdijen commented Jan 26, 2022

Good catch! I've fixed that.. Something else that needs to change is the www-script.. It should be converted to a Controller

@tvdijen
Copy link
Member

tvdijen commented Jul 19, 2023

I'm not sure how to fix the conflicts in src/SimpleSAML/IdP.php because the code has been refactored for Symfony responses

@tvdijen tvdijen force-pushed the master branch 5 times, most recently from 7587851 to d523b31 Compare August 2, 2023 11:58
@tvdijen tvdijen force-pushed the master branch 3 times, most recently from 8c90121 to d534e3b Compare September 5, 2023 08:09
@tvdijen tvdijen force-pushed the master branch 2 times, most recently from bc1c5c8 to d0a5974 Compare October 17, 2023 21:17
@tvdijen tvdijen force-pushed the master branch 3 times, most recently from ccb9b02 to 120a100 Compare December 1, 2023 14:34
@tvdijen tvdijen force-pushed the master branch 2 times, most recently from 6004a77 to 58bf8db Compare May 4, 2024 23:45
@tvdijen tvdijen force-pushed the master branch 2 times, most recently from 5c9fb2c to 0970efc Compare May 27, 2024 12:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ADFS IdP loads metadata of disabled SAML IdP
3 participants