Browsing Category

Ionic.Auth

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.