Firebase authenticationionic app authenticationionic authenticationionic loginionic platformionic push notificationsionic signinnative buildsuser authentication
Add Firebase authentication to your Ionic App
Authentication it’s a huge component on your app, it will enable to build a relation with your users.
Sign up or Registration, Sign in or Log in, you name it, these are the key to engage with them. Whether you want users to participate by leaving comments, blogging, leaving messages onto boards, posting photos or creating a personal network - participation needs to be attributed and/or associated with the user for purposes of building community and reputation, or creating a personal profile or knowledge base. This is why is imperative to build authentication the right way!
BaaS/PaaS Authentication
Advantages of using a PaaS:
- Update and Maintenance of database tools, systems and infrastructure is full responsibility of the PaaS Cloud Provider.
- Some PaaS providers give developing options to multiple platforms: mobile, browser, among others.
- Cloud PaaS provider can deliver better security measures than the existing software.
- There’s no need to manage the introduction of new versions of software or code. This is handle by the Cloud PaaS provider.
- There’s no need to supply servers or to manage the underlying data center.
Without further ado, let’s get our hand on with the code!
Hands on!
Remember ... you will need:
- An Ionic App where you will integrate this login. You can either use a blank app, or an existing one. If you don’t have one, you should check out these beautiful templates that’ll save you time.
- A Firebase account. If you haven't created a Firebase account yet, you will need to sign upfor one.
- A Facebook developer account. If you haven't done this yet, create one here.
Ad time!: If you are looking for a beautiful starter app with login UI/UX you must have a look at our beautiful mobile themes, templates & components. Specially our Logins Category.
Setup
Install Ionic
You can find the Ionic official installation documentation here.
Follow these links if you want more information on how to get started:
Other Dependencies
We are also going to use two javascript client side libraries:
- The Firebase web client [
firebase.js
]We are using firebase.jsv2.4.2
which is the last version before the new firebasev3.x
- And the AngularJS bindings for Firebase [
angularfire.js
]We will use angularfire.jsv1.2.0
which is the last version compatible with firebase.jsv2.x.x
. The new angularfire.jsv2.x.x
depends on firebase.jsv3.x.x
Add these dependencies to your
bower.json
file and then run bower install to install them. You can also run bower install firebase#2.4.2 --save and bower install angularfire#1.2.0 --saveand that will handle the installation also.Step 1: Set up your Firebase App
First of all, we should create a Firebase account and create a new Firebase app. As we mentioned before, we are going to use Firebase as our PaaS. It’s gonna be our data store where we will save all the users data.
We will use this Firebase App both for the email / password and Facebook authenticationproviders options.
Step 2: Register your Facebook app
In this section I will help you configuring your Facebook app.
- Go to your Facebook app dashboard (If you don’t have a developer Facebook account, please create one here)
Once in the dashboard, create a new Facebook App for our project. As we are going to implement the javascript facebook authentication, you should choose the website platform when creating the new facebook app.
NOTE: If you are looking for the native facebook authentication, please consider looking at this post: Add Facebook Native Login to your Ionic App. There you can also find more information about the differences between Facebook javascript and native approaches for authentication.
After creating the Facebook app, you should go to the app’s dashboard and on the Products section click Add Product to add the Facebook Login product.

Afterwards, we only need to add a redirection URL under the Valid OAuth redirect URIs field. The redirection URL should be like this
https://auth.firebase.com/v2/ /auth/facebook/callback
.
Use the Firebase app name from the Step 1.

Just a little thing before going to the next step. Go to Settings and grab your
App ID
and App Secret
from your Facebook app. We will need them later on in this tutorial.
NOTE: If you need further help for these configurations, please check this section of the Firebase documentation.
Step 3: Hook up our Facebook App with Firebase
After having both Firebase and Facebook apps ready we need to set up some minor stuff before proceeding to code.
Go to your Firebase dashboard and under the Login & Auth select the Facebook tab and paste your Facebook
App ID
and App Secret
you got on Step 2.
Step 4: Ionic Templates & AngularJS Navigation
Now we will go straight to the code, so open your Ionic App with your preferred code editor. Personally we recommend atom.
For this example app we are going to build a simple navigation schema that will enable us to have both login and signup views, and only one authenticated view with the user profile information. This user view will be only accessible for authenticated users.
This image illustrates the navigation between views

The app will have two main nodes in the navigation, one for the auth section of the app (login, signup views) and other for the main section of the app (user view).

To achieve this, we are going to:
- Use
www/index.html
with default app’s placeholder - Add
www/templates/auth/login.html
with basic login view layout - Add
www/templates/auth/signup.html
with basic signup view layout - Add
www/templates/app/user.html
with basic user details view layout - Update
www/js/app.js
with app’s desired routing - Update
www/js/controllers.js
with a basic controllers for each view
App Placeholder (index.html
)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
<title></title>
<!-- compiled css output -->
<link href="css/ionic.app.css" rel="stylesheet">
<!-- vendor js -->
<script src="lib/ionic/js/ionic.bundle.js"></script>
<script src="lib/firebase/firebase.js"></script>
<script src="lib/angularfire/dist/angularfire.min.js"></script>
<!-- cordova script (this will be a 404 during development) -->
<script src="cordova.js"></script>
<!-- your app's js -->
<script src="js/app.js"></script>
<script src="js/controllers.js"></script>
<script src="js/services.js"></script>
</head>
<body ng-app="starter">
<ion-nav-view name="main-view"></ion-nav-view>
</body>
</html>
App Routes (js/app.js
)
.config(function($stateProvider, $urlRouterProvider) {
// Ionic uses AngularUI Router which uses the concept of states
// Learn more here: https://github.com/angular-ui/ui-router
// Set up the various states which the app can be in.
// Each state's controller can be found in controllers.js
$stateProvider
// setup an abstract state for the auth section
.state('auth', {
url: '/auth',
abstract: true
})
.state('auth.login', {
url: '/login',
views: {
'main-view@': {
templateUrl: 'templates/auth/login.html',
controller: 'LogInCtrl'
}
},
data: {
authenticate: false
}
})
.state('auth.signup', {
url: '/signup',
views: {
'main-view@': {
templateUrl: 'templates/auth/signup.html',
controller: 'SignUpCtrl'
}
},
data: {
authenticate: false
}
})
.state('app', {
url: '/app',
abstract: true
})
.state('app.user', {
url: '/user',
views: {
'main-view@': {
templateUrl: 'templates/app/user.html',
controller: 'UserCtrl'
}
},
data: {
authenticate: true
}
})
;
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/app/user');
})
Serve the app with ionic serve and look at the Ionic dev server running on
http://localhost:8100
. There you’ll see the Ionic Auth app with the navigation DONE.Step 3: Login/Signup Layout
The layout of login and signup views is very similar and simple. Note that we added basic
angular.js
form validation using ng-disabled directive and required attributes on the fields just to prevent the submission of the form if the fields are empty.
Login View (templates/auth/login.html
)
<ion-view>
<ion-header-bar class="bar-stable">
<h1 class="title">Log In</h1>
</ion-header-bar>
<ion-content class="padding">
<button class="button button-block button-positive" ng-click="facebookLogin()">Login with Facebook</button>
<div class="row">
<div class="col col-center">
<h4 class="text-center">OR</h4>
</div>
</div>
<form name="login_form" class="form-container" novalidate>
<div class="list list-inset">
<label class="item item-input">
<input type="email" placeholder="Email" ng-model="user.email" required>
</label>
<label class="item item-input">
<input type="password" placeholder="Password" ng-model="user.password" required>
</label>
</div>
<button class="button button-block button-balanced" ng-click="login(user)" ng-disabled="login_form.$invalid">Login</button>
</form>
<button class="button button-block button-clear button-positive button-small" ui-sref="auth.signup">
Sign Up
</button>
<div ng-show="errors">
<p class="message error" ng-repeat="error in errors"><b>[{{error.code}}]</b> {{error.msg}}</p>
</div>
</ion-content>
</ion-view>
Signup View (templates/auth/signup.html
)
<ion-view>
<ion-header-bar class="bar-stable">
<h1 class="title">Sign Up</h1>
</ion-header-bar>
<ion-content class="padding">
<form name="signup_form" class="form-container" novalidate>
<div class="list list-inset">
<label class="item item-input">
<input type="email" placeholder="Email" ng-model="data.email" required>
</label>
<label class="item item-input">
<input type="password" placeholder="Password" ng-model="data.password" required>
</label>
</div>
<button class="button button-block button-energized" ng-click="signup(data)" ng-disabled="signup_form.$invalid">Create Account</button>
</form>
<button class="button button-block button-clear button-positive button-small" ui-sref="auth.login">
Already have an account?
</button>
<div ng-show="errors">
<p class="message error" ng-repeat="error in errors"><b>[{{error.code}}]</b> {{error.msg}}</p>
</div>
</ion-content>
</ion-view>
Step 4: App Controllers & Authentication Implementation
The angular.js controllers are the bridge between the views and the main functionality of the app. In this case we choose to add another layer of abstraction. Instead of having the authentication functionality directly in the controllers, we added an AuthService that handles all the authentication communication between our app and the Firebase services.
This way we add independence and if you want to have another provider for the authentication you just have to add a new service with the same signature methods and forget about changing the controllers.
App Controllers (js/controllers.js
)
.controller('LogInCtrl', function($scope, $state, AuthService, $ionicLoading) {
$scope.login = function(user){
$ionicLoading.show({
template: 'Logging in ...'
});
AuthService.doLogin(user)
.then(function(user){
// success
$state.go('app.user');
$ionicLoading.hide();
},function(err){
// error
$scope.errors = err;
$ionicLoading.hide();
});
};
$scope.facebookLogin = function(){
$ionicLoading.show({
template: 'Logging in with Facebook ...'
});
AuthService.doFacebookLogin()
.then(function(user){
// success
$state.go('app.user');
$ionicLoading.hide();
},function(err){
// error
$scope.errors = err;
$ionicLoading.hide();
});
};
})
.controller('SignUpCtrl', function($scope, $state, AuthService, $ionicLoading) {
$scope.signup = function(user){
$ionicLoading.show({
template: 'Signing up ...'
});
AuthService.doSignup(user)
.then(function(user){
// success
$state.go('app.user');
$ionicLoading.hide();
},function(err){
// error
$scope.errors = err;
$ionicLoading.hide();
});
};
})
.controller('UserCtrl', function($scope, $state, AuthService){
$scope.current_user = {};
var current_user = AuthService.getUser();
if(current_user && current_user.provider == "facebook"){
$scope.current_user.email = current_user.facebook.displayName;
$scope.current_user.image = current_user.facebook.profileImageURL;
} else {
$scope.current_user.email = current_user.password.email;
$scope.current_user.image = current_user.password.profileImageURL;
}
$scope.logout = function(){
AuthService.doLogout();
$state.go('auth.login');
};
})
Authentication service using Firebase (js/services.js
)
.service('AuthService', function($q){
var _firebase = new Firebase("https://logfirebase.firebaseio.com/");
this.userIsLoggedIn = function(){
var deferred = $q.defer(),
authService = this,
isLoggedIn = (authService.getUser() !== null);
deferred.resolve(isLoggedIn);
return deferred.promise;
};
this.getUser = function(){
return _firebase.getAuth();
};
this.doLogin = function(user){
var deferred = $q.defer();
_firebase.authWithPassword({
email : user.email,
password : user.password
}, function(errors, data) {
if (errors) {
var errors_list = [],
error = {
code: errors.code,
msg: errors.message
};
errors_list.push(error);
deferred.reject(errors_list);
} else {
deferred.resolve(data);
}
});
return deferred.promise;
};
this.doFacebookLogin = function(){
var deferred = $q.defer();
_firebase.authWithOAuthPopup("facebook", function(errors, data) {
if (errors) {
var errors_list = [],
error = {
code: errors.code,
msg: errors.message
};
errors_list.push(error);
deferred.reject(errors_list);
} else {
deferred.resolve(data);
}
});
return deferred.promise;
};
this.doSignup = function(user){
var deferred = $q.defer(),
authService = this;
_firebase.createUser({
email : user.email,
password : user.password,
}, function(errors, data) {
if (errors) {
var errors_list = [],
error = {
code: errors.code,
msg: errors.message
};
errors_list.push(error);
deferred.reject(errors_list);
} else {
// After signup we should automatically login the user
authService.doLogin(user)
.then(function(data){
// success
deferred.resolve(data);
},function(err){
// error
deferred.reject(err);
});
}
});
return deferred.promise;
};
this.doLogout = function(){
_firebase.unauth();
};
})
Remember we mentioned earlier that we were going to implement both email / password and facebook authentication options using Firebase providers. In Step 3 we hook up everything to enable the Firebase Facebook auth provider.
Now it’s time to implement the code for that.
We are also going to put it in the AuthService to gain abstraction in our code. This is how it looks like:
Authentication service using Firebase Facebook provider (js/services.js
)
this.doFacebookLogin = function(){
var deferred = $q.defer();
_firebase.authWithOAuthPopup("facebook", function(errors, data) {
if (errors) {
var errors_list = [],
error = {
code: errors.code,
msg: errors.message
};
errors_list.push(error);
deferred.reject(errors_list);
} else {
deferred.resolve(data);
}
});
return deferred.promise;
};
Step 5: Final details
The last thing we are going to do is to add some code in the app.js file to handle only the authentication views. We will check if the view state requires authentication and if the user is authenticated and based on that decide whether or not show him the view.
App run method (js/app.js
)
.run(function($ionicPlatform, $rootScope, $state, AuthService) {
$ionicPlatform.ready(function(){
AuthService.userIsLoggedIn().then(function(response)
{
if(response === true)
{
$state.go('app.user');
}
else
{
$state.go('auth.login');
}
});
// 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);
cordova.plugins.Keyboard.disableScroll(true);
}
if (window.StatusBar) {
// org.apache.cordova.statusbar required
StatusBar.styleDefault();
}
});
// UI Router Authentication Check
$rootScope.$on("$stateChangeStart", function(event, toState, toParams, fromState, fromParams){
if (toState.data.authenticate)
{
AuthService.userIsLoggedIn().then(function(response)
{
if(response === false)
{
event.preventDefault();
$state.go('auth.login');
}
});
}
});
})
0 comments