Skip to content

Latest commit

 

History

History
705 lines (493 loc) · 19.6 KB

v3.md

File metadata and controls

705 lines (493 loc) · 19.6 KB

Using AngularFire with Ionic 3

This tutorial provides a walkthrough of integrating AngularFire Authentication with Ionic 3 /Angular 4+. The below setup has been tested on Windows 10 and macOS Sierra, but it should be same for Linux.

Note: - If you're working with Ionic2 and Angular2.0, then you should refer to Auth-with-Ionic2 tutorial here

Ensure that you're executing these commands as Administrator on Windows and sudo on Mac/Linux if you get any permission errors.

This tutorial uses Facebook as the sign-in provider. After completing this tutorial, you should be able to configure other sign-in providers like Twitter, Google on your own.

Prerequisites

The first step is to ensure you have latest version of Node installed. You can get the latest version from nodejs.org. This will install both node and npm.

After installing node, check the version by executing the following command in your prompt window:

$ node -v
v6.10.2

As of this writing, this is the most stable version. If you're not on this version, please upgrade yourself to latest stable version by installing node from nodejs.org.

Check your npm version by executing the following command:

$ npm -v
3.10.10

Install the Angular CLI, which will be used to build our Angular project and install Angular version 4 or later.

$ npm install -g @angular/cli

Check your angular version by executing the following command:

$ ng -v

@angular/cli: 1.0.0
node: 6.10.2
os: win32 x64

Your Application code sits on top of Ionic Framework and the Ionic Framework sits on top of Cordova.

Let's get them installed globally, so that all projects can use them.

Execute the following commands.

$ npm install -g cordova ionic

Once the above command is executed successfully, check the versions of cordova and ionic:

$ cordova -v
7.0.1

$ ionic -v
3.4.0

You're all set to create your app with Ionic framework.

To create your app, change into the directory where you want your app to reside and execute the following command:

$ ionic start auth-ng4-ionic3-af2 blank

The command ionic start will create the project with name "auth-ng4-ionic3-af2" using "blank" template.

Change to the project directory, which was just created with the above command.

$ ionic info

global packages:

    @ionic/cli-utils : 1.4.0
    Cordova CLI      : 7.0.1
    Ionic CLI        : 3.4.0

local packages:

    @ionic/app-scripts              : 1.3.12
    @ionic/cli-plugin-cordova       : 1.4.0
    @ionic/cli-plugin-ionic-angular : 1.3.1
    Cordova Platforms               : none
    Ionic Framework                 : ionic-angular 3.5.0

System:

    Node       : v8.1.2
    OS         : Windows 10
    Xcode      : not installed
    ios-deploy : not installed
    ios-sim    : not installed
    npm        : 5.0.4

You need to ensure you've got Ionic Framework Version 3, as shown above.

Alternatively you can open package.json to ensure you've got the following Angular and Ionic versions:

"dependencies": {
    "@angular/common": "4.1.3",
    "@angular/compiler": "4.1.3",
    "@angular/compiler-cli": "4.1.3",
    "@angular/core": "4.1.3",
    "@angular/forms": "4.1.3",
    "@angular/http": "4.1.3",
    "@angular/platform-browser": "4.1.3",
    "@angular/platform-browser-dynamic": "4.1.3",
    "@ionic-native/core": "3.12.1",
    "@ionic-native/splash-screen": "3.12.1",
    "@ionic-native/status-bar": "3.12.1",
    "@ionic/storage": "2.0.1",
    "ionic-angular": "3.6.0",
    "ionicons": "3.0.0",
    "rxjs": "5.4.0",
    "sw-toolbox": "3.6.0",
    "zone.js": "0.8.12"
  },
  "devDependencies": {
    "@ionic/app-scripts": "1.3.12",
    "@ionic/cli-plugin-ionic-angular": "1.3.1",
    "typescript": "~2.3.4"
  }

If not, replace them to match above. These are the latest as of writing this tutorial.

To start your app, execute the following command:

$ ionic serve

If everything is installed correctly, the app should open your browser with the dev server running at the following url http://localhost:8100 and will display default home page.

Configuring AngularFire and Firebase

Install the required packages in your project directory:

$ npm install angularfire2 firebase promise-polyfill --save

This should add angularfire2, promise-polyfill and firebase entry in your project's package.json file as dependencies. Something similar to:

"angularfire2": "^4.0.0-rc.1",
"firebase": "^4.1.3",
"promise-polyfill": "^6.0.2",

As the Angularfire2 v5+ rc10 requires rxjs6, you need to install rxjs-compat for angular version < 6.0:

npm install rxjs@6 rxjs-compat@6 promise-polyfill --save

Setup @NgModule

Open your project in your favourite editor and open the app.module.ts file, under src/app and add the following three entries.

  1. Import AngularFireModule and AngularFireDatabaseModule at top.

  2. Define your firebaseConfig constant.

  3. Initialize your app, by adding AngularFireModule and AngularFireAuthModule in the "imports" array in @NgModule

  4. Also, add AngularFireDatabase in the "providers" array in @NgModule

your app.module.ts file should look something like this.

import { BrowserModule } from '@angular/platform-browser';
import { ErrorHandler, NgModule } from '@angular/core';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
import { SplashScreen } from '@ionic-native/splash-screen';
import { StatusBar } from '@ionic-native/status-bar';

import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';

import { AngularFireModule } from '@angular/fire/compat';
import { AngularFireDatabaseModule, AngularFireDatabase } from '@angular/fire/compat/database';
import { AngularFireAuthModule } from '@angular/fire/compat/auth';

export const firebaseConfig = {
  apiKey: "xxxxxxxxxx",
  authDomain: "your-domain-name.firebaseapp.com",
  databaseURL: "https://your-domain-name.firebaseio.com",
  storageBucket: "your-domain-name.appspot.com",
  messagingSenderId: '<your-messaging-sender-id>'
};

@NgModule({
  declarations: [
    MyApp,
    HomePage
  ],
  imports: [
    BrowserModule,
    IonicModule.forRoot(MyApp),
    AngularFireModule.initializeApp(firebaseConfig),
    AngularFireDatabaseModule,
    AngularFireAuthModule
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    HomePage
  ],
  providers: [
    StatusBar,
    SplashScreen,
    AngularFireDatabase,
    {provide: ErrorHandler, useClass: IonicErrorHandler}
  ]
})
export class AppModule {}

Inject AngularFire and Bind it to List

Now inject AngularFireDatabase in your component. Open your home.ts by going into src/pages/home/home.ts and make the following changes:

  1. Import "AngularFireDatabase" at the top of your component.
  1. Inject your AngularFireDatabase dependency in the constructor.
  1. Call the list method on AngularFireDatabase object.

Your home.ts file should look like this:

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';

import { AngularFireDatabase } from '@angular/fire/compat/database';
import { Observable } from 'rxjs/Observable';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {
  items: Observable<any[]>;

  constructor(public navCtrl: NavController, afDB: AngularFireDatabase) {
    this.items = afDB.list('cuisines').valueChanges();
  }

}

*Ensure you've cuisines node in your database with some primitive data.

Update your home.html at src/pages/home/home.html, with following entry

<ion-header>
	<ion-navbar>
		<ion-title>
			Ionic Blank
		</ion-title>
	</ion-navbar>
</ion-header>

<ion-content padding>
	<ion-list>
		<ion-item class="text" *ngFor="let item of items | async">
			{{item | json}}
		</ion-item>
	</ion-list>
</ion-content>

Run your app by executing the following command

C:\projects\auth-ng4-ionic3-af2> ionic serve

This should fetch the data from firebase.

Configuring Firebase/Facebook to talk to each other

Go to Facebook Developers Page here and create a new App.

Once the App is created, get the App ID and App Secret from the dashboard and come back to Firebase Console.

  1. Login to Firebase Console and click on the Authentication section on the left hand side of the menu.
  2. Click on Sign-In Method tab and click on Facebook under Sign-In Providers.
  3. Paste the App ID and App Secret copied from Facebook dashboard here.
  4. Next copy the "OAuth redirect URI" from Firebase console. We need to go back and add it in Facebook dashboard.

This URI is important, since it tells facebook, where to redirect a user, once he is successfully authenticated.

  1. Click the Save button and come back to the facebook dashboard.

Go to your app in Facebook developers site ( Facebook Dashboard )

  1. Ensure you see Facebook Login under products section, if not add it via the Add Product Button.
  2. Once you see Facebook Login under products, click on the button to go to settings and there you should see "Valid OAuth redirect URIs" input field.
  3. Enter the URI copied from Firebase Console and click on Save Changes.

That's it. This will ensure Facebook and Firebase are able to talk to each other.

As we were able to fetch data from Firebase database in the above step, let's focus on authentication below, by removing calls to fetch data.

Let's add the following two buttons in our home.html

The home.html should look like below

<ion-header>
	<ion-navbar>
		<ion-title>
			Auth with Ionic
		</ion-title>
	</ion-navbar>
</ion-header>

<ion-content padding>
	<button ion-button outline (click)="signInWithFacebook()">Login</button>  
  <button ion-button outline (click)="signOut()">Logout</button>
</ion-content>

Let's update the home.ts to add the corresponding methods:

  1. First import AngularFireAuth from angularfire2/auth.
  2. Inject AngularFireAuth in the constructor
  3. The AngularFireAuth has various signIn methods to which we can pass instance of AuthProviders as shown below.

The home.ts should look like below

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';

import { AngularFireAuth } from '@angular/fire/compat/auth';
import firebase from 'firebase/app';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {

  constructor(public navCtrl: NavController,
    private afAuth: AngularFireAuth) { }

  signInWithFacebook() {
    this.afAuth.auth
      .signInWithPopup(new firebase.auth.FacebookAuthProvider())
      .then(res => console.log(res));
  }

  signOut() {
    this.afAuth.auth.signOut();
  }

}

Note the import of firebase from firebase/app, to take advantage of the tree-shaking

Also, update your app.module.ts to contain following import

import { AngularFireAuthModule } from '@angular/fire/compat/auth';

and add it to the imports array.

Run the app and click on the Login Button, you should see a pop-up asking you to enter username and password for Facebook to authenticate. Once authenticated, you should see the response from Facebook in console window.

Inspect the Object in the console, under user property, you should see all the attributes and we're going to use two of them, next.

Let's get the displayName from the user property, which we just saw on the console to be rendered on the screen. The AngularFireAuth has an authState property, which returns an observable, let's subcribe it to get notified everytime the Authentication state changes.

Add class property displayName and subscribe to the AngularFireAuth.authState property in the constructor. Also add the property in our template to render them on screen.

Your home.ts should look as follows:

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';

import { AngularFireAuth } from '@angular/fire/compat/auth';
import firebase from 'firebase/app';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {

  displayName;  

  constructor(public navCtrl: NavController,
    private afAuth: AngularFireAuth) {
    afAuth.authState.subscribe(user => {
      if (!user) {
        this.displayName = null;        
        return;
      }
      this.displayName = user.displayName;      
    });
  }

  signInWithFacebook() {
    this.afAuth.auth
      .signInWithPopup(new firebase.auth.FacebookAuthProvider())
      .then(res => console.log(res));
  }

  signOut() {
    this.afAuth.auth.signOut();
  }

}

and home.html should look like this:

<ion-header>
	<ion-navbar>
		<ion-title>
			Auth with Ionic
		</ion-title>
	</ion-navbar>
</ion-header>

<ion-content padding>

  <h1>Hello {{displayName}}</h1>  
  
	<button ion-button outline (click)="signInWithFacebook()">Login</button>  
  <button ion-button outline (click)="signOut()">Logout</button>
</ion-content>

Now run your app and if everything is configured correctly, you should be able to click on the login button in your app, which should open the facebook pop-up.

Once you authenticate yourself, you should see your Facebook display name on your screen. Click the Logout button, which will make the AuthState to null and you should see the difference on your screen.

You can try redirecting yourself to another page to grab additional details from Facebook and experiment on your own.

Running our application on mobile phone

Ensure you've the platform added to your project. If not add the platform by executing the following command:


C:\projects\auth-ng4-ionic3-af2>ionic platform add android

This adds android platform for your project. Replace android with ios, if you're on Mac book or add both. The generic command is ionic platform add <platform-name>

Now, let's try to run the app in browser. Execute the command:


C:\projects\auth-ng4-ionic3-af2> ionic run android

This should run the app on your mobile phone. Now click on the Facebook button and you'll notice the button doesn't work anymore. This is because the code written so far is good for running our application in browsers, but when running the application on mobile phones, we need to have access to Native Mobile API's, which are provided by Cordova Plugins.

We can access these cordova plugins, using Ionic Native, which are nothing but wrappers for cordova plugins.

List of all Ionic Native API's for cordova plugins can be found here.

Let's look at configuring and installing the Facebook plugin here. Ensure you follow the steps correctly to configure your app.

Login to the Facebook dashboard here, go to your App and make a note of your App ID. Next go to command prompt in your project directory and execute the following command by replacing the APP_ID with your App Id and APP_NAME with your App Name.

C:\projects\auth-ng4-ionic3-af2>
ionic cordova plugin add cordova-plugin-facebook4 --variable APP_ID="123456789" --variable APP_NAME="myApplication"

This should add the following entry in your config.xml, located at the root of your project:

<plugin name="cordova-plugin-facebook4" spec="~1.7.4">
        <variable name="APP_ID" value="1689092456387654" />
        <variable name="APP_NAME" value="auth-ng4-ionic3-af2" />
</plugin>

This will install the cordova plugin for facebook.

You should also see a sub-folder named cordova-plugin-facebook4 under your plugins folder.

Add the native dependencies by executing the following command:

C:\projects\auth-ng4-ionic3-af2>npm install --save @ionic-native/facebook

After executing the above command, ensure you have the following entry in your package.json:

"@ionic-native/facebook": "^3.12.1",

Now import the Platform and Facebook objects in your home.ts and inject the objects in constructor.

import { Platform } from 'ionic-angular';
import { Facebook } from '@ionic-native/facebook';

Update the "signInWithFacebook" method and use Platform Service to determine the platform and run the appropriate code.

Your home.ts should look as below:

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';

import { AngularFireAuth } from '@angular/fire/compat/auth';
import firebase from 'firebase/app';

import { Platform } from 'ionic-angular';
import { Facebook } from '@ionic-native/facebook';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {

  displayName;

  constructor(public navCtrl: NavController,
    private afAuth: AngularFireAuth, private fb: Facebook, private platform: Platform) {
    afAuth.authState.subscribe((user: firebase.User) => {
      if (!user) {
        this.displayName = null;
        return;
      }
      this.displayName = user.displayName;      
    });
  }

  signInWithFacebook() {
    if (this.platform.is('cordova')) {
      return this.fb.login(['email', 'public_profile']).then(res => {
        const facebookCredential = firebase.auth.FacebookAuthProvider.credential(res.authResponse.accessToken);
        return firebase.auth().signInWithCredential(facebookCredential);
      })
    }
    else {
      return this.afAuth.auth
        .signInWithPopup(new firebase.auth.FacebookAuthProvider())
        .then(res => console.log(res));
    }
  }

  signOut() {
    this.afAuth.auth.signOut();
  }

}

You'll also need to add the "Facebook" object in the provider section in app.module.ts.

The final app.module.ts should look like below:

import { BrowserModule } from '@angular/platform-browser';
import { ErrorHandler, NgModule } from '@angular/core';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
import { SplashScreen } from '@ionic-native/splash-screen';
import { StatusBar } from '@ionic-native/status-bar';

import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';

import { AngularFireModule } from '@angular/fire/compat';
import { AngularFireDatabaseModule } from '@angular/fire/compat/database';
import { AngularFireAuthModule } from '@angular/fire/compat/auth';
import { Facebook } from '@ionic-native/facebook';

export const firebaseConfig = {
  apiKey: "xxxxxxxxxx",
  authDomain: "your-domain-name.firebaseapp.com",
  databaseURL: "https://your-domain-name.firebaseio.com",
  storageBucket: "your-domain-name.appspot.com",
  messagingSenderId: '<your-messaging-sender-id>'
};

@NgModule({
  declarations: [
    MyApp,
    HomePage
  ],
  imports: [
    BrowserModule,
    IonicModule.forRoot(MyApp),
    AngularFireModule.initializeApp(firebaseConfig),
    AngularFireDatabaseModule,
    AngularFireAuthModule
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    HomePage
  ],
  providers: [
    StatusBar,
    SplashScreen,
    {provide: ErrorHandler, useClass: IonicErrorHandler},
    Facebook
  ]
})
export class AppModule {}

Verfiy your app is running in browser by executing the following command:

C:\projects\auth-ng4-ionic3-af2>ionic serve

Everything should work. Now trying running the app on your android phone:

C:\projects\auth-ng4-ionic3-af2> ionic cordova run android

Once the App launches click on the Login button. You should get the Facebook pop-up window. Enter your credentials. On successful authentication, you should see your Facebook Display name and profile picture on your screen.