En posts anteriores vimos cómo utilizar Firebase con Ionic para autenticar usuarios registrar y autenticar usuarios utilizando correo y contraseña; en esta ocasión vamos a ver cómo utilizar el proveedor de Facebook de Firebase para autenticar nuestros usuarios con su cuenta de Facebook.
Prerrequisitos
Por comodidad vamos a adicionar esta funcionalidad a la aplicación que ya empezamos a implementar en los posts anteriores por lo que les recomiendo que lean esos posts primeramente y luego regresen a este.
Aplicación de Facebook
Por supuesto, para poder permitir autenticacion con Facebook necesitamos tener creada una aplicacion de facebook, lo cual podemos hacer en el sitio de desarrolladores de Facebook. Hay muchos articulos sobre como hacerlo por lo que no vamos a entrar en detalles sobre esto, sólo mencionar que vamos a necesitar el App Id de la aplicacion que creemos.
Plugin de Cordova y wrapper de Facebook de Ionic Native
Necesitaremos este plugin y su wrapper de Ionic Native porque vamos a utilizar (de estar disponible) la integración nativa a través de la app de Facebook, de lo contrario vamos a utilizar el navegador para integrarnos.
Para instalarlos, nos colocamos en la carpeta de nuestro proyecto y ejecutamos el comando que veremos a continuación, pero antes, debemos obtener y reemplazar el valor de APP_ID con el “App Id” de nuestra app de Facebook y de igual manera con APP_NAME:
ionic cordova plugin add cordova-plugin-facebook4 --variable APP_ID="1911595049109511" --variable APP_NAME="IonFire"
Con el comando anterior instalamos el plugin de Cordova, antes de seguir quiero mostrar lo que sucedió en mi caso:

Noten como durante la instalación tuve que actualizar un plugin del CLI de Ionic e instalar uno nuevo, esto es debido a que el nuevo CLI de Ionic está organizado ahora por plugins, los cuales vamos a ir instalando a medida que los vayamos necesitando, por ejemplo los comandos relacionados con el CLI de Cordova (como ionic cordova plugin add) se encuentran en @ionic/cli-plugin-cordova por lo cual me ha pedido que lo instale.
Aún falta instalar el Wrapper de Ionic Native, el cual instalaremos ejecutando:
npm install --save @ionic-native/facebook
Finalmente necesitamos registrar el plugin en el módulo principal de nuestra aplicación que se encuentra en src/app/app.module.ts:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 { Facebook } from '@ionic-native/facebook'; | |
import { AngularFireModule } from 'angularfire2'; | |
import { AngularFireAuthModule } from 'angularfire2/auth'; | |
import { AuthService } from '../providers/auth-service'; | |
import { MyApp } from './app.component'; | |
import { HomePage } from '../pages/home/home'; | |
import { SignInPage } from '../pages/signin/signin'; | |
import { SignUpPage } from '../pages/signup/signup'; | |
export const firebaseConfig = { | |
apiKey: "AIzaSyA3jE_yGw17BSReFk_QMo7fuf4fSiKFW8k", | |
authDomain: "ionfire-df87b.firebaseapp.com", | |
databaseURL: "https://ionfire-df87b.firebaseio.com", | |
projectId: "ionfire-df87b", | |
storageBucket: "ionfire-df87b.appspot.com", | |
messagingSenderId: "783410523738" | |
}; | |
@NgModule({ | |
declarations: [ | |
MyApp, | |
HomePage, | |
SignInPage, | |
SignUpPage | |
], | |
imports: [ | |
BrowserModule, | |
IonicModule.forRoot(MyApp), | |
AngularFireModule.initializeApp(firebaseConfig), | |
AngularFireAuthModule | |
], | |
bootstrap: [IonicApp], | |
entryComponents: [ | |
MyApp, | |
HomePage, | |
SignInPage, | |
SignUpPage | |
], | |
providers: [ | |
StatusBar, | |
SplashScreen, | |
{ provide: ErrorHandler, useClass: IonicErrorHandler }, | |
AuthService, | |
] | |
}) | |
export class AppModule { } |
Primero lo importamos en la línea 6 y luego lo adicionamos a la lista de proveedores en la línea 52.
El botón
Pues es hora de adicionar el botón de entrar con Facebook, tanto en la pantalla de inicio de sesión como en la de registro respectivamente:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<ion-header> | |
<ion-navbar hideBackButton="true"> | |
<ion-title>Iniciar Sesión</ion-title> | |
</ion-navbar> | |
</ion-header> | |
<ion-content> | |
<form #signInForm="ngForm" (submit)="signIn()"> | |
<ion-list> | |
<ion-item> | |
<ion-label stacked>Correo electrónico</ion-label> | |
<ion-input [(ngModel)]="userModel.email" type="email" autocorrect="off" autocapitalize="none" name="email" pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,3}$" | |
required></ion-input> | |
</ion-item> | |
<ion-item> | |
<ion-label stacked>Contraseña</ion-label> | |
<ion-input [(ngModel)]="userModel.password" type="password" name="password" required minlength="6"></ion-input> | |
</ion-item> | |
<div padding-left padding-right padding-top> | |
<button ion-button [disabled]="!signInForm.form.valid" block>Entrar</button> | |
</div> | |
<div padding-left padding-right> | |
<p>¿No tiene Cuenta de Usuario? <a (click)="signUp()">Regístrese</a> | |
</div> | |
</ion-list> | |
</form> | |
<div padding> | |
<div padding-bottom>Entrar con una red social:</div> | |
<button ion-button block (click)="signInWithFacebook()" class="facebook-btn">Entrar con Facebook</button> | |
</div> | |
</ion-content> |
En la línea 31 podemos ver cómo adicionamos un div donde pusimos el botón, ya le colocamos que método queremos invocar cuando lo toquemos (el cual vamos a implementar luego) y le pusimos una clase CSS llamada facebook-btn la cual vamos a crear más adelante para darle un poco de estilo, ahora hacemos lo mismo en la página de registro:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<ion-header> | |
<ion-navbar> | |
<ion-title>Registrarse</ion-title> | |
</ion-navbar> | |
</ion-header> | |
<ion-content> | |
<form #signUpForm="ngForm" (submit)="signUp()"> | |
<ion-list> | |
<ion-item> | |
<ion-label stacked>Correo electrónico</ion-label> | |
<ion-input [(ngModel)]="userModel.email" type="email" autocorrect="off" autocapitalize="none" name="email" pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,3}$" | |
required></ion-input> | |
</ion-item> | |
<ion-item> | |
<ion-label stacked>Contraseña</ion-label> | |
<ion-input [(ngModel)]="userModel.password" type="password" name="password" required minlength="6"></ion-input> | |
</ion-item> | |
<div padding-left padding-right padding-top> | |
<button ion-button [disabled]="!signUpForm.form.valid" block>Registrarse</button> | |
</div> | |
</ion-list> | |
</form> | |
<div padding> | |
<div padding-bottom>Entrar con una red social:</div> | |
<button ion-button block (click)="signInWithFacebook()" class="facebook-btn">Entrar con Facebook</button> | |
</div> | |
</ion-content> |
No hay mucho que comentar sobre el código anterior…
Vamos a adicionar la clase CSS al archivo src/theme/variables.scss para poder utilizarla en varias pantallas:
.facebook-btn { text-transform: none !important; background-color: #4267b2 !important; }
Ya tenemos todos los cambios visuales que necesitamos, si ejectuamos ionic serve podemos ver el botón en ambas pantallas, pero si lo tocamos veremos que produce un error porque no hemos implementado el método signInWithFacebook().
Servicio de autenticación
Ya nos toca refactorizar un poco el servicio de autenticación que creamos en posts anteriores el cual se encuenta en el archivo src/providers/auth-service.ts, por lo que vamos a cambiarlo por el siguiente código:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Injectable } from '@angular/core'; | |
import { AngularFireAuth } from 'angularfire2/auth'; | |
import * as firebase from 'firebase/app'; | |
import { UserModel } from '../models/user-model'; | |
@Injectable() | |
export class AuthService { | |
user: firebase.User; | |
constructor(public angularFireAuth: AngularFireAuth) { | |
angularFireAuth.authState.subscribe((user: firebase.User) => { | |
this.user = user; | |
}); | |
} | |
get authenticated(): boolean { | |
return this.user != null; | |
} | |
signInWithEmailAndPassword(userModel: UserModel): firebase.Promise<any> { | |
return this.angularFireAuth.auth.signInWithEmailAndPassword(userModel.email, userModel.password); | |
} | |
createUserWithEmailAndPassword(userModel: UserModel): firebase.Promise<any> { | |
return this.angularFireAuth.auth.createUserWithEmailAndPassword(userModel.email, userModel.password); | |
} | |
signInWithFacebook(accessToken: string): firebase.Promise<any> { | |
const facebookCredential = firebase.auth.FacebookAuthProvider.credential(accessToken); | |
return this.angularFireAuth.auth.signInWithCredential(facebookCredential); | |
} | |
signInWithPopup(): firebase.Promise<any> { | |
return this.angularFireAuth.auth.signInWithPopup(new firebase.auth.FacebookAuthProvider()); | |
} | |
signOut(): firebase.Promise<any> { | |
return this.angularFireAuth.auth.signOut(); | |
} | |
} |
Veamos qué modificaciones hicimos:
- En la línea 4 cambiamos cómo importamos el contenido del módulo firebase/app pues ahora vamos a empezar a necesitar más clases de dicho módulo.
- Debido a que cambiamos cómo importamos el contenido del módulo firebase/app debemos arreglar algunas referencias que perdimos pues ahora necesitamos especificar que, por ejemplo, las clases User y Promise que estabamos utilizando son del módulo firebase, por lo que a través del código ahora veremos cómo utilizamos firebase.User y firebase.Promise.
- En la línea 30 vemos la implementación del método que nos va a permitir entrar con Facebook dado un token de autenticación, con dicho token creamos una credencial de tipo FacebookAuthProvider de Firebase la cual luego utilizamos en el método signInWithCredential() de la propiedad auth (instancia de la clase Auth de Firebase) perteneciente a angularFireAuth (servicio de AngularFire que inyectamos en posts anteriores). Necesitamos este método porque con el uso del plugin de Cordova para Facebook vamos a poder obtener el token de autenticación, ya que el mismo nos permite autenticar al usuario, luego necesitamos este método para poder “crear/autenticar” el usuario en nuestra aplicación de Firebase.
- También implementamos el método signInWithPopup(), el cual vamos a utilizar cuando el teléfono no tenga instalada la aplicación nativa de Facebook o si decidimos usar este código como parte de nuestro sitio web, en resumen lo que hace es que utiliza el método de igual nombre de la propiedad auth el cual recibe una instancia “vacía” de FacebookAuthProvider, el API del Firebase se encarga de autenticar al usuario en Facebook, llenar la instancia de FacebookAuthProvider y “crear/autenticar” el usuario en Firebase.
Implementación de la funcionalidad de los botones
De regreso a las pantallas de inicio de sesión y registro para poder implementar el método signInWithFacebook() que dejamos pendiente, modificamos src/pages/signin/signin.ts de la siguiente manera:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Component } from '@angular/core'; | |
import { NavController, LoadingController, AlertController, Platform } from 'ionic-angular'; | |
import { Facebook } from '@ionic-native/facebook'; | |
import { AuthService } from '../../providers/auth-service'; | |
import { UserModel } from '../../models/user-model'; | |
import { SignUpPage } from '../signup/signup'; | |
import { HomePage } from '../home/home'; | |
@Component({ | |
selector: 'page-signin', | |
templateUrl: 'signin.html' | |
}) | |
export class SignInPage { | |
userModel: UserModel; | |
constructor( | |
public navCtrl: NavController, | |
public loadingCtrl: LoadingController, | |
public alertCtrl: AlertController, | |
public authService: AuthService, | |
public platform: Platform, | |
public facebook: Facebook) { | |
this.userModel = new UserModel(); | |
} | |
signIn() { | |
let loading = this.loadingCtrl.create({ | |
content: 'Iniciando sesión. Por favor, espere…' | |
}); | |
loading.present(); | |
this.authService.signInWithEmailAndPassword(this.userModel).then(result => { | |
loading.dismiss(); | |
this.navCtrl.setRoot(HomePage); | |
}).catch(error => { | |
loading.dismiss(); | |
console.log(error); | |
this.alert('Error', 'Ha ocurrido un error inesperado. Por favor intente nuevamente.'); | |
}); | |
} | |
signInWithFacebook() { | |
if (this.platform.is('cordova')) { | |
return this.facebook.login(['email']).then(result => { | |
this.authService.signInWithFacebook(result.authResponse.accessToken).then(result => { | |
this.navCtrl.setRoot(HomePage); | |
}); | |
}); | |
} else { | |
return this.authService.signInWithPopup().then(result => { | |
this.navCtrl.setRoot(HomePage); | |
}); | |
} | |
} | |
signUp() { | |
this.navCtrl.push(SignUpPage); | |
} | |
alert(title: string, message: string) { | |
let alert = this.alertCtrl.create({ | |
title: title, | |
subTitle: message, | |
buttons: ['OK'] | |
}); | |
alert.present(); | |
} | |
} |
- En la línea 2 vemos cómo importamos el servicio Platform, con el cual vamos a poder determinar sobre qué entorno se está ejecutando la aplicación.
- Importamos el wrapper de Ionic Native para el plugin de Facebook, como mismo hicimos en el módulo de la aplicación.
- En las líneas 24 y 25 (en el constructor) inyectamos los servicios que acabamos de importar.
- Finalmente en la línea 47, iniciamos la implementación del método signInWithFacebook(), en resumen, lo que hacemos es verificar utilizando el servicio Platform si la aplicación está ejecutandose nativamente (‘cordova’), de ser así utilizamos el plugin de Cordova para Facebook para autenticar el usuario y obtener el token y luego utilizamos el método signInWithFacebook() del servicio de autenticación authService, el cual recibe el token de autenticación de Facebook para “crear/autenticar” el usuario en Firebase. De no estar ejecutándose la aplicación en un entorno nativo utilizamos el método signInWithPopup() el cual ya explicamos anteriormente.
Les dejo de tarea hacer lo mismo en la pantalla de registro, pues es exactamente lo mismo.
Podemos ver que hay un poco de duplicación de código, lo cual vamos a aprender a resolver en un próximo post.
Ya casi estamos listos, sólo faltan algunos pasos que tienen que ver con algunas configuraciones que debemos hacer en Firebase y Facebook.
Firebase
En Firebase tenemos que activar el proveedor de autenticación de Facebook, es muy parecido a lo que hicimos cuando activamos el de “Email/Password” solo que esta vez seleccionamos el de Facebook.
Entramos a la consola de Firebase y seleccionamos el proyecto que creamos para esta aplicación, en mi caso “IonFire”, luego vamos a seleccionar el menú Authentication que se encuentra en el panel de navegación de la izquieda, seleccionamos el tab “SIGN-IN METHOD”, nos colocamos encima de la fila del proveedor de Facebook y veremos cómo al final de la fila aparece un ícono de un lápiz, al hacerle click, veremos la siguiente ventana:

Como vemos tenemos que activarlo donde dice “Enable” y colocar el “App ID” y el “App Secret” de la aplicación de Facebook que hayamos creado. En la configuración de la aplicación de Facebook tenemos que adicionar las plataformas en las que deseemos publicar nuestra aplicación: Web, Android, iOS, etc. En el caso de la Web debemos colocar la URL que nos muestra en la imagen anterior como “Site URL”:

Hay muchas guías sobre cómo configurar una aplicación en Facebook, si tienen algún problema me dejan saber en los comentarios e intentaré ayudarles.
Y eso es todo ya podemos ejecutar nuesta aplicacion y empezar a registrar usuarios con Facebook en Firebase. Espero que les sirva de ayuda.
Si te gustó el post ayuda a compartirlo en tus redes sociales 🙂
[…] futuros posts veremos cómo utilizar otros métodos de autenticación de Firebase (como Facebook) y otras funcionalidades de Firebase (como la base de […]