Firebase authentication with Ionic creator

Why Ionic creator?

Mobile first is the new mantra of today's applications. Building mobile based apps has also seen a huge growth from early 90s. Along with languages like swift and Java, which are focussed on specific environments like IOS and Android respectively, we have seen good traction on platforms like phonegap and cordova.

Today's startup are aiming mostly on business logic which are compatible with desktop and mobile devices. Investing on individuals for each aspects might be expensive. For ex: Instead of having 3 developers, 1 for android 1 for IOS and 1 for web is far too expensive than having 1 for all 3. Here platforms like Phonegap and Cordova play a vital role in binding one code for all 3 platforms.

Cordova is just a fork of Phonegap, but as per my research if someone ask you which one you will chose, I suggest go with Cordova. Phonegap is a adobe project compared to Cordova which is an apache open source project. Being a part of Apache community it seems to be more reliable and maintainable in future by the community.

You might be wondering where Ionic is going to come?

Well here it is, Ionic plays a critical role in binding cordova plugins with angularjs components. Ionic framework exists since past few years, but what we want to talk about here is Ionic creator which is a web version of creating mobile based app with easy to use utilities.

It took me just 3 hours to have a basic app up and running without going through Android or IOS based native coding tutorials.

Ionic creator gives you a web view where you can not only preview your changes real time but also can create beautiful designs and give that standard native look and feel which will make your app great for the consumer




Why Firebase authentication?

Now after getting the knowledge of ionic creator, which is the UI look and feel, let's now focus on the backend stuff. When we are talking about backend we should be considering couple of questions which will help us design our app

1. App performance should be good,  Database related actions should not prove to be a poor performant.
2. App should be able to handle offline data. This becomes incredibly important for mobile based apps. Offline data should sync seamlessly when it gets network back.
3. App authentication can be personified as a backbone to your app work. Authentication should be secure and managed by certified vendor.
4. It should work in scale

The list of design consideration goes on and on. But let's focus on a solution based on the above listed aspects.

Firebase is a relatively new product released by Google. Yeah Google! that answers you scaling requirement. 

Performance is relatively fast, as the data transmission is done in form of json objects. Being a no sql type , fields can be added or deleted on the fly. 

Firebase has support for offline data also, however I have not explored this, but as per documentation feel this can be achieved with minimal effort

There are tons of other advantages for this. But the most striking advantage is with Ionic creator Firebase comes as a plugin. Believe me when I say it will take 15 min for you to setup an app and get it authenticated from Firebase.



Why Ionic creator with Firebase authentication?

Let's jump to the other topic which is the crux of this blog. Let's first talk about the motivation behind this blog.

If you search youtube there are samples where Ionic creator team has shown how to create an app in minutes. If you checkout the authentication part link you will see they used ionicauth for the same.

Now when I started working with this, the first question I had that where I want to store my data. I wanted to go with Firebase, now my question was how will I authorize my app. Examples showed by integration with ionic auth. Honestly this did not make sense to me. 

I didn't like the fact that ionic auth will authorize the app and the data then will go and get stored in firebase. This was weird because Firebase itself has an authentication piece where user can signup/signin with their email and password

So I started exploring Firebase auth with Ionic creator. Now comes the exciting part. The code which was working with ionic auth in case of error was not working with Firebase. In error scenario, ionicauth was able to update the ui element with the corresponding error message. Here {{errorBox}} is the ui element.


People have posted on forums (https://forum.ionicframework.com/t/basic-firebase-error-handling/65798 ) but I couldn't find any solution for this. Note there are examples with ionic framework and firebase auth but none with ionic creator.

The reason for this blog is to share the fix with you

Enough of whys now let's answer how?

Refer to https://github.com/driftyco/creator-weekly-workshops/tree/master/04-ionic-auth-and-gravatar for the ionic auth integration with ionic creator, video is available at https://www.youtube.com/watch?v=McBS4fbPt5Q

The code which is handling the auth and on success helping the user to navigate to the home page is as following

$ionicAuth.signup($scope.data).then(function() {
// `$ionicUser` is now registered
$ionicAuth.login('basic', $scope.data).then(function(){
$state.go('menu.home');
});
}, function(err) {
var error_lookup = {
'required_email': 'Missing email field',
'required_password': 'Missing password field',
'conflict_email': 'A user has already signed up with that email',
'conflict_username': 'A user has already signed up with that username',
'invalid_email': 'The email did not pass validation'
}
$scope.errorBox = error_lookup[err.details[0]];
});

Note on success the ionicAuth.login is going to home and on error it should update a paragraph component populating it with the error details. This error scenario fails when you try to get Firebase auth. Why? because the firebase auth action is asynchronous and we need a mechanism to invoke the update action on the ui paragraph element in case of error so that it is updated properly.

To solve this we can have the following

$scope.errorBox='';

const promise = firebase.auth().createUserWithEmailAndPassword($scope.data.email,  
$scope.data.password);
promise.then(resp => {
    
        $state.go('menu.home');
    })
    .catch(err => {
        $scope.$apply(function(){
        //Set error box message        $scope.errorBox = err.message;
    });
}) 
In case of firebase, when there is an error one should do $scope.$apply and then update the element with the message

Note the intent of this blog is to save that one hour which I spent learning about firebase async transaction and angularjs $apply function. Once this was done everything worked fine.

Hope this blog will help someone to save his/her few hours of investigation. Let me know if you see any issues.


Part 2 - (This section has been updated with the latest)

Thanks all for liking the earlier analysis. As few of you wanted to know the implementation I am pasting the code snippet which helped me create the login and signup feature. In my app I had a restaurant signup page and a user signup page. The login page was common for both.

Will request you to post any questions/concerns if you have regarding the following. I will try to help to the best of my knowledge.

Login method:


.controller('loginCtrl', ['$scope', '$stateParams', '$firebaseArray', '$state', function ($scope, $stateParams,  $firebaseArray, $state) {

    $scope.data = {
        'email': '',
        'password': ''
    }

    $scope.login = function(){
        $scope.errorBox = '';
        const promise = firebase.auth().signInWithEmailAndPassword($scope.data.email, $scope.data.password);
        promise.then(resp => {

            $state.go('myHome')
        })
        .catch(err => {
          $scope.$apply(function(){
             $scope.errorBox = err.message;
          });
        });
    }

}])


Here is the corresponding template

<form id="login-form1" class="list center-form">
      <div>
        <img src="img/gOVYEwjOT2WxJu2pPPKA_e6bcbbd8-e870-4615-81a8-a937930488e2.png" style="display: block; width: 50%; height: auto; margin-left: auto; margin-right: auto;">
      </div>
      <ion-list id="login-list1">
        <label class="item item-input top-input" id="login-input1">
          <span class="input-label">Email</span>
          <input type="text" placeholder="" ng-model="data.email">
        </label>
        <label class="item item-input bottom-input" id="login-input2">
          <span class="input-label">Password</span>
          <input type="password" placeholder="" ng-model="data.password">
        </label>
      </ion-list>
      <div class="spacer" style="width: 290px; height: 28px;"></div>
      <button id="login-button1" ng-click="login()" class="button button-assertive  button-block button-positive">Log in</button>
      <a ui-sref="signup" id="login-button2" class="button button-positive  button-block">Or create an account</a>
    </form>


Signup:

.controller('signupCtrl', ['$scope', '$stateParams', '$firebaseArray', '$state', // The following is the constructor function for this page's controller. See https://docs.angularjs.org/guide/controller
// You can include any angular dependencies as parameters for this function
// TIP: Access Route Parameters for your page via $stateParams.parameterName
function ($scope, $stateParams, $firebaseArray, $state) {

    $scope.data = {
        'email': '',
        'password': '',
        'usertype':''
    }

    $scope.signup = function(){
        $scope.errorBox='';

        const promise = firebase.auth().createUserWithEmailAndPassword($scope.data.email, $scope.data.password);
        promise.then(resp => {
            createUser();

            if($scope.data.usertype == "individual"){
                $state.go('individualSignup');
            } else if($scope.data.usertype = "restaurant"){
                $state.go('restaurantSignup');
            }
        })
        .catch(err => {
           $scope.$apply(function(){
                //Set error box message
                $scope.errorBox = err.message;
           });
        })
    }

    //By default check the individual option
    $scope.activeSection = 1;
    $scope.data.usertype = "individual";

    //Choose Occupation type as individual or business
    $scope.choseType = function(option){
        $scope.activeSection = option;
        if(option == 1){
            $scope.data.usertype = "individual";
        }
        else if(option == 2){
            $scope.data.usertype = "restaurant";
        }
    }

    function createUser(){
        firebase.auth().onAuthStateChanged(function(user) {
          if (user) {
            var uid = user.uid;
            var email = user.email;
            var userType = $scope.data.usertype;
            firebase.database().ref('users/' + uid).set({
                email: email,
                user_type : userType
              });
          } else {
            // No user is signed in.
          }
        });
    }

}])


Here is the corresponding template

<form id="signup-form12" class="list center-form">
      <div>
        <img src="img/gOVYEwjOT2WxJu2pPPKA_e6bcbbd8-e870-4615-81a8-a937930488e2.png" style="display: block; width: 50%; height: auto; margin-left: auto; margin-right: auto;">
      </div>
      <div id="signup-button-bar4" class="button-bar">
        <button id="signup-button30" ng-class="{'active':activeSection==1}" ng-click="choseType(1)" class="button button-positive  button-block">Individual</button>
        <button id="signup-button31" ng-class="{'active':activeSection==2}" ng-click="choseType(2)" class="button button-positive  button-block">Restaurant</button>
      </div>
      <ion-list id="signup-list4" ng-show="activeSection==1">
        <label class="item item-input top-input" id="signup-input3">
          <span class="input-label">Email</span>
          <input type="text" placeholder="" ng-model="data.email">
        </label>
        <label class="item item-input bottom-input" id="signup-input4">
          <span class="input-label">Password</span>
          <input type="password" placeholder="" ng-model="data.password">
        </label>
      </ion-list>
      <ion-list id="signup-list5" ng-show="activeSection==2">
        <label class="item item-input top-input" id="signup-input6">
          <span class="input-label">Restaurant Email</span>
          <input type="text" placeholder="" ng-model="data.email">
        </label>
        <label class="item item-input bottom-input" id="signup-input7">
          <span class="input-label">Password</span>
          <input type="password" placeholder="" ng-model="data.password">
        </label>
      </ion-list>
      <div id="signup-markdown5" class="show-list-numbers-and-dots error-box">
        <p style="margin-top:0px;color:#000000;">{{errorBox}}</p>
      </div>
      <button id="signup-button25" ng-click="signup()" class="button button-assertive  button-block button-positive">Signup</button>
      <a ui-sref="login" id="signup-button26" class="button button-positive  button-block">Already have an account</a>
    </form>

Comments

  1. Thank you for the tip!
    It saved me a lot of time of investigation!

    ReplyDelete
  2. Thanks for the tip! Do you happen to have sample code for how to handle the login part of auth with Ionic/Firebase? Having trouble finding a straight-forward answer on Google.

    ReplyDelete
    Replies
    1. I do but the project is not public. Do you want a sample ionic app for the same .

      Delete
    2. Sure, if you can send a link it would be helpful! I have it working, but I think It's not implemented perfectly. Thanks!

      Delete
    3. Hi Kyle , I have updated the blog post with the signup and login snippet. Not sure if this is as per guidelines because I couldn't get any example for the same, but this works on my production instance perfectly fine. Let me know if you see any issues.

      Delete
  3. This code snippet helped me Thanks, Actually my app was not giving me error when I click on login button so I had to click again then only it was showing error. So I used the Promise thing you did and it worked. Great help.

    http://www.webdata-scraping.com

    ReplyDelete
  4. Excellent, will try when I get home tonight.
    Thanks for posting

    ReplyDelete
  5. please how did you add the codes especially the login snippet to the creator?

    ReplyDelete
    Replies
    1. Are you asking about the JS section provided at the bottom of the web UI?

      Delete

Post a Comment

Popular posts from this blog

Big Data - SWOT Analysis

LINKEDIN api call using NODE.JS OAUTH module