NoState error after Login -> Logout -> Login after setting session.cookie.domain

651 views
Skip to first unread message

casey....@tasktop.com

unread,
Feb 23, 2017, 2:15:17 PM2/23/17
to SimpleSAMLphp

I’m encountering an issue with SimpleSAMLphp you may be able to help me resolve.

Previously, I had simply let `session.cookie.domain’ be the default value of null.  Now that we’re hoping to expand the scope of the SSO service, I was expecting that it would be necessary to set this value to a level higher, e.g. instead of it defaulting to www.example.com, I would set it to .example.com, and so the same auth token would be valid for foo.example.com as well.

On both the SP and IdP (both using SimpleSAMLphp), the following values are consistent in their respective config.php files:

'session.cookie.name' => 'FooSession',
'session.cookie.domain' => '.example.com',
'session.cookie.secure' => true,
'session.phpsession.cookiename' => null,
'session.authtoken.cookiename' => 'FooAuthToken',

From a state where there are no cookies, I can login well enough.  I have a button that performs the SLO as well, and I can see that that the logout response is successful:

<samlp:LogoutResponse
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_4b29ecc79cc7a693638425e595d7c8345575f96dfa" Version="2.0" IssueInstant="2017-02-23T01:42:39Z" Destination="https://www.example.com/sso-sp/module.php/saml/sp/saml2-logout.php/my-db-service" InResponseTo="_54f5680d70ea11282960a7e0fd4502b206f58eed3a">
Feb 22 17:42:39 simplesamlphp DEBUG [1cd636f74a]   <saml:Issuer>https://auth.example.com/saml2/idp/metadata.php</saml:Issuer>
Feb 22 17:42:39 simplesamlphp DEBUG [1cd636f74a]   <samlp:Status>
Feb 22 17:42:39 simplesamlphp DEBUG [1cd636f74a]     <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
Feb 22 17:42:39 simplesamlphp DEBUG [1cd636f74a]   </samlp:Status>
Feb 22 17:42:39 simplesamlphp DEBUG [1cd636f74a] </samlp:LogoutResponse>


If I click the Login button again, I get back to auth.example.com with a login form.  Successfully fill out the form, and I get the dreaded NoState error.  If I click "Back" on the browser button, I'm back on the page that I was trying to login to, but now _I'm actually logged in_.

I can see in the DEBUG logs of the SP that 1) it's a NoState error, and then 2) that it still has a valid saml response!  I can keep refreshing the page with the NoState error over and over, and it will claim there's no state.  Click back; voila.  Logged in.  If I just type the root URL, I won't be logged in, but I'll get the login button.  If I click the login button again, it will login me in "automatically" and drop me back at the same page as if I was logged in the whole time.


Feb 22 17:42:47 simplesamlphp DEBUG [c01f1c196e] Loading state: '_3698154e4a67ac7b7b4337e14b9ef9b0674294a7e6'
Feb 22 17:42:47 simplesamlphp ERROR [c01f1c196e] SimpleSAML_Error_NoState: NOSTATE
Feb 22 17:42:47 simplesamlphp ERROR [c01f1c196e] Backtrace:
Feb 22 17:42:47 simplesamlphp ERROR [c01f1c196e] 2 /var/www/html/sso-sp/lib/SimpleSAML/Auth/State.php:263 (SimpleSAML_Auth_State::loadState)
Feb 22 17:42:47 simplesamlphp ERROR [c01f1c196e] 1 /var/www/html/sso-sp/modules/saml/www/sp/saml2-acs.php:78 (require)
Feb 22 17:42:47 simplesamlphp ERROR [c01f1c196e] 0 /var/www/html/sso-sp/www/module.php:137 (N/A)
Feb 22 17:42:47 simplesamlphp ERROR [c01f1c196e] Error report with id fb421943 generated.
Feb 22 17:42:47 simplesamlphp DEBUG [c01f1c196e] Template: Reading [/var/www/html/sso-sp/dictionaries/errors]
Feb 22 17:42:47 simplesamlphp DEBUG [c01f1c196e] Template: Reading [/var/www/html/sso-sp/modules/core/dictionaries/no_state]
Feb 22 17:42:47 simplesamlphp DEBUG [c01f1c196e] Received message:
Feb 22 17:42:47 simplesamlphp DEBUG [c01f1c196e] <samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_7085ff93653fff2576f069987ef0e493b9d78ad2f2" Version="2.0" IssueInstant="2017-02-23T01:42:46Z" Destination="https://www.example.com/sso-sp/module.php/saml/sp/saml2-acs.php/my-db-service" InResponseTo="_3698154e4a67ac7b7b4337e14b9ef9b0674294a7e6">
...
^^^ NoState, but seems to have a valid SAML assertion response saved.


**None of this happens if I leave session.cookie.domain => null**, but then of course I can't use the same auth token for multiple SPs.

I received a response which did little to explain what was wrong with this configuration:

"In any case, the whole idea about SSO is, precisely, to allow cross-domain authentication, so you not only don't need to make the cookie available in both the SP and the IdP, but doing so is exactly the source of your trouble, because now the IdP and the SP try to use the same session and they can't."

I don't know either a) which cookie he's referring to or b) how I seem to have gone out of my way to make it "available" in both the SP and IdP.  In the case of the auth token cookie, these seem to definitely need to have the same name; so...

Can someone realign my expectations of reality?



Jaime Perez Crespo

unread,
Feb 23, 2017, 3:48:41 PM2/23/17
to simple...@googlegroups.com
Hi,

I’ve just replied to the mail you sent me personally, but just in case this helps others:

On 23 Feb 2017, at 20:15 PM, casey....@tasktop.com wrote:
> [https://github.com/simplesamlphp/simplesamlphp/issues/567]
>
> I’m encountering an issue with SimpleSAMLphp you may be able to help me resolve.
>
> Previously, I had simply let `session.cookie.domain’ be the default value of null. Now that we’re hoping to expand the scope of the SSO service, I was expecting that it would be necessary to set this value to a level higher, e.g. instead of it defaulting to www.example.com, I would set it to .example.com, and so the same auth token would be valid for foo.example.com as well.

Wrong. That’s not only unnecessary, but the source of your trouble. *SSO is NOT achieved by sharing cookies between domains*.

> On both the SP and IdP (both using SimpleSAMLphp), the following values are consistent in their respective config.php files:
>
> 'session.cookie.name' => 'FooSession',
> 'session.cookie.domain' => '.example.com',
> 'session.cookie.secure' => true,
> 'session.phpsession.cookiename' => null,
> 'session.authtoken.cookiename' => 'FooAuthToken’,

Wrong. They *have to be different*.
>> "In any case, the whole idea about SSO is, precisely, to allow cross-domain authentication, so you not only don't need to make the cookie available in both the SP and the IdP, but doing so is exactly the source of your trouble, because now the IdP and the SP try to use the same session and they can't.”

Maybe I should have said “they MUST NOT” instead of “they can’t”… In any case, let me try again:

> I don't know either a) which cookie he's referring to

The session cookie that you are configuring with the same parameters in both the SP and the IdP, obviously.

> or b) how I seem to have gone out of my way to make it "available" in both the SP and IdP. In the case of the auth token cookie, these seem to definitely need to have the same name;

No, they don’t. They auth token cookie is an internal mechanism of SimpleSAMLphp to avoid session fixation attacks. Nobody needs to have a cookie with the same name. Nobody needs to even know such a cookie exists...

> so…

So the cookies set by “auth.example.com” are clashing with the cookies set by “www.example.com” (and the other way around), and they MUST NOT. You are making the cookies available to each other by setting the cookie domain to the common “.example.com”, so that if “auth.example.com” sets a cookie named “FooSession” with the “.example.com” domain, the browser will send it for every request made both to “auth.example.com”, “foo.example.com” and “www.example.com”. And of course, since your SimpleSAMLphp in “www.example.com” is expecting a cookie named “FooSession” and the browser is sending it, it will try to use it. However, it won’t be able to use that session, because *it’s not its own session*. Furthermore, if IdP and SP are not in the same machine or use the same session backend, they won’t even find the session set by the other. You can’t just drop a session from an IdP to an SP and expect it to work, it won’t.

If you need more SPs, deploy new instances of SimpleSAMLphp, but don’t try to have SSO by sharing a session cookie.

--
Jaime Pérez
UNINETT / Feide

jaime...@uninett.no
jaime...@protonmail.com
9A08 EA20 E062 70B4 616B 43E3 562A FE3A 6293 62C2

"Two roads diverged in a wood, and I, I took the one less traveled by, and that has made all the difference."
- Robert Frost

casey....@tasktop.com

unread,
Feb 23, 2017, 4:26:21 PM2/23/17
to SimpleSAMLphp
Ah.  This is interesting.  I'm not sure what case I would want to set session.cookie.domain in to non-default...
 
> Previously, I had simply let `session.cookie.domain’ be the default value of null.  Now that we’re hoping to expand the scope of the SSO service, I was expecting that it would be necessary to set this value to a level higher, e.g. instead of it defaulting to www.example.com, I would set it to .example.com, and so the same auth token would be valid for foo.example.com as well.

Wrong. That’s not only unnecessary, but the source of your trouble. *SSO is NOT achieved by sharing cookies between domains*.

> On both the SP and IdP (both using SimpleSAMLphp), the following values are consistent in their respective config.php files:
>
> 'session.cookie.name' => 'FooSession',
> 'session.cookie.domain' => '.example.com',
> 'session.cookie.secure' => true,
> 'session.phpsession.cookiename' => null,
> 'session.authtoken.cookiename' => 'FooAuthToken’,

Wrong. They *have to be different*.

^^^ All of these values *must* be different? That's definitely true (since you say it!), but is just completely in contrast to my previous expectations.  Our IdP has definitely serviced several thousand logins with this being the case, and so my aloofness is the source of my surprise.
^^^ again; *all* of the values?  When you say 'cookie', I don't know if you mean session.authtoken.cookiename, session.phpsession.cookiename, or session.cookie.name.

> 'session.cookie.name' => 'FooSession', 
> 'session.cookie.domain' => '.example.com', 
> 'session.cookie.secure' => true, 
> 'session.phpsession.cookiename' => null, 
> 'session.authtoken.cookiename' => 'FooAuthToken’, 

 
> I don't know either a) which cookie he's referring to

The session cookie that you are configuring with the same parameters in both the SP and the IdP, obviously.

So.... session.cookie.name? What about the php session cookie?  My PHP session cookies are PHPSESSID; the default.  Pretty sure I can leave session.phpsession.cookiename set to null to inherit the default PHP configuration; true? 

In my (limited) experience, whenever I was trying to get this going, I would find myself in strange redirect loops.  It always seemed like auth would work properly, but when bounced back to the SP, it would be "missing the cookie" and redirect me back to auth endlessly.  I'm evidently still not sure why that's the case, and I will probably be wrestling with that instead this afternoon once I change these values. :)

 
> or b) how I seem to have gone out of my way to make it "available" in both the SP and IdP.  In the case of the auth token cookie, these seem to definitely need to have the same name;

No, they don’t. They auth token cookie is an internal mechanism of SimpleSAMLphp to avoid session fixation attacks. Nobody needs to have a cookie with the same name. Nobody needs to even know such a cookie exists...


Interesting!
 
> so…

So the cookies set by “auth.example.com” are clashing with the cookies set by “www.example.com” (and the other way around), and they MUST NOT. You are making the cookies available to each other by setting the cookie domain to the common “.example.com”, so that if “auth.example.com” sets a cookie named “FooSession” with the “.example.com” domain, the browser will send it for every request made both to “auth.example.com”, “foo.example.com” and “www.example.com”. And of course, since your SimpleSAMLphp in “www.example.com” is expecting a cookie named “FooSession” and the browser is sending it, it will try to use it. However, it won’t be able to use that session, because *it’s not its own session*. Furthermore, if IdP and SP are not in the same machine or use the same session backend, they won’t even find the session set by the other. You can’t just drop a session from an IdP to an SP and expect it to work, it won’t.

If you need more SPs, deploy new instances of SimpleSAMLphp, but don’t try to have SSO by sharing a session cookie.

Super rad.  I'll give this a go and post back with my results.  Thanks so much Jaime.  Your guidance here is super appreciated!!!!!

casey....@tasktop.com

unread,
Feb 23, 2017, 4:57:10 PM2/23/17
to SimpleSAMLphp, casey....@tasktop.com
Dude. Everything "just works," now.  Thank you so freaking much for helping here.  I clearly needed some direction here, as basically all of my prevailing assumptions were wrong, but that's because I had only used SimpleSAMLphp in the most trivial case: just one SP.

Tempted to add some comments to the config.php file to help clarify this, but for now, I'm happy you've saved my Thursday; oh, and our entire auth scheme... Stepping back, I'd say part of the difficulty is the seeming symmetry of deploying the same library on both ends of the equation.  When you have 0 context, and time to experiment, you can come up with some strange "solutions."

I was having to clear cookies and such for a different SP to auth properly, or it would go into a redirect loop.  That would break auth for yet another SP; clear cookies, retry, etc.  All of that is gone now.  Freaking Elmo-happy over here.

Salut!

- Casey
Reply all
Reply to author
Forward
0 new messages