This post is based on my previous post Ionic 2 and Firebase authentication.
You can download the code on GitHub at https://github.com/henkie14/ionic2Firebase. Make sure you change the Firebase configuration in the app.module.ts file.
In this post I will continue working on the project above and add native Facebook authentication to the Ionic app.
The first thing you will have to do is to create a new Facebook App in the Facebook developer portal, install the cordova Facebook plugin and configure your Facebook app for Android and/or iOS.
There is a nice installation guide on http://ionicframework.com/docs/v2/native/facebook/.
Make sure you do the installation up to the Events chapter and you are good to go.
For future use make sure you can find the Facebook App ID and App secret you will need them in a later stage.
Eventually you should have an APP_ID, an APP_NAME and the App secret.
Now you can run the following command. (Add –save if you want the plugin and configuration to be stored in your config.xml).
$ionic plugin add cordova-plugin-facebook4 --variable APP_ID="yourAppId" --variable APP_NAME="yourAppName" --save
Let’s add a Facebook login button to the home page, open up your home.html and change it like this:
<ion-header> <ion-navbar> <ion-title> Ionic2Firebase </ion-title> </ion-navbar> </ion-header> <ion-content padding> <ion-title>Login</ion-title> <ion-row> <ion-item> <div *ngIf="auth.authState">current user is {{auth.currentUser}}</div> </ion-item> </ion-row> <form [formGroup]="loginForm" (ngSubmit)="submit()" novalidate> <ion-row> <ion-item> <ion-label for="email"></ion-label> <ion-input type="email" value="" placeholder="Email" formControlName="email"></ion-input> </ion-item> </ion-row> <ion-row> <ion-item> <ion-label for="password"></ion-label> <ion-input type="password" placeholder="Password" formControlName="password"></ion-input> </ion-item> </ion-row> </form> <ion-row> <button (click)="login()" ion-button block>Log in</button> </ion-row> <ion-row> <button [navPush]="signupPage" ion-button block>Sign up</button> </ion-row> <!--new link to sign up page--> <ion-row> <button [navPush]="resetPasswordPage" ion-button block>Reset password</button> </ion-row> <ion-row> <button (click)="logout()" ion-button block>Log out</button> </ion-row> <ion-row> <button (click)="loginWithFacebook()" ion-button block>Facebook login</button> </ion-row> </ion-content>
And add the loginWithFacebook method to home.ts.
import { Component } from '@angular/core'; import { FormGroup, FormBuilder, Validators, AbstractControl } from '@angular/forms'; import { NavController } from 'ionic-angular'; import { AuthProvider } from '../../providers/auth-provider'; import { SignupPage } from '../signup/signup' import { ResetPasswordPage } from '../reset-password/reset-password' @Component({ selector: 'page-home', templateUrl: 'home.html' }) export class HomePage { loginForm: FormGroup; email: AbstractControl; password: AbstractControl; error: any; signupPage = SignupPage; resetPasswordPage = ResetPasswordPage constructor(private navCtrl: NavController, private fb: FormBuilder, private auth: AuthProvider) { this.loginForm = this.fb.group({ 'email': ['', Validators.compose([Validators.required, Validators.pattern(/[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/)])], 'password': ['', Validators.compose([Validators.required, Validators.minLength(1)])] }); this.email = this.loginForm.controls['email']; this.password = this.loginForm.controls['password']; } loginWithFacebook(): void{ this.auth.loginWithFacebook().subscribe((success) => { console.log(success); }, err => { console.log(err); }); } login(): void { if(this.loginForm.valid) { var credentials = ({email: this.email.value, password: this.password.value}); this.auth.loginWithEmail(credentials).subscribe(data => { alert('login succeeded'); console.log(data); }, error=>{ console.log(error); if (error.code == 'auth/user-not-found') { alert('User not found'); } }); } } logout(): void { this.auth.logout(); } }
Last part is the implementation on the authorization provider. Change auth-provider.ts like this:
import { Injectable, EventEmitter, Inject } from '@angular/core'; import { AuthProviders, AngularFire, FirebaseAuthState, AuthMethods, FirebaseApp } from 'angularfire2'; //Add FirebaseApp import { Observable } from "rxjs/Observable"; import { Platform } from 'ionic-angular'; import { Facebook } from 'ionic-native'; import { auth } from 'firebase'; //needed for the FacebookAuthProvider @Injectable() export class AuthProvider { private authState: FirebaseAuthState; public onAuth: EventEmitter<FirebaseAuthState> = new EventEmitter(); public firebase : any; constructor(private af: AngularFire, @Inject(FirebaseApp)firebase: any,private platform: Platform) { //Add reference to native firebase SDK this.firebase = firebase; this.af.auth.subscribe((state: FirebaseAuthState) => { this.authState = state; this.onAuth.emit(state); }); } loginWithFacebook() { return Observable.create(observer => { if (this.platform.is('cordova')) { return Facebook.login(['email', 'public_profile']).then(res => { const facebookCredential = auth.FacebookAuthProvider.credential(res.authResponse.accessToken); this.firebase.auth().signInWithCredential(facebookCredential).then(()=>{ observer.next(); }).catch(error => { //console.log(error); observer.error(error); }); }); } else { return this.af.auth.login({ provider: AuthProviders.Facebook, method: AuthMethods.Popup }).then(()=>{ observer.next(); }).catch(error => { //console.log(error); observer.error(error); }); } }); } loginWithEmail(credentials) { return Observable.create(observer => { this.af.auth.login(credentials, { provider: AuthProviders.Password, method: AuthMethods.Password }).then((authData) => { //console.log(authData); observer.next(authData); }).catch((error) => { observer.error(error); }); }); } registerUser(credentials: any) { return Observable.create(observer => { this.af.auth.createUser(credentials).then(authData => { //authData.auth.updateProfile({displayName: credentials.displayName, photoURL: credentials.photoUrl}); //set name and photo observer.next(authData); }).catch(error => { //console.log(error); observer.error(error); }); }); } resetPassword(emailAddress:string){ return Observable.create(observer => { this.firebase.auth().sendPasswordResetEmail(emailAddress).then(function(success) { //console.log('email sent', success); observer.next(success); }, function(error) { //console.log('error sending email',error); observer.error(error); }); }); } logout() { this.af.auth.logout(); } get currentUser():string{ return this.authState?this.authState.auth.email:''; } }
There’s a lot going on here, let me explain.
There’s an import of Platform, that’s being used to check on what platform the app is running, based on the platform we will call the native Facebook login or a pop-up.
The Facebook import is used for calling the native Facebook plugin.
The auth import from Firebase is needed since AngularFire2 doesn’t have support for the FacebookProvider (yet).
This is why it’s important to use the correct firebase (3.3.0) and angularfire2 (2.0.0-beta.6) versions. Otherwise you might end up with a lot of ‘Duplicate identifier’ errors.
Ok, let’s run the application to see if it’s working. First test it in your browser.
$ionic serve
When you try to login by Facebook you will see the following error:
The given sign-in provider is disabled for this Firebase project. Enable it in the Firebase console, under the sign-in method tab of the Auth section.
So let’s go to the Firebase console again at https://console.firebase.google.com and select your project.
Next select Authentication on the left hand side and click the tab ‘Sign in method’.
Click Facebook and enable it. Fill in you App Id and App secret, if you didn’t already write them down you can get them from your Facebook developer portal on the dashboard page (https://developers.facebook.com).
Make sure you copy the OAuth redirect URI and click the save button.
Now you should go back to the Facebook developer portal and click ‘+ add product’ on the lef hand side and select ‘Facebook Login’.
Next click ‘settings’ below Facebook Login on the left hand side and fill in the Auth redirect URI you’ve copied from the Firebase Facebook provider settings.
Let’s test it again in your browser.
$ionic serve
When you click the Facebook login button you should see a popup where you can connect with your Facebook account and when you login, it should show the corresponding email address as the current user.
You can also check the users tab on the authentication menu in the Firebase console to see all registered users and their provider.
Now let’s try it on android to see if the native Facebook functionality is working. Connect you Android phone and run the following commands.
$ionic platform add android $ionic run android
Okay, when trying to login by Facebook you will see a native popup, but with this message: “Facebook test error in development mode.”
This can be fixed by going to the Facebook developer portal again and after selecting your project, you should select ‘App Review’ from the menu on the left and make the app public.
This should be all!
If things don’t seem to work or you see the following Firebase error: auth/network-request-failed. Try this:
$ionic platform rm android $ionic platform add android
You can try it out on iOS by connecting you iOS device and run:
$ionic platform add ios $ionic run ios
Please leave a message if you got it working or not or things aren’t clear or whatever 🙂
Next is native Google login…
14 comments. Leave new
Your tutorial really helped me, thanks a lot. Hope you keep doing this.
Hey Chriz!
I’ve been following your tutorials, they’re so helpful. I manged to get the authentication with email and Firebase working fine but I’m having some issues with Facebook.
In the browser when I click the login to Facebook button it opens up a new balk popup window(as if it were about to ask for authentication) but then the window closes.
Console logs give back two errors I just can’t seem to fix:
1. Uncaught DOMException: Blocked a frame with origin “https://*my-app-name*.firebaseapp.com” from accessing a cross-origin frame.
at :1:15
2. POST https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyAssertion?key=*my-firebase-key* 400 ()
login.ts:40 R {code: “auth/internal-error”, message: “https://*myapp.firebaseapp.com/__/auth/handler”}
The second one seems like something wrong with my firebase side of things but I’ve made sure of all the config on the Facebook side and it is all enabled on Firebase side also!
I’m also using the versions of angular fire and firebase you specified. I’ve been really stuck on this issue so any ideas at all would be greatly appreciated!!!!
Thanks for the tutorial!
Alice
Hi Alice,
It’s hard to help without being able to reproduce the error…
Could you try to get some more information from the error message. (Add some extra console logging in the error handlers)
It might be something like this:
https://github.com/firebase/firebaseui-web/issues/10
or this:
https://groups.google.com/forum/#!topic/firebase-talk/eVvL2j4UWL4
Hope this helps.
Alice are you solve the problem ? i have too this issue
how do I PhotoURL to view photo. Can you give an example
html
current user PhotoURI: {{auth.currentUserPhotoURI}}
and
ts
get currentUserPhotoURI():string{
return this.authState?this.authState.auth.photoURL:”;
}
Thanks
html should be something like this:
![]()
Hey,
i tried your tutorial and it works great! Thanks for that.
But at the moment im struggeling at the point to
1. Check if the User is already Loggedin on the Homepage
2. Redirect him if he is already logged in or if he log himself in.
I tried with the currentUser function but it doesnt work.
Would be amazing if you could help me with that
Hi Steve,
There is an onAuth event on the AuthProvider. You can subscribe to it and see if the user is authenticated. Something like this:
auth.onAuth.subscribe((authState)=>{
if (authState){
console.log('Logged in user :', authState.auth.email);
}
});
In the app.component.ts file you can see it’s already implemented.
You only have to redirect to another page (set the rootPage to your homepage).
how do I make this in ionic 3 after they update angularfire2?
they way you did not works.
hello, can you please update the tutorial? how can I do that in ionic 3 after firebase update to latest angularfire?
I tried your way and it’s not working.
I’m getting the following error in response to the method: firebase.auth().signInWithCredential
Error: 400
POST https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyAssertion?key=AIzaSyDTzFkA0rhc8DH53I6iwVD_4ptAqYbPsTQ 400 ()
16:59:31.051 ion-dev.js?v=2.1.3:156 {“error”:{“errors”:[{“domain”:”global”,”reason”:”invalid”,”message”:”Unsuccessful debug_token response from Facebook: {\”error\”:{\”message\”:\”(#100) The App_id in the input_token did not match the Viewing App\”,\”type\”:\”OAuthException\”,\”code\”:100,\”fbtrace_id\”:\”BuFBiZERFu2\”}}”}],”code”:400,”message”:”Unsuccessful debug_token response from Facebook: {\”error\”:{\”message\”:\”(#100) The App_id in the input_token did not match the Viewing App\”,\”type\”:\”OAuthException\”,\”code\”:100,\”fbtrace_id\”:\”BuFBiZERFu2\”}}”}}
Are you able to manage this issue?? I am facing the same issue
Just tested it and it all works, are you sure you are using the correct Facebook App_Id and App_name?
In APP settings on Facebook in URL Site http://localhost/