Child pages
  • Configuring a simpleSAMLphp SP for step-up authentication

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

  1. Configure a SimpleSAMLphp SAML 2.0 hosted SP named "default-sp" by following the instructions on https://simplesamlphp.org/docs/stable/simplesamlphp-sp
  2. Add the step-up gateway as SAML 2.0 identity provider to <simplesaml>/metadata/saml20-idp-remote.php. See below for configuration example.
  3. Put the sp.php example script below in the <simplesaml>/www directory

Note: depending on what environment you are using (Production, Pilot) you need to adapt the example code with the correct LoA identifiers (e.g. in $gLOAmap below). Different environments use different identifiers!

Code Block
languagephp
titlesp.php
<?php
// Include SimpleSAMLphp. Assume this script is placed in the <simplesaml>/www dir.
require_once('../lib/_autoload.php');

// Name of session variable for storing the min required LOA for a login
define( 'SSP_SESSION_MIN_LOA', 'RequestedMinLOA' );

// Build return URL. This is where ask simplesamlPHP to direct the browser to after login or logout
// Point to this script, but without any request parameters so we won't trigger an login again (and again, and again, and ...)
$returnURL = ($_SERVER['HTTPS'] == 'on') ? 'https://' : 'http://';
$returnURL .= $_SERVER['HTTP_HOST'];
$returnURL .= $_SERVER['SCRIPT_NAME'];

// Map integer level of assurance level to identifier used by the gateway
// Note: these identifiers differ between environments!
$gLOAmap = array(
    1 => 'http://suaas.example.com/assurance/loa1',
    2 => 'http://suaas.example.com/assurance/loa2',
    3 => 'http://suaas.example.com/assurance/loa3',
);

try {
    // Init SP instance
    // Assumes you have setup a SP named "default-sp" in <simplesaml>/config/authsources.php
    // See: https://simplesamlphp.org/docs/stable/simplesamlphp-sp
    $as = new SimpleSAML_Auth_Simple('default-sp');    // Init SP instance

    /** @var $session SimpleSAML_Session */
    $session = SimpleSAML_Session::getInstance();

    // Process login action. Assumes the login function of your SP uses ...?action=login
    if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'login' ) {

        // We use the SSP session to keep track of the LOA we want.
        // Unset any existing RequiredAuthnContextClassRef
        $session->deleteData('string', SSP_SESSION_MIN_LOA);

        // login
        $requiredLOA = 2; // The LOA we want.

        // Store the requested LOA in the session so we can verify it later
        $session->setData('string', SSP_SESSION_MIN_LOA, $requiredLOA);

        $as->login( array(
            'ReturnTo' => $returnURL,
            'ForceAuthn' => false,
            'saml:AuthnContextClassRef' => $gLOAmap[$requiredLOA]  // Specify LOA
        ) );


        exit;   // Never reached. Added for clarity
    }


    // Process logout action
    if( isset($_REQUEST['action']) && $_REQUEST['action'] == 'logout' ) {
        $as->logout( array (
            'ReturnTo' => $returnURL,
        ) );  // Process logout

        exit;   // Never reached. Added for clarity
    }


    // Display HTML page

    echo <<<head
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
        <head>
            <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
            <style type="text/css">
                table,th,td {border: 1px solid black;}
                th,td {padding 1px}
            </style>
            <title>simpleSAMLphp Demo</title>
        </head>
        <body>
            <h1>SimpleSAMLphp LOA Demo</h1>
head;

    // Show some info when authenticated
    if ( $as->isAuthenticated() ) {
        $attributes = $as->getAttributes();

        $requestedLoA = $session->getData('string', SSP_SESSION_MIN_LOA);    // What we requested during login
        $authState = $session->getAuthState();
        $authnConext = $authState['saml:sp:AuthnContext'];
        $nameID = $session->getNameID();
        $authnInstant = gmdate('r', $authState['AuthnInstant'] );
        $expire = gmdate('r', $authState['Expire'] );

        echo "<h2>You are logged in</h2>";

        echo "<h3>SimpleSAMLphp Session</h3>";
        echo "<p>SimpleSAMLphp session start: <b>{$authnInstant}</b></br />";
        echo "SimpleSAMLphp session expire: <b>{$expire}</b></p>";

        echo "<h3>LOA</h3>";
        echo "<p>Received authnConext: <b>{$authnConext}</b></p>";

        // Map LoA identifier back to integer LoA level
        $actualLoA = array_search($authnConext, $gLOAmap);
        if (false ==! $actualLoA)
            echo "<p>Actual LoA is: <b>{$actualLoA}</b></p>";
        else
            $actualLoA = -1;

        if (NULL !== $requestedLoA) {
            echo "<p>Requested LoA was: <b>{$requestedLoA}</b></p>";
            if ($actualLoA >= $requestedLoA)
                echo '<p><b>You were authenticated at or above the minimally required LoA</b></p>';
            else
                echo '<p><b>You were NOT authenticated at the required LoA</b></p>';
        }

        echo <<<html
        <h3>NameID</h3>
        <table>
            <tr><th>Value</th><td>{$nameID['Value']}</td></tr>
            <tr><th>Format</th><td>{$nameID['Format']}</td></tr>
        </table>
html;

        echo <<<html
        <h3>SAML Attributes</h3>
        <table>
            <tr><th>Attribute</th><th>Value(s)</th></tr>
html;
        foreach ($attributes as $attrName => $attrVal) {
            echo "<tr><td>{$attrName}</td><td>";
            if (is_array($attrVal))
                echo implode('<br />', $attrVal);
            else
                echo $attrVal;
            echo "</td>";
        }
        echo <<<html
        </table>

        <h3>Logout</h3>
        <p>
            <form name="logout" action="{$returnURL}" method="get">
               <input type="hidden" name="action" value="logout"/>
               <input type="submit" value="Logout" />
            </form>
        </p>
html;
    } else {
        echo <<<html
            <h2>Your are not logged in</h2>
html;
    }

    echo <<<html
            <h3>Login (again)</h3>
            <p>
                <form name="login" action="{$returnURL}" method="get">
                   <input type="hidden" name="action" value="login"/>
                   <input type="submit" value="Login" />
                </form>
            </p>
html;

    echo <<<html
        </body>
    </html>
html;
}
catch (Exception $e)
{
    echo $e->getFile().':'.$e->getLine().' : '.$e->getMessage();
}

...