SP-initiated SSO to remote IdP server returns to wrong URL

1,606 views
Skip to first unread message

Tom Mount

unread,
Jul 10, 2014, 6:07:19 PM7/10/14
to simple...@googlegroups.com
I set up SimpleSAMLphp to connect to a client's PingFederate IdP server (my application needs to provide their users a way to use their internal SSO). So far so good - they have my metadata, I have theirs, and I configured an authsource that, from the "Test authentication sources" page, successfully loads up their SSO login page, validates the testing account they provided, and then comes back...to a completely different page in my app than I expected. I don't know enough about the SSO process to know whose fault this is and how to correct it. Here are my config files:

config/authsources.php:

'client-sp' => array(
    'saml:SP',
    'privatekey' => 'saml.pem',
    'certificate' => 'saml.crt',
    'entityID' => NULL,
    'idp' => 'https://client.idp.url',
    'discoURL' => NULL,
    'signature.algorithm' => 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
),

metadata/saml20-idp-remote.php:

$metadata['https://client.idp.url'] = array(
    'metadata-set' => 'saml20-idp-remote',
    'entityid' => 'https://client.idp.url',
    'SingleSignOnService' => array(
        0 => array(
            'Binding' => "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST", 
            'Location' => "https://client.idp.url/idp/startSSO.ping?PartnerSpId=http://my.app.url",
        ),
        1 => array(
            'Binding' => "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect",
            'Location' => "https://client.idp.url/idp/startSSO.ping?PartnerSpId=http://my.app.url",
        ),
    ),
    'certData' => 'etc'
    'NameIDFormat' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified',
);

Where the Feide OpenIdP authsource goes back to the page from which it was called (the "Test authentication sources" page, in this case), my configured authsource goes to what's listed as 'PartnerSpId' in the SSO location above. Changing that value in the metadata file breaks the entire process, so I'm guessing it's not getting the return URL from there. I've verified that my metadata has the following line:

<md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http:/my.app.url/simplesaml/module.php/saml/sp/saml2-acs.php/foo-sp" index="0"/>

From my (limited) understanding, the ACS URL is where the request should end up once it completes its round-trip from the IdP, right? So at this point I'm kind of stuck. I can't see what data their service is returning to me, because it's redirecting back to the wrong page. A secondary question is, ultimately that return URL needs to be dynamic and I can't just change the metadata every time a new request is sent out, so how do I ensure someone who goes to /admin/page3.php directly gets returned to /admin/page3.php rather than some arbitrary URL? I've used Chrome developer tools to see what requests are made, and I'm including the RelayState with my request, which should bring me back to the right page.

So my questions are: how do I control what page their service posts back to? And can that be dynamic or does it always have to go to a single page, at which point my app would need to manually redirect back to the actual page requested?

Peter Schober

unread,
Jul 10, 2014, 7:04:46 PM7/10/14
to simple...@googlegroups.com
* Tom Mount <tmou...@gmail.com> [2014-07-11 00:07]:
> I set up SimpleSAMLphp to connect to a client's PingFederate IdP server (my
> application needs to provide their users a way to use their internal SSO).
> So far so good - they have my metadata, I have theirs, and I configured an
> authsource that, from the "Test authentication sources" page, successfully
> loads up their SSO login page, validates the testing account they provided,
> and then comes back...to a completely different page in my app than I
> expected.

From that it's hard to know whether the SAML assertion from the IDP
actually was transmitted to your (Simple)SAML(php)'s
AssertionConsumerURL location.
Use e.g. the Firefox SAMLtracer extension to see what happens.

> config/authsources.php:
>
> 'client-sp' => array(
> > 'saml:SP',
> > 'privatekey' => 'saml.pem',
> > 'certificate' => 'saml.crt',
> > 'entityID' => NULL,
> > 'idp' => 'https://client.idp.url',
> > 'discoURL' => NULL,
> > 'signature.algorithm' =>
> > 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
> > ),

Looks OK. Personally I always set the entityID myself to a sane value.
The autogenerated ones don't look very stable to me and are long and ugly.

> metadata/saml20-idp-remote.php:
>
> $metadata['https://client.idp.url'] = array(
> > 'metadata-set' => 'saml20-idp-remote',
> > 'entityid' => 'https://client.idp.url',
> > 'SingleSignOnService' => array(
> > 0 => array(
> > 'Binding' => "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST",
> > 'Location' =>
> > "https://client.idp.url/idp/startSSO.ping?PartnerSpId=http://my.app.url",
> > ),
> > 1 => array(
> > 'Binding' =>
> > "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect",
> > 'Location' =>
> > "https://client.idp.url/idp/startSSO.ping?PartnerSpId=http://my.app.url",
> > ),
> > ),
> > 'certData' => 'etc'
> > 'NameIDFormat' =>
> > 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified',
> > );

OK. The SSO and SLO Locations are weird (making the endpoints on the
IDP specific to an SP) but that's probably just the way this
implementation works.
If "PartnerSpId" should be the entityID of your SP (as the name would
suggest to me) then this is probably not correct: Look at your SP's
admin interface to see what SSP autogenerates as its own SAML metadata
(unless you override it your authsources.php file).

> Where the Feide OpenIdP authsource goes back to the page from which it was
> called (the "Test authentication sources" page, in this case), my
> configured authsource goes to what's listed as 'PartnerSpId' in the SSO
> location above.

Trace the requests as described above to make sure where the SAML
response is being sent and who (the IDP or SSP after processing the
response) redirects you to the undesired URL.

> Changing that value in the metadata file breaks the entire
> process, so I'm guessing it's not getting the return URL from there. I've
> verified that my metadata has the following line:
>
> <md:AssertionConsumerService
> > Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
> > Location="http:/my.app.url/simplesaml/module.php/saml/sp/saml2-acs.php/foo-sp"
> > index="0"/>
>
> From my (limited) understanding, the ACS URL is where the request should
> end up once it completes its round-trip from the IdP, right?

Yes and no. The ACS URL is where the IDP sends the response with the
SAML protocol message to, with help from your web browser. I.e., it's
where your SimpleSAMLphp instance recieves and processes the SAML, and
where SimpleSAMLphp then decides to redirect you further.

The originally requested (protected) resource, where you ultimately
want to end up again is the 'RelayState', which the SP sets before all
the madness starts, which gets sent to the IDP and which the IDP must
return back to the SP verbatim, so the SP can then send you off to
your resource after all. So that's different from the ACS URL, as it's
your application/code/resource the subject wants to access.

And the entityID is a different URI again, it's a globally unique name
for your SAML entity.

You'd have to ask the IDP admin what kind of information the required
value for 'PartnerSpId' should be.

> So at this
> point I'm kind of stuck. I can't see what data their service is returning
> to me, because it's redirecting back to the wrong page.

You can, using browser plugins (or a logging proxy).

> A secondary question is, ultimately that return URL needs to be
> dynamic and I can't just change the metadata every time a new
> request is sent out, so how do I ensure someone who goes to
> /admin/page3.php directly gets returned to /admin/page3.php rather
> than some arbitrary URL?

No, only the entityID (the name of your SP) and the ACS URL (the
location where SimpleSAMLphp wants to recieve SAML protocol messages)
are in metadata, not the URLs of protected resources, which can be as
dynamic as you want them to be.

> I've used Chrome developer tools to see what requests are made, and
> I'm including the RelayState with my request, which should bring me
> back to the right page.

It should, if everything were correct.

> So my questions are: how do I control what page their service posts
> back to? And can that be dynamic or does it always have to go to a
> single page, at which point my app would need to manually redirect
> back to the actual page requested?

You don't need to control where they send the response to because
that's none of your concern, really, SimpleSAMLphp handles the
processing of SAML protocol messages on your behalf. What you (or your
SP) control is what happens /after/ SimpleSAMLphp has recieved the
SAML on its endpoint, has created a session with extracted attributes
and passes control back to your own code.
The ACS URL can (and usually should) be static.
The redirect to the originally requested URL should happen
automagically based on the RelayState value, and would be done by
SimpleSAMLphp.
-peter

Tom Mount

unread,
Jul 11, 2014, 4:24:26 PM7/11/14
to simple...@googlegroups.com
Thanks for the detailed response. Some of the inconsistencies you observed may have been from a few rounds of anonymizing. But I think the core of the issue is that the client's service is not respecting the RelayState value I'm sending (because I can watch through all the posts and redirects, and that value is consistently correct). I've got a meeting scheduled with their IT folks to review all the initial setup information I gave them. I'll know more after that call.

Peter Schober

unread,
Jul 11, 2014, 4:30:53 PM7/11/14
to simple...@googlegroups.com
* Tom Mount <tmou...@gmail.com> [2014-07-11 22:24]:
> But I think the core of the issue is that the client's service is
> not respecting the RelayState value I'm sending (because I can watch
> through all the posts and redirects, and that value is consistently
> correct).

Note that the IdP MUST return the RelayState verbatim, which you can
verify. If it's there together with the response, and it's the same
value as you sent before, it's an issue with your SP, otherwise
(missing or different value) it's an issue with the IdP.
-peter

Tom Mount

unread,
Jul 15, 2014, 11:47:49 AM7/15/14
to simple...@googlegroups.com, peter....@univie.ac.at
We got it sort of working - they basically grabbed a new copy of our metadata and recreated their configuration. So now their login form returns back to the SimpleSAMLphp control panel, but with an error:

SimpleSAML_Error_Error: UNHANDLEDEXCEPTION

Backtrace:
0 /var/simplesamlphp/www/module.php:180 (N/A)
Caused by: SimpleSAML_Error_Exception: No authentication source with id false found.
Backtrace:
2 /var/simplesamlphp/lib/SimpleSAML/Auth/Source.php:242 (SimpleSAML_Auth_Source::getById)
1 /var/simplesamlphp/modules/saml/www/sp/saml2-acs.php:8 (require)
0 /var/simplesamlphp/www/module.php:135 (N/A)
I've seen exactly one thread where this came up (well, three threads by the same two people), and it was magically fixed, but the idiots involved didn't bother to explain *how* they fixed it, which makes it useless as a support thread. 

In the meantime, by config files changed a little. Here's my authsource:

        'client-sp' => array(
                'saml:SP',
                'privatekey' => 'saml.pem',
                'certificate' => 'saml.crt',
                'entityID' => NULL,
                'idp' => 'idpserver.client.url:SAML2.0',
                'discoURL' => NULL,
                'signature.algorithm' => 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
        ),

And my metadata entry:

$metadata['idpserver.client.url:SAML2.0'] = array(
       'metadata-set' => 'saml20-idp-remote',
       'entityid' => 'https://idpserver.client.url',
       'SingleSignOnService' => array(
               0 => array(
                       'Binding' => "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST", 
               ),
               1 => array(
                       'Binding' => "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect",
               ),
       ),
       'certData' => '...'
       'NameIDFormat' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified',
);

Peter Schober

unread,
Jul 15, 2014, 12:26:03 PM7/15/14
to simple...@googlegroups.com
* Tom Mount <tmou...@gmail.com> [2014-07-15 17:47]:
> I've seen exactly one thread where this came up (well, three threads
> by the same two people), and it was magically fixed, but the idiots
> involved didn't bother to explain *how* they fixed it, which makes
> it useless as a support thread.

I feel you, but I'd still recommend not calling people idiots on this
list (no matter the circumstances).

> In the meantime, by config files changed a little. Here's my authsource:
>
> 'client-sp' => array(
> 'saml:SP',
> 'privatekey' => 'saml.pem',
> 'certificate' => 'saml.crt',
> 'entityID' => NULL,
> 'idp' => 'idpserver.client.url:SAML2.0',
> 'discoURL' => NULL,
> 'signature.algorithm' =>
> 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
> ),

The value of the 'idp' key looks very weird (and is not a valid
entityID as the spec mandates, this needs to be of type anyURI and a
URI starts with a registered scheme) but if that's the name of the IDP
and no software you depend on trips over this, you'll likely have to
live with it.

> And my metadata entry:
>
> $metadata['idpserver.client.url:SAML2.0'] = array(
> 'metadata-set' => 'saml20-idp-remote',
> 'entityid' => 'https://idpserver.client.url',

About this I' not so sure. I thought the metadata array key /is/ the
entityID and if you specified it below again (for whatever reason) it
would need to match verbatim? Anyway, if it were wrong you wouldn't
even be sent to the IDP's SSO URL, so it's either an artifact of email
censoring or just a convention.

> 0 => array(
> 'Binding' =>
> "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST",
> 'Location' =>
> "https://idpserver.client.url/idp/startSSO.ping?PartnerSpId=https://myapp.url/simplesaml/module.php/saml/sp/metadata.php/client-sp",
> ),
> 1 => array(
> 'Binding' =>
> "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect",
> 'Location' =>
> "https://idpserver.client.url/idp/startSSO.ping?PartnerSpId=https://myapp.url/simplesaml/module.php/saml/sp/metadata.php/client-sp",
> ),
> ),
> 'certData' => '...'
> 'NameIDFormat' =>
> 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified',
> );

That still has those weird SP-specific endpoints but other than that
it looks OK.
-peter

Peter Schober

unread,
Jul 15, 2014, 12:35:43 PM7/15/14
to simple...@googlegroups.com
* Tom Mount <tmou...@gmail.com> [2014-07-15 17:48]:
> SimpleSAML_Error_Error: UNHANDLEDEXCEPTION
>
> Backtrace:
> 0 /var/simplesamlphp/www/module.php:180 (N/A)
> Caused by: SimpleSAML_Error_Exception: No authentication source with id false found.

Just to be on the safe side: Why don't you make up a nice, short
entityID for your SP (see
https://wiki.shibboleth.net/confluence/display/SHIB2/EntityNaming for
education/inspiration), e.g. "https://yourservice.example.org/saml2"
and set that in your authsource (instead of NULL)?

(If you wanted your entityID to resolve to a copy of your own SAML
metadata -- which is fully optional, an entitID is just a name, not a
location -- you could do that with a simple webserver redirect or a
PHP one-liner setting the 'Location' header to the URL where
SimpleSAMLphp servies up your metadata.)

The IDP will need to re-import your metadata then (or adjust the
changed entityID some other way) and the SP-specific locations in your
saml20-idp-remote.php will also change (another reason why it's weird
to encode the SP's entityID into the IDP metadata).

The value of the PartnerSpId request parameter (i.e. your entityID)
also should be urlencoded, again, to be on the safe side.

None of this might fix your problem, of course.
-peter

Tom Mount

unread,
Jul 15, 2014, 12:55:37 PM7/15/14
to simple...@googlegroups.com, peter....@univie.ac.at
Perhaps not an idiot, but at the very least unhelpful, if not inconsiderate. 

I'll create a non-resolving entityID and have them create a new configuration profile based off the new metadata. Perhaps a 3-way conference call between me, the client, and PingFederate could be useful? I get the feeling this is a "blind leading the blind" situation.

Aneel Sarwar

unread,
Aug 8, 2014, 4:16:15 AM8/8/14
to simple...@googlegroups.com, peter....@univie.ac.at
How did you solved this problem?

SimpleSAML_Error_Exception: No authentication source with 
id false found. 

Tom Mount

unread,
Aug 8, 2014, 9:39:57 AM8/8/14
to simple...@googlegroups.com, peter....@univie.ac.at
What it ended up being on my end was a misconfigured saml20-idp-remote.php file. I didn't realize there was a tool on the Federated Identity page to import a metadata XML file and spit out an entry for the metadata file. Once I did that, the problem went away. I'm not sure which specific change solved the problem, but that was my solution.
Reply all
Reply to author
Forward
0 new messages