When the IdP redirects the user's browser back to my test script (same_sp.php) my script receives four cookies (two I set, XDEBUG_SESSION and PHPSESSID) and two POST values with the keys "RelayState" and "SAMLResponse".
SAMLResponse is the following, base64 encoded:
<?xml version="1.0" encoding="UTF-8"?>
<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="http://www.my_host.com/passport/saml_sp.php" ID="id19876001351288363577195108" InResponseTo="_aec320c144cf4e413ba11900c7f2f15797c034d35e" IssueInstant="2017-03-30T18:57:20.494Z" Version="2.0"> <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">
</saml2:Issuer>
<ds:SignedInfo>
<ds:Reference URI="#id19876001351288363577195108">
<ds:Transforms>
</ds:Transforms>
<ds:DigestValue>
n0+uijHcGL25JGZmIyzoi6vrd/ivCdxBobDknMbK2A4=
</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>
(removed for brevity)
</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>
(removed for brevity)
v </ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
<saml2p:Status xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol">
<saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
</saml2p:Status>
<saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="id198760013513164641170398949" IssueInstant="2017-03-30T18:57:20.494Z" Version="2.0">
<saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
</saml2:Issuer>
<ds:SignedInfo>
<ds:Reference URI="#id198760013513164641170398949">
<ds:Transforms>
</ds:Transforms>
<ds:DigestValue>
ozWxaJa84FzGXP3rkDP2vPm2SsbThOQ1mObq6G5Svkg=
</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>
(removed for brevity)
</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>
(removed for brevity)
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
<saml2:Subject xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
<saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">
128
</saml2:NameID>
<saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
</saml2:SubjectConfirmation>
</saml2:Subject>
<saml2:Conditions NotBefore="2017-03-30T18:52:20.494Z" NotOnOrAfter="2017-03-30T19:02:20.494Z" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
<saml2:AudienceRestriction>
<saml2:Audience>
passport
</saml2:Audience>
</saml2:AudienceRestriction>
</saml2:Conditions>
<saml2:AuthnStatement AuthnInstant="2017-03-30T18:57:20.494Z" SessionIndex="_aec320c144cf4e413ba11900c7f2f15797c034d35e" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
<saml2:AuthnContext>
<saml2:AuthnContextClassRef>
urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
</saml2:AuthnContextClassRef>
</saml2:AuthnContext>
</saml2:AuthnStatement>
</saml2:Assertion>
</saml2p:Response>"
In the SimpleSAML_Auth_Simple class the requireAuth method is called. This method first calls SimpleSAML_Session::getSessionFromRequest() which returns a session object. It then calls the session object's isValid() method with $authority = "default-sp". The session object's authData property is an empty array, but this method expects it to contain an element where the key = "default-sp". As a result it logs the "Session: default-sp not valid because we are not authenticated." DEBUG message and returns FALSE.
The session object looks like this:
$sessionobject [SimpleSAML_Session]
$session::sessions = array[1]
$session::instance = null
$session->sessionId = "b76d8dfe63c585526bd377be8bf3322d"
$session->transient = 0
$session->trackid = "275751ad4c"
$session->authority = null
$session->rememberMeExpire = null
$session->dirty = 0
$session->dataStore = array[2]
$session->dataStore['SimpleSAML_Auth_State'] = array[8]
$session->dataStore['core_postdatalink'] = array[4]
$session->associations = array[0]
$session->authToken = null
$session->authData = array[0]
Because the session object's isValid() method returned false the session object's login() method is called and the cycle starts again. The data sent from the SP to the IdP is reflected in the log output I included in my original post.
I have set the logging to its most detailed level (DEBUG) and have stepped through the code using Atom's PHP Debugging function, and still can't decipher what is going wrong. Any suggestions regarding where I should be looking are greatly appreciated.