eswald
eswald

Reputation: 8406

Is there a good SimpleSAMLphp SLO example?

One of our clients is requesting that we implement Single Logout (SLO) through SAML. Their side of the SAML service is the Identity Provider, while ours is the Service Provider. Single-Signon (SSO) works by validating the user's credentials with the client's IdP, then redirecting the user to a login page on yet another platform, with a token that lets them log straight in. That platform knows absolutely nothing about SAML, and in particular doesn't share the SimpleSAMLphp session state.

Logout needs to happen two ways, though:

I'm able to convince our platform to redirect the user to an arbitrary page on logout, so I think the first part can be achieved by a page that uses SimpleSAML_Auth_Simple::getLogoutURL().

Such a page might also work when hit from the IdP side, but the SAML specs are complicated enough that I can't be sure until we try it. However, the SP configuration in config/authsources.php doesn't accept a SingleLogoutService parameter; the metadata as produced by /www/module.php/saml/sp/metadata.php/entityid still lists /www/module.php/saml/sp/saml2-logout.php/entityid as the SingleLogoutService location. If that page is necessary for clearing the SimpleSAMLphp session, that's fine, but I need to know how to slip in the extra redirects required for logging the user out of our platform.

I've tried searching for examples, but all I get is API references. It would also be nice to know how I can test logout without attempting to set up my own IdP; is there a service like the openidp.feide.no that handles SLO as well as SSO?

Upvotes: 12

Views: 12225

Answers (2)

Michael Leiss
Michael Leiss

Reputation: 5670

public function logout()
    {
        $timeNotOnOrAfter = new \DateTime();
        $timeNow = new \DateTime();

        $timeNotOnOrAfter->add(new DateInterval('PT' . 2 . 'M'));

        $context = new \LightSaml\Model\Context\SerializationContext();
        $request = new \LightSaml\Model\Protocol\LogoutRequest();
        $request
            ->setID(\LightSaml\Helper::generateID())
            ->setIssueInstant($timeNow)
            ->setDestination($this->_helper->getSloServiceUrl())
            ->setNotOnOrAfter($timeNotOnOrAfter)
            ->setIssuer(new \LightSaml\Model\Assertion\Issuer($this->_helper->getSpEntityId()));

        $certificate = \LightSaml\Credential\X509Certificate::fromFile($this->_helper->getSpCertFile());
        $privateKey = \LightSaml\Credential\KeyHelper::createPrivateKey($this->_helper->getSpPemFile(), '', true);

        $request->setSignature(new \LightSaml\Model\XmlDSig\SignatureWriter($certificate, $privateKey));

        $serializationContext = new \LightSaml\Model\Context\SerializationContext();

        $request->serialize($serializationContext->getDocument(), $serializationContext);

        $serializationContext->getDocument()->formatOutput = true;
        $xml = $serializationContext->getDocument()->saveXML();


        Mage::log($xml);

        $bindingFactory = new \LightSaml\Binding\BindingFactory();
        $redirectBinding = $bindingFactory->create(\LightSaml\SamlConstants::BINDING_SAML2_HTTP_REDIRECT);

        $messageContext = new \LightSaml\Context\Profile\MessageContext();
        $messageContext->setMessage($request);

        return $redirectBinding->send($messageContext);

    }

Finally do:

$httpResponse = $this->logout();
$this->_redirectUrl($httpResponse->getTargetUrl());

Upvotes: -1

smartin
smartin

Reputation: 3047

SLO Issue

Imagine this scheme:

Plattform -- SP1 ----- IdP ----- SP2----- App

Plattform and Apps are connected with simpleSAMLphp SP, that also forms a federation with a IdP.

You must find the normal log out function of Platffom, app1 and app2 and rewrite it:

normal_app_logout() {

 // code of the normal logout
 ....
 ....

 // new code

 require_once('<path-to-ssp>/simplesamlphp/lib/_autoload.php');   //load the _autoload.php
 $auth = new SimpleSAML_Auth_Simple('default-sp');  // or the auth source you using at your SP
 $auth->logout();   <--- call to the SLO 
}

This will end local session, the SP session connected to this application, the IdP session and the SP sessions of the SPs connected to the IdP but... what happen to the others apps session? They will still be active. You thought about an active call to end it but I think is better if you also override the "is_logged_in()" function that many app implement.

You must override this function and only return true if exists also a valid SP session active using the function

$auth->isAuthenticated()

Recently I implemented this functionality on the Wordpess SAML plugin, check the code

IdP Issue

Use Onelogin free trial , you can register your SP there and use its IdP. Follow this guide to configure your SAML connectors

But I think that you better may try to build a IdP by yourself. There is a nice documentation and the steps are easy. Use "example-userpass" authsource if you dont want to waste time configuring a database/ldap.

Also you can set your actual simplesamlphp instance as SP & IdP but i think that if you are learning simplesamlphp better dont mix.

Upvotes: 2

Related Questions