zl4bv / CakePHP-simpleSAMLphp-Plugin

Adds support for SAML authentication to CakePHP 2.x.
12 stars 8 forks source link

Application doesn't remember if user is logged in (via saml) #8

Closed s512 closed 9 years ago

s512 commented 9 years ago

Is there any extra configuration I am missing? I followed your set up guide on the project homepage.

All pages (except login etc) are denied to guests (using $this->Auth->deny() in app_controller.php). I am using Saml.SamlForm - with both form and SAML authentication allowed. Log in with a form (@ /users/login), and user can access the site, browse pages no problem.

Login with SAML and user is always redirected back to the login page (/users/login). Any links will always redirect back to this page. If I print saml attributes, they are shown, and $this->Saml->isAuthenticated() returns true, but the application always redirects back to the Form login page. Is there more code I am missing so that Cake knows the user is logged in? Do I need to manually initialize a User (accessible from $this->Auth->User()) in the session? If so, what is the best way of achieving this?

I know the saml login is actually working as I can see a token cookie added when login is successful.

Many thanks for any pointers. Sam

zl4bv commented 9 years ago

Hi Sam,

Is there more code I am missing so that Cake knows the user is logged in?

There shouldn't be. The code in the examples directory is the minimal viable code for a fully functional setup - and it sounds like your code is relatively similar to the example.

Do I need to manually initialize a User (accessible from $this->Auth->User()) in the session?

If Cake understands that you're authenticated then it should take care of this for you - so no.

I will take a look at my own usage of this plugin when I get home from work and see if I can spot anything immediately obvious that could be missing here.

zl4bv commented 9 years ago

Also, which versions of Cake and SimpleSAML are you using?

s512 commented 9 years ago

Cake version 2.5.2 SimpleSaml - not sure exactly without checking tomorrow, but should be up to date (downloaded a few days ago)

I've seen some example Auth components for Ldap that add a user to the database using fields retrieved from the directory, then call cake's $this->Auth->login($user) with the new user created (obviously only creating the user once). This could be a viable solution.

Thanks for your help.

s512 commented 9 years ago

So it might be something wrong with my side - on the login page, I used $this->Saml->isAuthenticated() to work out the current state, and even on successful login it shows that it is unauthenticated. However, if I set $this->Auth->allow() in app_controller, so login is not required, $this->Saml->isAuthenticated() says the user IS authenticated.

I guess it's some sort of session conflict...?

zl4bv commented 9 years ago

Having Session.defaults set to php in Cake and store.type set to phpsession in SimpleSAML does cause a conflict of session information so avoid using that combination if possible.

s512 commented 9 years ago

My Session.defaults is set to database - would this still cause issues? I was getting issues with phpsessions in Cake with SimpleSamlPHP so changed to database.

Thanks.

s512 commented 9 years ago

I've added echo "authenticating...";die(); into the start of the authenticate() function of SamlFormAuthenticate.php. However, this is never seen, it's like something steps in before it to redirect to /users/login.

If I login using the form, this message IS seen.

The login redirect is set to /dashboard. If I call die() (if action is not samlLogin) on the beforeFilter of app_controller, the login is successful, and URL redirects to dashboard as it should. So obviously $this->Saml->isAuthenticated() IS returning true. However after this point, some action is stepping in, which thinks the user is not authenticated, and redirects to /users/login. I am so confused!

zl4bv commented 9 years ago

My Session.defaults is set to database - would this still cause issues? I was getting issues with phpsessions in Cake with SimpleSamlPHP so changed to database.

That should be fine.


In SamlFormAuthenticate.php could you please try adding the following function:

public function unauthenticated(Controller $controller) {
    return $this->Saml->isAuthenticated();
}

"When an unauthenticated user tries to access a protected page first the unauthenticated() method of the last authenticator in the chain is called. [...] If authenticator returns null, AuthComponent redirects user to login action." http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#handling-unauthenticated-requests

s512 commented 9 years ago

I added the function, changing it slightly to fix errors/warnings:

public function unauthenticated(CakeRequest $request, CakeResponse $response) {
    return $this->as->isAuthenticated();
}

However, still no luck: $this->as->isAuthenticated(); is returning false. If I set it to return true, then the user has access to the site. I wonder if it is still a session conflict... I will try and get memcache installed to rule that out for sure.

I need access to a $this->Auth->User() anyway for some functions of the site, so I will set about creating a User from the data returned from AD, and login that user manually.

Will let you know if I find some success. Many thanks for your help so far.

zl4bv commented 9 years ago

If $this->as->isAuthenticated() is returning false then SimpleSAML is unhappy for some reason - my money is on a session conflict.

As far as I know SimpleSAML leaves its PHP session open once it has authenticated the user. So when Cake comes along and makes its call to session_start() the existing session state information is lost - which could be why $this->as->isAuthenticated() returns false. Typically if the reverse happens - Cake starts a session first - then SimpleSAML throws an exception claiming the state information was lost (see issue #7).

s512 commented 9 years ago

Hmm... makes sense. I've tried creating a user on successful login of the SAML user, and logging in manually through $this->Auth->login($user), but the system subsequently forgets this user is logged in. Which is strange.

Question: in a 'normal' environment, where the user is logged in successfully with SAML, what is shown when you print $this->Auth->User()? Will this be the attributes returned from SAML, or empty?

Thanks.

zl4bv commented 9 years ago

Question: in a 'normal' environment, where the user is logged in successfully with SAML, what is shown when you print $this->Auth->User()? Will this be the attributes returned from SAML, or empty?

As far as I know it should get it from the authenticate() method in SamlFormAuthenticate.php. So yes, it will return the attributes from SimpleSAML if the user is authenticated or false if the user is not authenticated.

http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#creating-custom-authentication-objects

s512 commented 9 years ago

So a lot more success - I changed the cake session storage back to php and also set the session.name option to be PHPSESSID - and (with the unauthenticated function in place) - the system logs in! Cake was originally setting the session name to 'cake', and apparently it needs to be 'phpsessid'.

I then check if this user exists in my database, adding the user if not. And log the user in manually. However, I could not do any User creation/logging in at the authenticate() function as it is never called, so have added this code in beforeFilter() of app_controller.php. I need to create a user and log them in in my system so that user_id foreign keys work within the system.

Many thanks for your help, my issue is now resolved. I have another issue with logging out, but this is most likely due to the simplesaml config.

zl4bv commented 9 years ago

Brilliant! That's good to hear. Best of luck with your project.