Ionic + Parse

User Authentication with Ionic 1.x and Parse, Part 1: Email Login



·

Creating a login system for any kind of application, mobile or desktop, has historically been a pretty hard task. In the case of a mobile app it would at least involve:

  • Setting up a secure server
  • Creating a database to hold user information
  • Posting information from the app to a script on the server which would create and store a user
  • Posting information from the app to a script on the server which would check the users existing credentials
  • Sending user and session data from the server back to the app
  • and so on…

Not only is this difficult to set up, but it adds many more layers of complexity to your app which means more places things can go wrong. Services like Parse make this process a lot easier. It provides a simple API for doing a lot of things that many mobile applications require like:

  • User Authentication
  • Data Storage
  • Using Social APIs
  • Push Notifications

which is great because it means you can just focus on building your app, without having to worry about servers and databases. Plus, their platform will scale a lot more easily as your users grow as well. Parse is a paid service of course, but it does have a very decent pricing structure and a free tier for apps without much traffic.

So, Parse does a lot of fancy stuff but in this tutorial I’m going to show you how we can set up user authentication with an email login in an Ionic application with Parse. If you’ve never used a service like Parse before you’ll probably be surprised at how few steps this tutorial has.

NOTE: Ionic’s ionic.io platform seems to be heading in the direction of Parse, so in the not too distant future you may be able to do all of this within Ionic’s ecosystem.

Creating an Application in Parse

Before you can use Parse you will need to sign up, and then create a new app in Parse. You can follow their quickstart guide to get up and running quickly. First, choose the service you want to use:

Parse Dashboard

In this case we will be using Social. Next you will choose your environment:

Parse Dashboard

You might assume we would want to choose Mobile but we will actually be using Web. Since we are using a HTML5 mobile framework we want to use the JavaScript SDK, not the native SDKs in the mobile section. On the next screen, you should choose Existing Project:

Parse Dashboard

and then you will come to a screen with some installation instructions:

Parse Dashboard

It doesn’t really matter which service you choose and the setup is always the same anyway, but by choosing Social we also get an example of how to implement some user authentication in our application. I’ll be walking you through how you can set that up in an Ionic application now.

Generate a new Ionic Application

Let’s generate a new blank Ionic application by running:

ionic start ionic-parse blank

If you don’t have Ionic installed on your machine yet, take a look at this post for getting started with Ionic. If you’re new to Ionic though, you’re probably jumping the gun a bit by building a login system! If you want to take a look at a comprehensive course on building an Ionic application from scratch you should check out Mobile Development for Web Developers.

Although we won’t really be using it in this tutorial, it’s a good idea to set up SASS when starting any new Ionic application, so you should also run:

ionic setup sass

Setting up Parse in an Ionic Application

In an Ionic project you will need to add the Parse library to your index.html file before you can use it in your application.

Add the following code to your index.html file

    <!-- ionic/angularjs js -->
    <script src="lib/ionic/js/ionic.bundle.js"></script>
    <script type="text/javascript" src="http://www.parsecdn.com/js/parse-1.4.2.min.js"></script>

Once you’ve included that you can then initialize Parse by adding some code to your run method.

Add the following code to app.js

.run(function($ionicPlatform) {
  $ionicPlatform.ready(function() {
    // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
    // for form inputs)
    if(window.cordova && window.cordova.plugins.Keyboard) {
      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
    }
    if(window.StatusBar) {
      StatusBar.styleDefault();
    }

    Parse.initialize("YOUR APP ID", "JAVASCRIPT KEY");

  });
});

Parse is now ready to use within your application.

Users

Users are one of the core features of Parse. Essentially, we can create a User object with Parse, store data on that user object including login information, and easily authenticate users and manage sessions. First we will need to create a new User on Parse with some information provided by the person signing up, and then we need to allow that user to sign in with their existing account later.

Creating a new User with Parse

Let’s create an email sign up form to to create a new user. I’ve built a form that looks like this:

Ionic Sign Up Screen

to create that we will first create a template for it.

Create a new folder called templates at www/templates

Create a new file in templates called signup.html and add the following code:

<ion-view title="Sign Up">
    <ion-content padding="true" class="has-header">
        <form>
            <ion-list>
                <label class="item item-input">
                    <span class="input-label">Username</span>
                    <input type="text" placeholder="enter username..." ng-model="data.username">
                </label>
                <label class="item item-input">
                    <span class="input-label">Email</span>
                    <input type="email" placeholder="[email protected]" ng-model="data.email">
                </label>
                <label class="item item-input">
                    <span class="input-label">Password</span>
                    <input type="password" placeholder="At least 6 characters" ng-model="data.password">
                </label>
            </ion-list>
            <button class="button button-stable button-block" ng-click="signupEmail()">Done</button>
        </form>
    </ion-content>
</ion-view>

We’re also going to need a way to activate that view, so let’s add some routing to the application. First we will modify our index.html file to use an <ion-view>.

Make the following changes to index.html

  <body ng-app="starter">
    <ion-nav-bar align-title="center" class="bar-calm nav-title-slide-ios7">
      <ion-nav-back-button class="button-clear">
        <i class="ion-arrow-left-c"></i> Back
      </ion-nav-back-button>
    </ion-nav-bar>
    <ion-nav-view></ion-nav-view> 
  </body>

We’ve also added an <ion-nav-bar> so that the user can navigate around the application. Now we’ll need to add some routes in app.js.

Make the following changes to app.js

.config(function($stateProvider, $urlRouterProvider) {

  $stateProvider
  .state('login', {
    url: '/',
    templateUrl: 'templates/login.html',
    controller: 'LoginCtrl'
  })
  .state('signup', {
    url: '/signup',
    templateUrl: 'templates/signup.html',
    controller: 'LoginCtrl'
  });

  $urlRouterProvider.otherwise("/");

})

So we have two routes here, one that uses the singup.html template we have already created, and one that uses login.html. We’ll need to create another template now called login.html which will allow the user to choose to either sign up or sign in (we will add sign in functionality later).

Create a new file in the templates folder called login.html and add the following code

<ion-view title="Welcome!">
    <ion-content>

      <a href = "#/signup" class="button button-positive" style="width: 100%; margin: 20px 0;">
        Sign Up
      </a>

      <a href = "#/signin" class="button button-positive" style="width: 100%; margin: 20px 0;">
        Sign In
      </a>

    </ion-content>
</ion-view>

You will also notice that we have supplied a controller called LoginCtrl in the routing which we have not created yet. If you take a look at signup.html you will see that when the user clicks Done a function called signupEmail() is triggered. This function will live in the login controller and since we can bind data between a view and a controller in Ionic, once we create this LoginCtrl we will be able to access all of the values for the form since we have defined ng-model on them.

Add the following controller to your app.js file

.controller('LoginCtrl', function($scope, $state) {

  $scope.data = {};

  $scope.signupEmail = function(){  

  };

  $scope.loginEmail = function(){

  };

});

Now that we have all of that information available in the controller, and we have Parse set up, we want to create a new Parse User object, set some values on that User and then trigger the signUp method. We can do that by expanding upon the signupEmail function.

Modify the signupEmail function in your Login controller in app.js to reflect the following:

  $scope.signupEmail = function(){

    //Create a new user on Parse
    var user = new Parse.User();
    user.set("username", $scope.data.username);
    user.set("password", $scope.data.password);
    user.set("email", $scope.data.email);

    // other fields can be set just like with Parse.Object
    user.set("somethingelse", "like this!");

    user.signUp(null, {
      success: function(user) {
        // Hooray! Let them use the app now.
        alert("success!");
      },
      error: function(user, error) {
        // Show the error message somewhere and let the user try again.
        alert("Error: " + error.code + " " + error.message);
      }
    });

  };

You can see that I’m setting the username, password and email as you might expect, but I’m also setting another property called “somethingelse”. You can define absolutely anything you like on the object, which is obviously very useful since different apps will have very different goals. Some might want to store standard data like phone numbers and addresses, but maybe you want to store your users star sign or favourite celebrity, it doesn’t matter.

Calling the signUp method will create the User in your Parse backend. After going through the signup form, you should be able to see this entries like this in your Parse dashboard:

Parse Dashboard

Authenticating an Existing User with Parse

The code in the last section allows our users to create a new account and then access the app, but if they are a returning user we want them to be able to sign in instead of signing up. To do that we are going to create another screen like this:

Ionic Sign In Screen

Create a new file called signin.html in the templates folder and add the following code:

<ion-view title="Sign In">
    <ion-content padding="true" class="has-header">
        <form>
            <ion-list>
                <label class="item item-input">
                    <span class="input-label">Username</span>
                    <input type="text" placeholder="enter your username..." ng-model="data.username">
                </label>
                <label class="item item-input">
                    <span class="input-label">Password</span>
                    <input type="password" placeholder="enter your password..." ng-model="data.password">
                </label>
            </ion-list>
            <button class="button button-stable button-block" ng-click="loginEmail()">Done</button>
        </form>
    </ion-content>
</ion-view>

You will notice that this form is triggering loginEmail() instead of signupEmail(). We will get to that in a second, but first we will need to create another route for our new view.

Modify your routes in app.js to reflect the following

.config(function($stateProvider, $urlRouterProvider) {

  $stateProvider
  .state('login', {
    url: '/',
    templateUrl: 'templates/login.html',
    controller: 'LoginCtrl'
  })
  .state('signup', {
    url: '/signup',
    templateUrl: 'templates/signup.html',
    controller: 'LoginCtrl'
  })  
  .state('signin', {
    url: '/signin',
    templateUrl: 'templates/signin.html',
    controller: 'LoginCtrl'
  });

  $urlRouterProvider.otherwise("/");

})

Now let’s create the loginEmail function in the controller.

Modify the loginEmail function in app.js to reflect the following:

  $scope.loginEmail = function(){
    Parse.User.logIn($scope.data.username, $scope.data.password, {
      success: function(user) {
        // Do stuff after successful login.
        console.log(user);
        alert("success!");
      },
      error: function(user, error) {
        // The login failed. Check error to see why.
        alert("error!");
      }
    });
  };

If you try to log in now you should be able to do so with the user you just created:

Ionic Debug Message

If you take a look in the Console to the right of that image, you will see the user object that is being returned to our application. I’ve expanded the attributes property so that you can see the data we are storing for that user, including the “somethingelse” field.

BONUS CONTENT: Enter your email below and I’ll send you the complete source code for this tutorial:

That’s it! You now have authentication set up with Parse in an Ionic application. Obviously you would want to expand on this a bit for a real application (e.g. trigger some logged in view once the user signs in succesfully, add some error checking on the forms etc.) but this goes to show how much easier services like Parse make these tasks.

There’s a lot more you can do with Parse of course, so I will be doing some more tutorials in future. To start off with, I will be creating a series of posts about authentication with Ionic and Parse so stay tuned for Part 2!

Update: Part 2 is out!

What to watch next...

  • Pingback: User Authentication with Ionic and Parse, Part 2: Facebook Login | HTML5 Mobile Tutorials | Ionic, Phaser, Sencha Touch & PhoneGap()

  • Pingback: 170 Ionic Framework Resources()

  • Dan

    Hi Josh!

    Great tutorial! I was wondering if you had any suggestions or guidance on storing session data via ionic and parse. If so, that would be helpful.

    • Hi Dan, it should be fine to just store session data using local storage.

  • Pingback: Email and Facebook Authentication with Ionic and Firebase | HTML5 Mobile Tutorials | Ionic, Phaser, Sencha Touch & PhoneGap()

  • sunny

    Hi Josh,

    I got this working , however I am receiving 400 , logout badrequest invalid session token. Please help

  • Nuno

    Hello

    Thanks for detailed information, and I did manage to get it working…in browser.

    I’m trying to include this process in ionic app, but can’t get this to work. From the console, on Login I get this error:
    ReferenceError: Parse is not defined at Scope.$scope.loginEmail
    wich is the line: Parse.User.logIn($scope.data.username, $scope.data.password, {
    testing in browser does work fine (ionic serve) but after install in device not..

    I’m guessing we need to declare the Parse service , but I’m new to ionic and Angular JS..

  • Állif Henrique

    What would be the value to use parse?

  • shoaibbhimani

    thanks Josh 🙂

  • ShaneN

    Hi Josh,

    Great tutorial, really easy to follow and well explained.
    However I keep getting a “Error: undefined unauthorized” when I run the signup page.

    Any idea whats causing this or how I can fix it ?
    Thanks,
    Shane

    • nicholasz

      Shane,
      Did you ever figure out the problem you were having? I am having the same issue…

      • Mads

        You need to initialize the call. When creating a project in Parse, you get a intialization code, you need to modify in your app.js.

  • ablears

    Great stuff. I’m looking forward to Ionic.io’s offerings in this area as it’ll be good to do everything within the Ionic ecosystem.

  • Pingback: 200+ Ionic Framework Resources | Yahaay CodeStash()

  • Isaac Bhasme

    Great tutorial! But I have a question. When inspecting during login() I see that username and password is sent as plain text. Should SSL configuration be done separately?

  • mesk8080

    Hi, It’s a great tutorial, Can you please share how to send mail confirmation once the user has done registration?

  • César Bustíos Benites

    Congrats for the amazing tutorial! I have a question, how should I retrieve the user information after the login process? Should I just use Parse.Userr.current() every time or do I need to save the info locally?

  • Anderson Ferreira

    Parse will be discontinued in January 28, 2017 🙁
    http://blog.parse.com/announcements/moving-on/

  • chatur priyono

    Hi Josh, it’s great, can you please create posting user authentication with ionic 2? and what subtitution for parse if was discontinued?