First of all, thanks to anyone who will look into this with me. Let me just say that I am a CakePHP beginner. Although my website is functional, it is relatively simple thus I did not gain much knowledge of the framework from developing it. Let's say, I'm a basic user with a less basic problem...!
So, I'm currently developing a website with AngularJS and CakePHP 3. The CakePHP part is a REST API, and of course, the Angular, the client side of the website.
Some of the pages should only be accessed by registered/logged in users, or at least users which email matches @mydomain.com (who then should be registered).
At fisrt, the API/site were designed to deal with this through HTTP Basic authentication but two days ago I got asked to deal with it through a Google OAuth2 Authentication.
So I've tried looking around if anyone had done that on CakePHP3 yet, without a plugin (someone mentioned to me the CakeDC/users plugin, but the documentation is so poor that I didn't go there...). I found these :
http://caketuts.key-conseil.fr/index.php/2015/05/22/integrer-lapi-oauth2-de-google-avec-cakephp-v3/ (in French, sorry, but the code is pretty clear)
http://blog.jainsiddharth21.com/2013/04/29/login-with-google-in-cakephp/ (which is understandable but not really what I chose to do, but still usefull and close to my code)
Although my code is pretty much 90% like this first link, I can't seem to get the Authentication working the way it is supposed to.
Here is my code :
AppController.php :
public function initialize() {
parent::initialize();
$this->loadComponent('RequestHandler');
$this->loadComponent('Flash');
$this->loadComponent('Auth', [
'loginAction' => [
'controller' => 'Users',
'action' => 'googlelogin',
],
'authenticate' => [
'Form' => [
'fields' => [
'username' => 'email',
'password' => 'password'
]
]
],
'authError' => __("You don't have rights for this page"),
'authorize' => ['Controller'],
'unauthorizedRedirect' => [
'controller' => 'Users',
'action' => 'forbidden'
],
'loginRedirect' => [
'controller' => 'myHomePage',
],
'logoutRedirect' => [
'controller' => 'Users',
'action' => 'googlelogin'
]
]);
}
UsersController.php
public function googlelogin() {
$client = new Google_Client();
$client->setClientId(GOOGLE_OAUTH_CLIENT_ID);
$client->setClientSecret(GOOGLE_OAUTH_CLIENT_SECRET);
$client->setRedirectUri(GOOGLE_OAUTH_REDIRECT_URI);
$client->setScopes(array(
"https://www.googleapis.com/auth/userinfo.profile",
'https://www.googleapis.com/auth/userinfo.email'
));
$url = $client->createAuthUrl();
$this->redirect($url);
}
public function confirmLogin() {
$client = new Google_Client();
$client->setClientId(GOOGLE_OAUTH_CLIENT_ID);
$client->setClientSecret(GOOGLE_OAUTH_CLIENT_SECRET);
$client->setRedirectUri(GOOGLE_OAUTH_REDIRECT_URI);
$client->setScopes(array(
"https://www.googleapis.com/auth/userinfo.profile",
'https://www.googleapis.com/auth/userinfo.email'
));
$client->setApprovalPrompt('auto');
if (isset($this->request->query['code'])) {
$client->authenticate($this->request->query['code']);
$this->request->Session()->write('access_token', $client->getAccessToken());
}
if ($this->request->Session()->check('access_token') && ($this->request->Session()->read('access_token'))) {
$client->setAccessToken($this->request->Session()->read('access_token'));
}
if ($client->getAccessToken()) {
$this->request->Session()->write('access_token', $client->getAccessToken());
$oauth2 = new Google_Service_Oauth2($client);
$user = $oauth2->userinfo->get();
try {
if (!empty($user)) {
if (preg_match("/(@mydomain\.com)$/", $user['email'])) {
$result = $this->Users->find('all')
->where(['email' => $user['email']])
->first();
if ($result) {
$this->Auth->setUser($result->toArray());
$this->redirect($this->Auth->redirectUrl());
} else {
$data = array();
$data['email'] = $user['email'];
$data['first_name'] = $user['givenName'];
$data['last_name'] = $user['familyName'];
$data['socialId'] = $user['id'];
//$data matches my Users table
$entity = $this->Users->newEntity($data);
if ($this->Users->save($entity)) {
$data['id'] = $entity->id;
$this->Auth->setUser($data);
$this->redirect($this->Auth->redirectUrl());
} else {
$this->Flash->set('Logging error');
$this->redirect(['action' => 'login']);
}
}
} else {
$this->Flash->set('Forbidden');
$this->redirect(['action' => 'login']);
}
} else {
$this->Flash->set('Google infos not found');
$this->redirect(['action' => 'login']);
}
} catch (\Exception $e) {
$this->Flash->set('Google error');
return $this->redirect(['action' => 'login']);
}
}
}
I also added the following lines to the file
paths.php
define('GOOGLE_OAUTH_CLIENT_ID', 'My_client_id');
define('GOOGLE_OAUTH_CLIENT_SECRET', 'My_client_secret');
define('GOOGLE_OAUTH_REDIRECT_URI', 'mylinkto/confirmLogin');
In Chrome's debugging tool, it seems that confimLogin is called (twice by the way) with a valid code as query parameter, and then googlelogin is called. So I end up on the log page every time...
I feel like there must be something I'm missing here. Does anyone have any idea? (Thanks!)