Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parameterizable session subname #68

Closed
kakawait opened this issue Mar 7, 2013 · 17 comments
Closed

Parameterizable session subname #68

kakawait opened this issue Mar 7, 2013 · 17 comments
Milestone

Comments

@kakawait
Copy link
Contributor

kakawait commented Mar 7, 2013

Hi,

I have a case where an application can provide proxy authentication with many CAS server.
Thus on my application myapp.com, frontend developer is able to use multiple CAS server to point service under different CAS server.

The main problem, today, is when user1 launch widget using cas1.com server and instantiate another widget that uses cas2.com so the first session is override.

This behavior is due to the way to store auth inside session. Indeed phpCAS client stores auth inside $_SESSION['phpCAS'] so there is just one auth possible at the same time.

With parameterizable session subname we can imagine something like:

$_SESSION['phpCAS-cas1']
$_SESSION['phpCAS-cas2']

or maybe better splitting like

$_SESSION['cas1']['phpCAS']
$_SESSION['cas2']['phpCAS']
@jfritschi
Copy link
Contributor

I think this issue might already be fixed if we implement #67. The way the session cookies are set up currently they are do not include a subdirectory in the session cookie.

If #67 is implemented and your widgets would be split into different subdirectories (app1/ and app2/) a session cookie for one application would not interfere with the other. (provided you configure the cookies properly with the new hardening feature)

Would that already fix your problem?

@kakawait
Copy link
Contributor Author

kakawait commented Mar 7, 2013

Yeah but I have one widget for multiple CAS server. So the path is the same...

@jfritschi
Copy link
Contributor

I think this idea makes sense to fix this in general.

I will have a look at it and aim for an implementation somewhere down the road. I will check over the weekend how much effort this will actually take.

jfritschi added a commit that referenced this issue Mar 16, 2013
one server by adding the CAS server url to the phpcas session cookie
as new variable
@jfritschi
Copy link
Contributor

Please test the master branch and provide some feedback. It should work automagically since the cas server url is simply added to the cookie variables.

@jfritschi
Copy link
Contributor

Single logout is pretty certain not work properly and there is no way to fix it. A single log out call from one CAS server will kill all phpcas sessions (if you have single logout enabled).

And any forced local calls to the phpCAS::logout*() functions will also do the same. They will kill all sessions.

@jfritschi
Copy link
Contributor

The logout() problem should be fixed. Single sign out will not be fixable on our end.

The way PHP and phpcas work (stateless without database) there is no way to fix this. This can only be fixed with the single sign out callback handlers if you have some kind of persistence storage.

@kakawait
Copy link
Contributor Author

Yeah but I'm using a call back for logout with rename session to false.

@kakawait
Copy link
Contributor Author

Works fine for me. But one thing that can be nice is to expose function getServerBaseUrl() in phpCAS client, that can be useful for logout callback function.

function myLogoutCallbackFunction() 
{
    unset($_SESSION['phpCAS'][$casClient->getServerBaseUrl()]);
}

@jfritschi
Copy link
Contributor

In my view this will not work. The single logout depends on the callback with the ST and restoring the session with a matching name and then logging out. I don't think this is possible in your use case because a logout callback does not know which session to log out.

Also logout() does exactly what you are proposing.

@kakawait
Copy link
Contributor Author

I have one callback per server, so different instance of client is load depending of the callback. So in my case I can know which session I have to flush.
The problem with logout() function is the header('Location: '.$cas_url); where flow does not need redirection.

But getServerBaseUrl() is not a big deal, I already write my own function to generate the same output. And the single-sign-out works in my case.

Moreover do you think that is possible to retrieve referer when recieve SAML logout POST request and flush the session using the referer?

@jfritschi
Copy link
Contributor

Yes you can identify the server through the instance or URL you are using. But since the logout call is coming from the CAS server and not the user there is no way to match the call to a session (no cookie). The logout call only contains the ST that you have to use to find the right user session to terminate. This is done by having the ST as the session name.
But you can't use that method with multiple servers and only one session. How are you doing that? Do you have another persistent storage? In my view the only option would be to have some kind of database containing a mapping session id -> multiple STs.

The function getServerBaseUrl() could of course be public. Nothing secret about the function. I'm just conscious of the fact that every function we expose is another backwards compatibility issue....

@kakawait
Copy link
Contributor Author

Yeah I told bullshit... You'r true about SSOut. But without SSOut the feature is working.

I will think about a kind of mapping between session to be able to delete or override user (server side) session

@kakawait
Copy link
Contributor Author

About SSOut, it's may a bad idea but it's works if you create a session per CAS server using session_name().
With this kind of solution we don't need anymore a multi array session per server, because each server will have it's own session.

You must keep $changeSessionID to true!

cf. https://github.com/kakawait/phpCAS/commit/67573b3c667f4fbf9e6e81f9729ab973f9dd18d0

(based on branch 1.3 stable).

I would like to know your opinion.

@jfritschi
Copy link
Contributor

I don't think you can have multiple sessions with one user. The only alternative are multiple normal cookies but this does not help because there is no server side storage of cookies.

@kakawait
Copy link
Contributor Author

It's possible to use multiple sessions for one user. With this feature (that finally don't need any modification inside phpCAS lib) I can have multi widget on different passport with SSOut working.

Take two widgets:

  • WidgetA communicate with CASserverA
  • WidgetB communicate with CASserverB

Both widget are loaded on the same webpage of my application (here app.com) but each CASserver have different serviceUrl and callbackUrl.

  • WidgetA -> CASserverA: serviceUrl = app.com/auth/cas/CASserverA & callbackUrl = app.com/auth/cas/CASserverA/callback
  • WidgetB -> CASserverB: serviceUrl = app.com/auth/cas/CASserverB & callbackUrl = app.com/auth/cas/CASserverB/callback

and if you have a third widget using CASserverA the serviceUrl/callbackUrl are the same as WidgetA:

  • WidgetC -> CASserverA: serviceUrl = app.com/auth/cas/CASserverA & callbackUrl = app.com/auth/cas/CASserverA/callback

But in term of code implementation widget are using the same code, just config are different depending of the URL.
Thus before calling phpCAS->proxy(...), I just rename the session using session_name().

session_name(getCasServerBaseUri());
$client = new phpCAS();
// Note that last parameter $changeSessionID must be true or SSOut won't works
$client->proxy($version, $host, $port, $casUri, true);
...

Thereby user will have two sessions

Name Value Domain Path Expire
CASserverA ST-XXX-XXXXXX app.com / session
CASserverB ST-YYY-YYYYYY app.com / session

In this configuration widget authentication works now let's looks about SSOut flow process.
User is logout from CASserverB so CASserverB will send an HTTP POST logout request to the callbackUrl -> app.com/auth/cas/CASserverB/callback. Since I am using URL to define which CASserver is currently using I can easily reconstruct the CASserverB URI.

So the session_name() will be apply for the CASserverB and the phpCAS logout process will override the CASserverB session.

Thus next time the user comes back with it's CASserverB Session cookie, the server side session had been deleted by phpCAS so the user session cookie has no more value.


To conclude, this way to do works on my case (implem & tested) so I don't need anymore the multiCAS session on the same session because I will have a session per server.
Moreover this way to do has an advantage: we don't need to modify the phpCAS lib. I tested with phpCAS 1.3.2 stable and it's works fine.

@jfritschi
Copy link
Contributor

Using the session name makes sense. I guess i should change this in phpCAS and adopt your approach.

@kakawait
Copy link
Contributor Author

You will rollback the code ? And main davantage of using session name is that no development is needed on phpCas (the branch that i refer previously is useless, just put session name before instantiate phpCas is enough)

jfritschi added a commit that referenced this issue Apr 6, 2013
… client on one server by adding the CAS server url to the phpcas session cookie as new variable"

This reverts commit c3cb3ab.
jfritschi added a commit that referenced this issue Apr 6, 2013
@jfritschi jfritschi reopened this Apr 6, 2013
camlafit added a commit to camlafit/phpCAS that referenced this issue Aug 25, 2014
In some case, we need to test more than on CAS server

Looks near to apereo#68

```php
/* Check different CAS */   
    for ($i = 0; $i < $nb_server; $i++) {     
        //Init connection
        phpCAS::client(CAS_VERSION_2_0,$config[$i]['host'],$config[$i]['port'],$config[$i]['uri'],true,true);
        phpCAS::setNoCasServerValidation();
        //Check authentification
        if ($auth = phpCAS::checkAuthentication()) {
            echo "server $i is ok"   
            break;
        }
    }
```
@jfritschi jfritschi modified the milestones: 1.3.4, 1.4.0 Sep 8, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants