Custom-Auth Backend for Ionic.Auth using CakePHP

Ever since Ionic.Auth came out I wanted to create a custom-authorization using my CakePHP 2.6.x backend. The information that the Ionic team gave were really rare so I decided to dig a bit deeper into it.

Activate Custom Authorization in Ionic
First go to the Ionic Dashboard, activate custom-authorization, add a shared secret (this can be any string that you like) and add the URL to your custom-auth server:

Custom-auth in Ionic Dashboard
Custom-auth in Ionic Dashboard

So first let’s get all the parameters that are transmitted by Ionic:

$redirectUri = $this->request->query['redirect_uri'];
$state = $this->request->query['state'];
$token = $this->request->query['token'];

Now define the shared secred. Make sure that this matches the shared secret that you defined in the Ionic dashboard!

$sharedSecret = "some-random-string-that-you-like";

Let’s decode the token that was sent to us by Ionic. I am using the JWT class from Firebase. The Ionic team is using the HS256 algorithm, so we should also define it. You can get the JWT class from Firebase from here.

$decoded = JWT::decode($token, $sharedSecret, array('HS256'));

I tried a long time to finally get the structure of the data that was sent by Ionic. Here is a decoded sample:

"decoded": {
	"data": {
	  "password": "somePassword",
	  "email": "some@email.com"
	},
	"exp": 1457731231,
	"app_id": "8xb3x42"
}

Please note that the $decoded variable is not an array, it is an object. So you have to get your data like this:

$decoded->data->email

Now let’s do the authentication. First of all I am getting the current password hash from the user:

$usertmp = $this->User->find('first',
	array(
		'conditions' => array(
			'User.email' => $decoded->data->email
		),
		'fields' => array(
			'password'
		)
	)
);

Once I have the hash I can create a new hash for the password that was provided. Please note that I am using Blowfish!

$newHash = Security::hash($decoded->data->password, 'blowfish', $usertmp['User']['password']);

Now I try to get the user from the database with the given email address and password:

$user = $this->User->find('first', array(
	'conditions' => array(
		'User.email' => $decoded->data->email,
		'User.password' => $newHash,
		'User.is_active' => 1
	),
	'fields' => array(
		'id',
		'prename',
		'lastname',
		'is_active',
		'session_id',
		'username',
		'avatar',
		'photo_dir',
		'email'
	)
));

Now I check if the user exists. If the user does not exist, we have to throw a 401 exception (UnauthorizedException). If there the user successfully authenticated, we have to create a new variable and save the user_id from our backend. This payload has to be encoded again using our shared secred. Once this is done, we have to send our response back to Ionic:

if(empty($user)) {
	// return 401 auth error
	throw new UnauthorizedException(__('auth error'));
} else {
	$payload = array(
		'user_id' => $user['User']['id']
	);

	// encode payload
	$outgoingToken = JWT::encode($payload, $sharedSecret);

	// redirect back to ionic
	$url = $redirectUri . '&token=' . $outgoingToken . '&state=' . $state . '&redirect_uri=https://api.ionic.io/auth/integrations/custom/success';
	$this->redirect($url);
}

Update (24.03.2016): In case you want to get rid of the “You have successfully implemented custom authentication” screen, just change the url to this:

$url = $redirectUri . '&token=' . $outgoingToken . '&state=' . $state;

That’s it. If everything went well you should see a message that says “You have successfully implemented custom authentication” :) Let me know in the comments if that post was helpful!

You can find the whole function on Github.

Cake-PHP

Generate random strings using PHP

Sometimes you want to create random strings. The can be handy in different cases such as a random session_id, a temporary password when the user resets it and many more. This is a PHP function that accepts the length of the string as a parameter. The default value in case nothing is provided is 10:

public function generateRandomString($length = 10) {
  
  $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  $charactersLength = strlen($characters);
  $randomString = '';
  
  for ($i = 0; $i < $length; $i++) {
    $randomString .= $characters[rand(0, $charactersLength - 1)];
  }
  return $randomString;
}

Call it like this:

$randomString = generateRandomString(15);
Cake-PHP

UPDATE SINGLE FIELD IN DB USING CAKEPHP

This code shows how to update one single field in the database using CakePHP 2.x. It is as simple as this:

$this->User->id = $id;
$this->User->saveField('is_active', 1);

In case we are in an other controller or model as User, we can simply load the User model:

$this->loadModel('User');
$this->User->id = $id;
$this->User->saveField('is_active', 1);
2000px-PHPCode_HelloWorld

SO THIS IS WHERE IT ALL BEGINS

So this is it, my first post on my own blog!

I singed up to Simons newsletter on Devtactiv some weeks ago and got an interesting newsletter today. He encourages developers to write about their experience on their own blog. So let’s do it. Even tough I really do not feel like an expert or a pro at all, I think that some of my experiences might be helpful for other developers out there. I think I am going to talk about my recent projects with Ionic and AngularJS, a really nice cross-plattform framework to create native applications using web technologies!

Talk to you guys soon!