Problem, OpenID Simple Registration Extension - cakephp

I use OpenID Simple Registration on CakePHP like this post but this don't work for me.
my code in controller is here:
function openid() {
$returnTo = 'http://'.$_SERVER['SERVER_NAME'].$this->webroot.'customers/openid';
if (!empty($this->data)) {
try {
$this->Openid->authenticate($this->data['OpenidUrl']['openid'], $returnTo, 'http://'.$_SERVER['SERVER_NAME'].$this->webroot, array('email'), array('nickname'));
} catch (InvalidArgumentException $e) {
$this->setMessage($this->data);
} catch (Exception $e) {
$this->setMessage($e->getMessage());
}
}
elseif (count($_GET) > 1) {
$response = $this->Openid->getResponse($returnTo);
$this->set("test",$_GET);
if ($response->status == Auth_OpenID_CANCEL) {
$this->Session->write('OpenIdStatus','Verification cancelled');
} elseif ($response->status == Auth_OpenID_FAILURE) {
$this->Session->write('OpenIdStatus','OpenID verification failed: '.$response->message);
} elseif ($response->status == Auth_OpenID_SUCCESS) {
$this->Session->write('OpenIdStatus','successfully authenticated!');
$sregResponse = Auth_OpenID_SRegResponse::fromSuccessResponse($response);
$sregContents = $sregResponse->contents();
$this->set("message",$sregContents);
}
}
}
What is my wrong?!

The authenticate method only expects four params in the current version. The following snippet:
$this->Openid->authenticate($this->data['OpenidUrl']['openid'], $returnTo, 'http://'.$_SERVER['SERVER_NAME'].$this->webroot, array('email'), array('nickname'));
has to look like:
$this->Openid->authenticate($this->data['OpenidUrl']['openid'], $returnTo, 'http://'.$_SERVER['SERVER_NAME'].$this->webroot, array('sreg_required' => array('email'), 'sreg_optional' => array('nickname')));

Related

CakeDC users plugin: redirect error after changePassword

My app is developed in CakePHP 3.x.
I use CakedDC Users plugin, and it works fine, except when the user wants to change his password, and click on Submit.
Let's say we have a Profile ID = 52606b3f-c72d-4485-9c76-3b0f8
The Edit page has a url like this:
localhost/my_app/profile/52606b3f-c72d-4485-9c76-3b0f8
The changePassword page has a url like this:
localhost/my_app/users/users/change-password/52606b3f-c72d-4485-9c76-3b0f8
When I click on Submit, it redirects to the profile page, but the ID is lost:
localhost/my_app/profile
and I get this error message:
Record not found in table "users" with primary key [NULL]
I think the reason is that the ID is not passed. And I don't find where and how to fix it.
Any help please ?.
When id is not passed, the id is taken from the logged in user. You can take a look at src/Controller/Traits/ProfileTrait.php. Could you debug $this->Auth->user('id')?
Also, you could customize the redirect url after changing the password. Configure::write('Users.Profile.route', [{url}]), see src/Controller/Traits/PasswordManagementTrait.php Ln44.
I don't remember my initial code, but, after months, I found the solution.
in src/Controller/Traits/ProfileTrait.php, set $redirect = Configure::read('Users.Profile.route');
public function changePassword()
{
$user = $this->getUsersTable()->newEntity();
$id = $this->Auth->user('id');
if (!empty($id)) {
$user->id = $this->Auth->user('id');
$validatePassword = true;
//#todo add to the documentation: list of routes used
$redirect = Configure::read('Users.Profile.route');
} else {
$user->id = $this->request->session()->read(Configure::read('Users.Key.Session.resetPasswordUserId'));
$validatePassword = false;
if (!$user->id) {
$this->Flash->error(__d('CakeDC/Users', 'User was not found'));
$this->redirect($this->Auth->config('loginAction'));
return;
}
//#todo add to the documentation: list of routes used
$redirect = $this->Auth->config('loginAction');
}
$this->set('validatePassword', $validatePassword);
if ($this->request->is('post')) {
try {
$validator = $this->getUsersTable()->validationPasswordConfirm(new Validator());
if (!empty($id)) {
$validator = $this->getUsersTable()->validationCurrentPassword($validator);
}
$user = $this->getUsersTable()->patchEntity($user, $this->request->data(), ['validate' => $validator]);
if ($user->errors()) {
$this->Flash->error(__d('CakeDC/Users', 'Password could not be changed'));
} else {
$user = $this->getUsersTable()->changePassword($user);
if ($user) {
$this->Flash->success(__d('CakeDC/Users', 'Password has been changed successfully'));
return $this->redirect($redirect);
} else {
$this->Flash->error(__d('CakeDC/Users', 'Password could not be changed'));
}
}
} catch (UserNotFoundException $exception) {
$this->Flash->error(__d('CakeDC/Users', 'User was not found'));
} catch (WrongPasswordException $wpe) {
$this->Flash->error(__d('CakeDC/Users', '{0}', $wpe->getMessage()));
} catch (Exception $exception) {
$this->Flash->error(__d('CakeDC/Users', 'Password could not be changed'));
}
}
$this->set(compact('user'));
$this->set('_serialize', ['user']);
}

Session issues in cakephp 2.x with facebook sdk in production

I am trying to use Facebook PHP sdk with cakephp 2.x for login purpose.
And it is working with debug mode 1 or 2 but it is not working with debug mode 0.
It seems session is not working properly in production.
I search about it on the web many times but not get the right solution for me.
I read these two threads in detail but did not cope with the problem.
https://github.com/facebook/php-graph-sdk/issues/473
How do I integrate Facebook SDK login with cakephp 2.x?
I use these two functions in AppController for login.
public function beforeFilter()
{
$this->disableCache();
$this->Facebook = new Facebook(array(
'app_id' => 'appId',
'app_secret' => 'appSecret',
'default_graph_version' => 'v2.7',
));
$this->Auth->allow(['.....']);
}
public function login()
{
if (!session_id()) {
session_start();
}
$this->loadModel("User");
$user_id = $this->Session->read('Auth.User.id');
$fb = $this->Facebook->getRedirectLoginHelper();
$permissions = ['email']; // Optional permissions
$callback_url = HTTP_ROOT . 'login';
$fb_login_url = $fb->getLoginUrl($callback_url, $permissions);
$this->set('fb_login_url', $fb_login_url);
if (!empty($user_id)) {
//redirect to profile page if already logged in
$this->redirect(... . );
}
//local login request
if ($this->request->is('post')) {
......
}
// when facebook login is used
elseif ($this->request->query('code')) {
try {
$accessToken = $fb->getAccessToken();
} catch (\Facebook\Exceptions\FacebookResponseException $e) {
// When Graph returns an error
$this->Session->setFlash('Graph returned an error: ' . $e->getMessage(), 'error');
$this->redirect($this->referer());
} catch (\Facebook\Exceptions\FacebookSDKException $e) {
// When validation fails or other local issues
$this->Session->setFlash('Facebook SDK returned an error: ' . $e->getMessage(), 'error');
$this->redirect($this->referer());
}
if (!isset($accessToken)) {
if ($fb->getError()) {
header('HTTP/1.0 401 Unauthorized');
$this->Session->setFlash("Error: " . $fb->getError() . "\n", 'error');
$this->Session->setFlash("Error Code: " . $fb->getErrorCode() . "\n", 'error');
$this->Session->setFlash("Error Reason: " . $fb->getErrorReason() . "\n", 'error');
$this->Session->setFlash("Error Description: " . $fb->getErrorDescription() . "\n", 'error');
$this->redirect($this->referer());
} else {
header('HTTP/1.0 400 Bad Request');
$this->Session->setFlash('Bad request', 'error');
$this->redirect($this->referer());
}
}
// Logged in
$oAuth2Client = $this->Facebook->getOAuth2Client();
$tokenMetadata = $oAuth2Client->debugToken($accessToken);
$tokenMetadata->validateAppId('1200125790051089'); // Replace {app-id} with your app id
$tokenMetadata->validateExpiration();
if (!$accessToken->isLongLived()) {
try {
$accessToken = $oAuth2Client->getLongLivedAccessToken($accessToken);
} catch (\Facebook\Exceptions\FacebookSDKException $e) {
$this->Session->setFlash('Error getting long-lived access token: ' . $helper->getMessage() . "</p>\n\n", 'error');
$this->redirect($this->referer());
}
}
$_SESSION['fb_access_token'] = (string) $accessToken;
$fb_access_token = (string) $accessToken;
if (isset($accessToken)) {
try {
// Returns a `Facebook\FacebookResponse` object
$response = $this->Facebook->get('/me?fields=id,first_name,last_name,email', $accessToken);
} catch (\Facebook\Exceptions\FacebookResponseException $e) {
$this->Session->setFlash('Graph returned an error: ' . $e->getMessage(), 'error');
$this->redirect($this->referer());
} catch (\Facebook\Exceptions\FacebookSDKException $e) {
$this->Session->setFlash('Facebook SDK returned an error: ' . $e->getMessage(), 'error');
$this->redirect($this->referer());
}
$fb_user = $response->getGraphUser();
// We will varify if a local user exists first
$local_user = $this->User->find('first', array(
'conditions' => array('facebook_id' => $fb_user['id']),
));
// If exists, we will log them in
if ($local_user) {
$this->Auth->login($local_user['User']);
} else {
// we will create new user with facebook_id and log them in
$data['User'] = array(.........);
// You should change this part to include data validation
$new_user = $this->User->save($data);
$this->Auth->login($new_user['User']);
}
// redirect to profile page here
}
}
}
I've had some issues with the SDK and CakePHP 2.x as well. I wrote a small handler that lets the SDK make use of CakeSession.
You can find it here:
https://github.com/WrDX/FacebookCakeSessionPersistentDataHandler

A better way for using DB connection [PDO] using an class and further using it in other class?

I'm searching for a better PDO db connection which I could use in the different classes I have. For example my current code is like this:
core.php
//Connecting to Database
try {
$db = new PDO("mysql:host=localhost;dbname=mydb", "project", "project123");
}
catch(PDOException $e) {
echo $e->getMessage();
}
class Core {
protected $db;
public function __construct(PDO $db) {
$this->db = $db;
}
function redirectTo($page,$mode = 'response',$message = '') {
if($message != '') {
header('Location: '.SITEURL.'/'.$page.'?'.$mode.'='.urlencode($message));
} else {
header('Location: '.SITEURL.'/'.$page);
}
exit();
}
}
And apart from this I have 2 more class: wall.php and ticker.php
class Wall {
protected $db;
public function __construct(PDO $db) {
$this->db = $db;
}
function addComment($uid, $fid, $comment) {
$time = time();
$ip = $_SERVER['REMOTE_ADDR'];
$query = $this->db->prepare('INSERT INTO wall_comments (comment, uid_fk, msg_id_fk, ip, created) VALUES (:comment, :uid, :fid, :ip, :time)');
$query->execute(array(':comment' => $comment, ':uid' => $uid, ':fid' => $fid, ':ip' => $ip, ':time' => $time));
$nofity_msg = "User commented on the post";
$setTicker = Ticker::addTicker($uid,$nofity_msg,'comment');
if($setTicker) {
Core::redirectTo('wall/view-'.$fid.'/','error','Oops, You have already posted it!');
} else {
Core::redirectTo('wall/view-'.$fid.'/','error','Oops, Error Occured');
}
}
}
and ticker.php is:
class Ticker {
protected $db;
public function __construct(PDO $db) {
$this->db = $db;
}
function addTicker($uid,$msg,$type) {
$time = time();
$query = $this->db->prepare('INSERT INTO tickers (uid_fk, message, type, created) VALUES (:uid, :message, :type, :time)');
try {
$query->execute(array(':uid' => $uid, ':message' => $msg, ':type' => $type, ':time' => $time));
return $this->db->lastInsertId();
}
catch(PDOException $e) {
return 0;
}
}
}
Now my problem is that I need to call for the function addComment() and inside that function there is a further call for the function addTicker() present in the class Ticker. This is causing a Db connection problem as there is already an db instance created in the previous class or so.. I can't figure out how to sort this out.
This is the code I'm using in the main index file:
$core = new Core($db);
$ticker = new Ticker($db);
$wall = new Wall($db);
$wall->addComment($uid, $fid, $add_comment); // This statement is not working.. :(
My intention is to have a common main DB connection and further use that connection in other classes. Is there any better way to do it..?
there is already an db instance created in the previous class
this is actually single instance, but copied into 2 variables.
This is causing a Db connection problem
Can you please be a bit more certain about such a problem? What particular problem you have?

update Auth session

How to update user information stored in auth session? without logout and login again.
I think this function will do it.. but is it the best-practice?
function update($field, $value){
$this->Session->write($this->Auth->sessionKey . '.' . $field, $value);
}
Yes.
You could grab the current info array, modify it, and then call $this->Auth->login($newUserData);, but this will also renew the session (no user interaction needed, though). Note: Applies to CakePHP 2.0+ only.
I've completed update function to get an array of new values. with keys (field name):
public function update($fields, $values = null) {
if (empty(parent::$_user) && !CakeSession::check(parent::$sessionKey)) {
return false;
}
if (!empty(parent::$_user)) {
$user = parent::$_user;
} else {
$user = CakeSession::read(parent::$sessionKey);
}
if (is_array($fields)) {
if (is_array($values)) {
$data = array_combine($fields, $values);
} else {
$data = $fields;
}
} else {
$data = array($fields => $values);
}
foreach ($data as $field => $value) {
if (isset($user[$field])) {
$user[$field] = $value;
}
}
return $this->login($user);
}
(thanks to tigrang for login function)

CakePHP REST Authorization issue on POST and PUT (I get 404)

I'm developing a REST api for a application, and everething went fine up until now...
I'm building a header with login data, GET and DELETE work fine but when I try to send a PUT or POST request I get 404...
When authorization is off (i.e., I do not check it in cake) everything works fine.
Here's the controller code:
class SitesController extends AppController {
var $uses = array("Site");
var $name = 'Sites';
var $scaffold;
var $components = array('RequestHandler','Security');
function beforeFilter() {
$this->Security->loginOptions = array(
'type'=>'basic'
);
$this->Security->loginUsers = array(
'lukasz'=>'blabla',
'test'=>'test'
);
$this->Security->requireLogin();
}
function index() {
$sites = $this->Site->find('all');
$this->set(compact('sites'));
}
function view($id) {
$site = $this->Site->findById($id);
$this->set(compact('site'));
}
function add() {
if($this->data != null) {
$this->Site->create();
if($this->Site->save($this->data)) {
$message = array('Deleted');
} else {
$message = $this->data;
}
$this->set(compact("message"));
}
}
function edit($id) {
$this->Site->id = $id;
if ($this->Site->save($this->data)) {
$message = array('Saved');
} else {
$message = array('Error');
}
$this->set(compact("message"));
}
function delete($id) {
if($this->Site->delete($id)) {
$message = array('Deleted');
} else {
$message = array('Error');
}
$this->set(compact("message"));
}
}
And here's how I send requests:
http://bin.cakephp.org/view/165115685
http://bin.cakephp.org/view/1477117088
I suspect you're running into the CSRF protection (form spoofing protection) the SecurityComponent applies to all POST and PUT requests. Try turning it off using the $validatePost option.

Resources