Does anyone have a PHP Custom Authentication for Ionic they are willing to share?


#1

I am having trouble implementing Ionic Custom Auth using php. I have posted this several places but have gotten no response here and very limited on stackoverflow. Has anyone implemented Ionic Custom Auth successfully using just php and if so, are you willing to share your code? I am trying to implement with the inAppBrowser options and browser hidden using only my ionic forms instead of off site web forms.

I am on my last leg with this and if I cant get it figured out soon will need to move on to some other authentication and push service.

Here is the php I am using. It will validate a user fine, but if it has an exception in the script, say, invalid credentials, Ionic.Auth will not call the error callback function. It is returning a 401 message as outline in the docs along with the JSON response. But does not trigger the callback.

<?php
// custom authentication for Ionic Apps
/**
 * @param string GET parameter token.
 * @param string GET parameter state.
 * @param string GET parameter redirect uri.
 * @return string Redirect URI.
 * @throws Exception
 */
 
//header('Access-Control-Allow-Origin: *');
//header('Access-Control-Allow-Headers: Cache-Control, Pragma, Origin, Authorization, Content-Type, X-Requested-With');
//header('Access-Control-Allow-Methods: GET, PUT, POST');

require_once('../vendor/autoload.php');

use \Firebase\JWT\ExpiredException;
use \Firebase\JWT\JWT;

include($_SERVER['DOCUMENT_ROOT']."/connect/config.php");	

try {
	if (isset($_GET['token']) && isset($_GET['state']) && isset($_GET['redirect_uri'])) {

		$token 			= $_GET['token'];
		$state 			= $_GET['state'];
		$redirect_uri 	= $_GET['redirect_uri'];
		
		$decoded 	= JWT::decode($token, SECRET_KEY, array('HS256'));

		$email 		= $decoded->data->email;
		$password 	= $decoded->data->password;
		 
		$results 	= mysqli_query($dbc, "SELECT userID, fname, lname, userName, password, active FROM v_311users WHERE email='".$email."' LIMIT 1");
		$res_match  = mysqli_num_rows($results);
		$res 		= mysqli_fetch_assoc($results);
		 
		if ($res_match == 1){
			
			$userID		= $res['userID'];
			$active		= $res['active'];
			$pw 		= $res['password'];
			$fname 		= $res['fname'];
			$lname 		= $res['lname'];			
		
			if (password_verify($password, $pw)) {			 
			 		
				if($active == 1){			
                     
					$custom->name = $fname.' '.$lname;
					$custom->email = $email;
                    $payload = ['user_id'   => $userID,  'custom' => $custom];
					
					$token = JWT::encode($payload, SECRET_KEY); 				
					
					$url = $redirect_uri . '&' . http_build_query([
            			'token' => $token,
            			'state' => $state,
            			# TODO: Take out the redirect_uri parameter before production
            			//'redirect_uri' => 'https://api.ionic.io/auth/integrations/custom/success',
        			]);
					
					header('Location: '.$url);
					exit();
				} else {
					throw new Exception('Account Not Activated', 40);	
				}
			} else {
				throw new Exception('Invalid Credentials', 30);
			}
		} else {
			throw new Exception('Account Not Found', 20);
		}
	} else {
		// something failed with POST, should never get here!
		 throw new Exception('Missing Parameters', 10);
	}
	
} catch (Exception $e) {
	header('Content-type: application/json');
	//header('HTTP/1.0 401 Unauthorized');    	
	http_response_code(401);
	echo json_encode(['error' => $e->getMessage(), 'code' => $e->getCode()]);
}

?>

Here is the test code in my Ionic app.

	$ionicAuth.login('custom', userLogin, loginOptions).then(function (data) {
		Loading.hideLoading();
		Alert.showAlert('Success',JSON.stringify(data));
	},function(err){
		Alert.showAlert('Failed:',JSON.stringify(err));
	});

#2

SO I am trying to find some help by going through the ionic.cloud.js file to see if I can resolve my problem and found a note in the code for the Auth.prototype.login function!

@note TODO: Better error handling docs.

Please do! This is driving me nuts.

RGecy


#3

After reviewing the ionic.cloud.js file, I have come to the conclusion that the inAppBrowserFlow function is the culprit. The loadError function is never called, even if I change my auth script to fail miserably. Not to mention, the loadError_1 function does not return the code and message from the page if it was called. Looks to me it is set up only to handle 3 legged auth with inAppBrowser open.

Here is the inAppBrowserFlow function

AuthType.prototype.inAppBrowserFlow = function (moduleId, data, options) {
    var _this = this;
    if (data === void 0) { data = {}; }
    var deferred = new promise_1.DeferredPromise();
    if (!window || !window.cordova || !window.cordova.InAppBrowser) {
        deferred.reject(new Error('InAppBrowser plugin missing'));
    }
    else {
        this.client.post("/auth/login/" + moduleId)
            .send({
            'app_id': this.config.get('app_id'),
            'callback': window.location.href,
            'data': data
        })
            .end(function (err, res) {
            if (err) {
                deferred.reject(err);
            }
            else {
                var w_1 = window.cordova.InAppBrowser.open(res.body.data.url, '_blank', _this.parseInAppBrowserOptions(options.inAppBrowserOptions));
                var onExit_1 = function () {
                    deferred.reject(new Error('InAppBrowser exit'));
                };
                var onLoadError_1 = function () {
                    deferred.reject(new Error('InAppBrowser loadError'));
                };
                var onLoadStart = function (data) {
                    if (data.url.slice(0, 20) === 'http://auth.ionic.io') {
                        var queryString = data.url.split('#')[0].split('?')[1];
                        var paramParts = queryString.split('&');
                        var params = {};
                        for (var i = 0; i < paramParts.length; i++) {
                            var part = paramParts[i].split('=');
                            params[part[0]] = part[1];
                        }
                        w_1.removeEventListener('exit', onExit_1);
                        w_1.removeEventListener('loaderror', onLoadError_1);
                        w_1.close();
                        deferred.resolve({
                            'token': params['token'],
                            'signup': Boolean(parseInt(params['signup'], 10))
                        });
                    }
                };
                w_1.addEventListener('exit', onExit_1);
                w_1.addEventListener('loaderror', onLoadError_1);
                w_1.addEventListener('loadstart', onLoadStart);
            }
        });
    }
    return deferred.promise;
};

#4

Hi

Did you solve your problem?
I think i have the same problem!!


#5

I got word that they uploaded a new ionic cloud version and supposedly fixed it. I have not tried it yet.

You will have to remove the ionic cloud plugin files from your app and reinstall.

RGecy