SocialiteProviders / Providers

A Collection of Providers for Laravel Socialite
https://socialiteproviders.com
MIT License
495 stars 433 forks source link

SAML2, logout throws "unknown binding type" #978

Closed robertdeboer closed 11 months ago

robertdeboer commented 1 year ago

What:

When implementing the single sign out feature on the service provider as indicated here the application is throwing an "Unknown binding type" error instead of generating a SAML2 logout request and redirect.

When:

When implementing the single sign out

How:

Following the instructions in the SAML2 provider documentation, I have added the following in my routes/web.php file:

Route::get('/saml2/logout', [\App\Http\Controllers\Logout::class, 'logout']);

My Logout controller has a single function:

    public function logout()
    {
        /** @var \SocialiteProviders\Saml2\Provider $response */
        $response = Socialite::driver(self::DRIVER);
        return $response->logoutResponse();
    }

For testing purposes I omitted logging the user out locally.

What is expected:

The get call should result in a redirect to the single sign out URL as configured in my SAML configuration with the appropriately configured LogOut asssertion

What is wrong:

I am not quite sure. I have tracked the issue down to the BindingFactory.php processGet() function. It is looking for a request query that does not exists - the url given is a simple GET call to a URL with no additional data. The documentation does not give any additional setup instructions beyond some session cookie settings so nothing is every going to be given additionally. The URL provided by the application is what should start the single sign out request to the identity provider.

I may be missing something but I am not sure.

robertdeboer commented 1 year ago

@27pchrisl Have you had a change to look at this?

I have circled back to this and we have a upcoming corporate requirement to use single sign out on all applications soon.

Looking into this there appears to be a disconnect between calling for the logout response and getting the redirect response. It appears it expecting a GET query parameter of SAMLRequest or SAMLResponse but I'm not sure what exactly it is suppose to be as the documentation doesn't show anything beyond setting a simple route, updating config/services and then calling logoutResponse

27pchrisl commented 1 year ago

Hi @robertdeboer, sorry I had typed something here a few days ago but it seems to have been lost...

I didn't write the code for single logout, but it looks like it doesn't support SP-initiated SLO, only IDP-initiated. So it's expecting the flow to be started by the IDP, which would send a SAMLRequest to your logout endpoint. You'd then log out your local user session, and then return the message from logoutResponse().

robertdeboer commented 1 year ago

@27pchrisl

I have created an issue here with LiteSaml about this and when it is resolved, I should have a working implementation I can share

robertdeboer commented 1 year ago

@27pchrisl I was able to get this working by adding the following function to the \SocialiteProviders\Saml2\Providers file

    public function logoutRequest(string $nameId): HttpFoundationResponse
    {
        $identityProviderConsumerService = $this->getIdentityProviderEntityDescriptor()
            ->getFirstIdpSsoDescriptor()
            ->getFirstSingleLogoutService();

        $logoutRequest = new LogoutRequest();
        $logoutRequest
            ->setID(Helper::generateID())
            ->setIssueInstant(new DateTime())
            ->setDestination($identityProviderConsumerService->getLocation())
            ->setIssuer(new Issuer($this->getServiceProviderEntityDescriptor()->getEntityID()))
            ->setNameID(new NameID($nameId));

        return $this->sendMessage($logoutRequest, SamlConstants::BINDING_SAML2_HTTP_REDIRECT);
    }

The nameId parameter is what allows me to declare the user ID required by my SSO Logout configuration. This may change depending on how SSO Logouts are configured. Also, since I do not use sessions to hold SAML session data it cannot be pulled from the session

aleksanm commented 1 year ago

Hi. I also hope, that SLO will be implemented.

aleksanm commented 1 year ago

To this route Route::get('/saml2/logout', [\App\Http\Controllers\Logout::class, 'logout']); goes request from SP logout url to IDP and IDP cleans sessions and returns to this url Route::get('/saml2/logout', [\App\Http\Controllers\Logout::class, 'logout']); and returns $response->logoutResponse(); No errors.. So, SP first, logouts himself then sends logoutRequest to IDP, IDP responds with success message and You can dd($response->logoutResponse()); with success message... Did I understand it correct.. I created PR for logoutRequest