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 Google authentication to the Ionic app.
Start by getting the package name (or widget id) from your config.xml file (in the root of your application).
Open your firebase console at https://console.firebase.google.com and go to your project overview.
First we will do the iOS version.
Select iOS configuration.
Add your package name you got from the config.xml above and add the app.
The GoogleService-info.plist file will be downloaded, and you should get the REVERSE_CLIENTID from the file.
Skip the rest of the configuration steps by closing the wizard.
Now you can install the plugin by using the iOS REVERSE_CLIENTID.
ionic plugin add cordova-plugin-googleplus --save --variable REVERSED_CLIENT_ID=com.googleusercontent.apps.*********************
Next is the Android version.
First of all you need to get an SHA-1 fingerprint.
There’s is very good guide by Google : https://developers.google.com/android/guides/client-auth.
Next go to your Firebase console, project overview and add the Android configuration.
First add a new application.
Select Android.
Add the package name from the config.xml and the SHA-fingerprint you generated before.
You can now close the wizard.
The file google-services.json will be downloaded, copy it to your project, you will need some data from it in a later stage and get webclient_id for auth-provider.ts
If you didn’t install the iOS version above, install the plugin now. (You can get the REVERSED_CLIENT_ID from the google developer console at https://console.developers.google.com/apis/credentials, select your project and get the OAuth 2.0-client-ID for Android. something like ***************.apps.googleusercontent.com
ionic plugin add cordova-plugin-googleplus --save --variable REVERSED_CLIENT_ID=***************.apps.googleusercontent.com
Now we need to update the Ionic application to use the installed plugin.
Let’s add a Google 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)="loginWithGoogle()" ion-button block>Google login</button> </ion-row> </ion-content>
And add the loginWithGoogle 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' //Added reset password page @Component({ selector: 'page-home', templateUrl: 'home.html' }) export class HomePage { loginForm: FormGroup; email: AbstractControl; password: AbstractControl; error: any; signupPage = SignupPage; resetPasswordPage = ResetPasswordPage //Added reset password page 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']; } loginWithGoogle(): void{ this.auth.loginWithGoogle().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 => { 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 { GooglePlus } from 'ionic-native'; import { auth } from 'firebase'; //needed for the GoogleAuthProvider @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 platform this.firebase = firebase; this.af.auth.subscribe((state: FirebaseAuthState) => { this.authState = state; this.onAuth.emit(state); }); } loginWithGoogle() { return Observable.create(observer => { if (this.platform.is('cordova')) { return GooglePlus.login({ 'webClientId':'******************.apps.googleusercontent.com' //your Android reverse client id }).then(userData => { var token = userData.idToken; const googleCredential = auth.GoogleAuthProvider.credential(token, null); this.firebase.auth().signInWithCredential(googleCredential).then((success)=>{ observer.next(success); }).catch(error => { //console.log(error); observer.error(error); }); }).catch(error => { //console.log(error); observer.error(error); }); } else { return this.af.auth.login({ provider: AuthProviders.Google, 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:''; } }
IMPORTANT:The webclient id on line 27 should be replaced by the client_id from the google-services.json you downloaded previously.
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 Google login or a pop-up.
The Google import is used for calling the native Google plugin.
The auth import from Firebase is needed since AngularFire2 doesn’t have support for the GoogleProvider (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 Google 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 Google and enable it.
Let’s test it again in your browser.
$ionic serve
When you click the Google login button you should see a popup where you can connect with your Google 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 Google functionality is working. Connect you Android phone and run the following commands.
$ionic platform add android $ionic run android
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 🙂
That’s all folks.
The next post will be about getting data from and to Firebase…
9 comments. Leave new
getting error in this line Cresential marked as an error
const googleCredential = auth.GoogleAuthProvider.credential(token, null);
If you can sent me some extra information, I can have a look at it.
Hi Chris,
Thanks for the post. I’m getting ‘12501’ error on android device when I replace webClientId on line 27 with ‘client_id’ of ‘client_type’:1 from google-services.json but if I switch to ‘client_id’ for ‘web’ (client_type: 3) then it works on both browser and android device.
Hello,
I get the following error:
[ts]
Type ‘EventEmitter’ is not assignable to type ‘EventEmitter’.
Type ‘{}’ is not assignable to type ‘FirebaseAuthState’.
Property ‘uid’ is missing in type ‘{}’.
On “public onAuth: EventEmitter = new EventEmitter();”
What is wrong?
Have solved this by writing this instead: public onAuth: EventEmitter = new EventEmitter();
Hello Chris,
Thanks for taking the time to post this. However, when building the project for Android I keep getting the error:
Error: cmd: Command failed with exit code 1 Error output:
C:\Users\User\Documents\MyApp\platforms\android\src\nl\xservices\plugins\GooglePlus.java:346: error: cannot find symbol
cordova.getActivity(), acct.getAccount(), true
What is wrong? Have followed the tutorial.
thank you for that great tutorial .
1.in web when i sign in with google i get undefined in success response.
2.i have problem when i try to see in emulator android i see black screen.
3.when i try to see the app in view ionic app , when i click google login so nothing happen .
please help me , waiting for answer .
Thank you !
i get error “plugin_not_installed” when i click google login in on ionic view app on android
Thanks for the tutorial Chris!
On web, everything is working just fine. Unfortunately, when running on an Android device, I keep receiving error 10. After debugging and checking certificates, I’m kinda stuck. Any suggestions/experiences with this issues?