Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

jesse_orange_newable's avatar

Laravel SAML IDP initiated Single Sign On

I have a Laravel application in which I need to add functionality to enable SAML Single Sign On. To achieve this I'm using this package: https://github.com/codegreencreative/laravel-samlidp

The package does literally everything I need bar one thing.

For my purposes I need to trigger the SSO from my Laravel application (the IdP) and have been reading up on it,

Essentially in my app there will be a big button that says "Go to Service Provider X".

I'm just not really sure how to start this process?

Looking at the SingleSignOn job in the package here - https://github.com/codegreencreative/laravel-samlidp/blob/master/src/Jobs/SamlSso.php - its evident that this is based on an SP initialised flow.

I'd be interested in whether anyone knows of any documentation as all of the documentation I've read on IdP initialised SSO leads to more questions than answers.

If I can get on the right track I'm hoping to merge this ability into the above package.

0 likes
5 replies
atit1979's avatar

Hi Have you resolved this issue, I am also looking to implement this functionality where my laravel application will act as idp. Any help would be great. Thanks

jesse_orange_newable's avatar

Hi,

The package itself is great but I had to use my own controller in the end.

<?php
namespace App\Http\Controllers\Saml;

use App\Http\Controllers\Controller;
use App\Traits\PerformsSingleSignOn;
use Illuminate\Http\Request;
use LightSaml\Model\Context\DeserializationContext;
use LightSaml\Model\Protocol\AuthnRequest;
use LightSaml\SamlConstants;
use Log;

class ServiceProviderLoginController extends Controller
{
    use PerformsSingleSignOn;

    /**
     * Initialise a new constructotr instance.
     */
    public function __construct()
    {
        // $this->init();
        // $this->authnRequest = new AuthnRequest;
    }

    /**
     * Attempt to log into a given Service Provider.
     *
     * @return void
     */
    public function login(Request $request)
    {
        $samlRequest = $request->get('SAMLRequest');
        $decodedXml = base64_decode($samlRequest);

        $deserializationContext = new DeserializationContext();
        $deserializationContext->getDocument()->loadXML($decodedXml);

        $this->authnRequest->deserialize($deserializationContext->getDocument()->firstChild, $deserializationContext);

        $this->destination = 'https://services-uk.sungarddx.com/SingleSignOn/ServiceProvider';

        return $this->samlResponse();
    }

    /**
     * Send a SAML message to the intended Service Provider with security assertions and other bearer assertions.
     * In this case we're explicitly sending email and name id
     *
     * @link https://www.lightsaml.com/LightSAML-Core/Cookbook/How-to-make-Response/
     *
     * @return void
     */
    public function samlResponse()
    {
    //     // Create a new SAML Response instance
        $this->response = new \LightSaml\Model\Protocol\Response();

        // Create a response object that we'll send later.
        $this->response
            ->addAssertion($assertion = new \LightSaml\Model\Assertion\Assertion())
            ->setStatus(
                new \LightSaml\Model\Protocol\Status(
                    new \LightSaml\Model\Protocol\StatusCode(
                        \LightSaml\SamlConstants::STATUS_SUCCESS
                    )
                )
            )
            ->setID(\LightSaml\Helper::generateID())
            ->setIssueInstant(new \DateTime())
            ->setDestination($this->destination)
            ->setIssuer(new \LightSaml\Model\Assertion\Issuer($this->issuer))
            ->setInResponseTo($this->authnRequest->getId());

        // Build out our Assertion instance
        $assertion
            ->setId(\LightSaml\Helper::generateID())
            ->setIssueInstant(new \DateTime())
            ->setIssuer(new \LightSaml\Model\Assertion\Issuer($this->issuer))
            ->setSignature(new \LightSaml\Model\XmlDSig\SignatureWriter($this->certificate, $this->private_key))
            ->setSubject(
                (new \LightSaml\Model\Assertion\Subject())
                    ->setNameID(new \LightSaml\Model\Assertion\NameID(
                        auth()->user()->email,
                        \LightSaml\SamlConstants::NAME_ID_FORMAT_EMAIL
                    ))
                    ->addSubjectConfirmation(
                        (new \LightSaml\Model\Assertion\SubjectConfirmation())
                            ->setMethod(\LightSaml\SamlConstants::CONFIRMATION_METHOD_BEARER)
                            ->setSubjectConfirmationData(
                                (new \LightSaml\Model\Assertion\SubjectConfirmationData())
                                ->setInResponseTo($this->authnRequest->getId())
                                ->setNotOnOrAfter(new \DateTime('+1 MINUTE'))
                                ->setRecipient($this->authnRequest->getAssertionConsumerServiceURL())
                            )
                    )
            )
            ->setConditions(
                (new \LightSaml\Model\Assertion\Conditions())
                    ->setNotBefore(new \DateTime())
                    ->setNotOnOrAfter(new \DateTime('+1 MINUTE'))
                    ->addItem(
                        new \LightSaml\Model\Assertion\AudienceRestriction([$this->authnRequest->getIssuer()->getValue()])
                    )
            )
            ->addItem(
                (new \LightSaml\Model\Assertion\AttributeStatement())
                    ->addAttribute(new \LightSaml\Model\Assertion\Attribute(
                        \LightSaml\ClaimTypes::EMAIL_ADDRESS,
                        auth()->user()->email,
                    ))
                    ->addAttribute(new \LightSaml\Model\Assertion\Attribute(
                        \LightSaml\ClaimTypes::NAME_ID,
                        auth()->user()->id,
                    ))
            )
            ->addItem(
                (new \LightSaml\Model\Assertion\AuthnStatement())
                    ->setAuthnInstant(new \DateTime('-10 MINUTE'))
                    ->setSessionIndex(\LightSaml\Helper::generateID())
                    ->setAuthnContext(
                        (new \LightSaml\Model\Assertion\AuthnContext())
                            ->setAuthnContextClassRef(\LightSaml\SamlConstants::AUTHN_CONTEXT_WINDOWS)
                    )
            );

        return $this->send(SamlConstants::BINDING_SAML2_HTTP_POST);
    }
}
Cheecheeey's avatar

@jesse_orange_newable Hi, I am implementing SAML to my app and I am fairly new to it. I have trouble with my Service Provider though. which sp are you using?

Please or to participate in this conversation.