🔥 FIREBASE AUTHENTICATION, VINCULA Cuentas de Facebook, Google, etc
Vincular cuentas con Firebase Authentication nos permite que un user pueda acceder a nuestra app desde distintos proveedores como Email y Password, Facebook, Twitter, Google, etc. Nuestro Login es más flexible permitiendo a un user que escoja qué proveedor quiere utilizar.
Tabla de contenido
Hoy lo que vamos a ver en SwiftBeta es a como vincular diferentes proveedores de autenticación. ¿Esto qué significa? imagina que te registras en Firebase con el proveedor de Email y Password, si te deslogueas y quieres usar otro proveedor como Facebook o Twitter y estás usando el mismo email, la autenticación con Firebase fallará. Aparecerá un mensaje como el siguiente:
An account already exists with the same email address but different sign-in credentials. Sign in using a provider associated with this email address.
Para poder vincular varias cuentas y que un user comparta la misma sesión con diferentes proveedores (entendiendo proveedor como Facebook, Twitter, Google, Github, etc), primero tendremos que autenticarnos con el proveedor con el que nos hayamos registrado, y segundo dentro de la app tendremos que vincular la cuenta con el nuevo proveedor. Esto es muy útil para que un user pueda acceder de varias formas a nuestra app y se comparta la sesión.
¿Qué pasos seguiremos?
- Estar logueados con nuestro primer proveedor, por ejemplo, Email y Password
- Autenticarnos con otro proveedor
- Vincular los credenciales
Para poder autenticarnos con otro proveedor mientras estamos logueados con Email y Password, crearemos un TabView y en una de las opciones del TabView añadiré un Form con la opción de poder vincular una cuenta de Facebook. También aparecerá poder vincular con Email y Password. Pero nos vamos a centrar en el caso de que nos hemos registrado con Email y Password y queremos vincular nuestra cuenta de Facebook (cuando tengamos esta parte haremos el caso contrario, nos registraremos con Facebook y luego vincularemos nuestro Email y Password).
Para hacer esta parte, registrate dentro de la app con un email que también estés usando en Facebook. Así podrás comprobar que la vinculación de cuentas funciona.
Es decir, deberías tener un user al menos registrado usando el proveedor de Email y Password.
Creamos la vista en SwiftUI
Lo primero de todo que vamos hacer es crear una nueva vista, la vamos a llamar ProfileView. Y va a ser un simple Form con dos Buttons en SwiftUI:
Ahora vamos a usar nuestra nueva vista ProfileView en HomeView, para hacerlo vamos a crear un TabView como mencionábamos hace un momento:
Una vez tenemos una idea visual de lo que queremos hacer, vamos a seguir el mismo proceso de los otros posts. Vamos a empezar por las capas inferiores de nuestra arquitectura y luego iremos subiendo hasta la vista.
Pues lo primero que vamos hacer es saber qué Proveedor estamos usando actualmente, así desde nuestra vista marcaremos esa opción como deshabilitada (ya que no queremos vincular el mismo Proveedor con la que tenemos activa la sesión, no tendría sentido).
Creamos un modelo nuevo llamado LinkedAccounts
Vamos al listado de ficheros y nos situamos en el mismo nivel que tenemos AuthenticationFirebaseDatasource, allí vamos a crear una carpeta que vamos a llamar Model y vamos a meter un nuevo modelo llamado LinkedAccounts:
También vamos a mover el modelo User que tenemos en el AuthenticationFirebaseDatasource, vamos a crear en un fichero a parte dentro de la nueva carpeta Model.
CurrentProvider
Ahora vamos a nuestro AuthenticationFirebaseDatasource y vamos a crear un nuevo método, lo llamaremos currentProvider() y nos dará un array con todos los proveedores que tengamos vinculados con nuestra cuenta de email. En nuestro caso, ahora debería retornar solo un proveedor que sería el de Email y Password (si tuvieramos más proveedores asociados a ese email también los retornaría):
Vamos a crear un método en el Repository:
Y finalmente llegamos a nuestro AuthenticationViewModel. Aquí crearemos una propiedad y 3 métodos:
- El primer método llamará al método del repositorio
- El segundo método es un helper que nos indicará si tenemos como Proveedor Email y Password
- El tercer método es un helper que nos indicará si tenemos como Proveedor a Facebook
Ahora podemos llamar estos nuevos métodos del AuthenticationViewModel en nuestra vista ProfileView.
Vamos a añadir:
- El modificador .task y dentro de él vamos a pedir los Proveedores
- El modificador .disabled en cada Button, y cada Button llamará al método helper que hemos creado hace un momento. Así, si tenemos un proveedor deshabilitaremos la opción de vincularlo.
Si compilamos nuestra app y vamos a la sección de Profile, deberíamos ver algo parecido a esto. En mi caso estoy registrado y logueado usando el Proveedor de Email y Password.
Vincular Facebook con una cuenta existente a Firebase con el mismo Email
Lo que vamos hacer a continuación es que cuando el user pulse el button de Vincula Facebook, se ejecute toda la lógica necesaria para crear este vínculo con Firebase.
Pues vamos a crear esta nueva lógica creando un método en nuestro AuthenticationFirebaseDatasource
Ahora vamos a crear un método nuevo en nuestro AuthenticationRepository que llame a este nuevo que acabamos de crear:
y vamos hacer lo mismo en el AuthenticationViewModel:
Este closure solo está printando un mensaje por consola, lo que vamos hacer es crear algunas propiedades en nuestro AuthenticationViewModel y así mostrar un alert en nuestra vista ProfileView. Este alert se mostrará para indicar al user si se ha podido vincular la cuenta con el nuevo proveedor o no. Así que el método de linkFacebook() quedaría de la siguiente manera:
Creamos 2 propiedades nuevas:
y llamamos al método getCurrentProvider() para que obtenga otra vez el listado de Proveedores actualizado, y así marcar como disabled el último proveedor añadido, que en este caso será Facebook.
Ahora nos vamos a la vista ProfileView para:
- Añadir la lógica de que cuando se pulse el Button de vincular Facebook llame al método correcto del AuthenticationViewModel.
- Añadir un alert que se mostrará cuando el User quiera vincular un Proveedor nuevo. Este alert mostrará un mensaje tanto si hay éxito como si hay un error.
ProfileView quedaría de la siguiente manera:
Vamos a compilar nuestra app y vamos a probar de vincular nuestra cuenta de Facebook, cuando pulsamos el Button de vincular una cuenta con Facebook aparece el mismo proceso que si hicieramos la autenticación:
Al aparecer la vista anterior le damos a continuar y añadimos nuestros credenciales. Si todo ha ido bien verems el siguiente mensaje:
Ha aparecido el Alert y se ha deshabilitado el Button de Facebook ya que hemos vinculado este nuevo Proveedor.
Si ahora vamos a Firebase podemos ver que aparece el icono de Facebook al lado de nuestro email.
Vincular Email y Password con una cuenta existente a Firebase con el mismo Email (En este caso será Facebook)q
Para hacerlo, borra el user que tienes vinculado con los dos proveedores y vuelvete a registrar usando solo Facebook. Y te debería de quedar un user como en la siguiente imagen:
En este momento tu único Proveedor es Facebook y si haces logout e intentas registrarte con tu Email y Password te dará un error.
The email address is already in use by another account.
Antes debes vincular los dos Proveedores. Para hacerlo vamos a empezar por crear un método en la clase FacebookAutentication, el método se va a llamar getAccessToken y nos va a servir para crear un credencial de Facebook en el AuthenticationFirebaseDatasource:
Una vez creado este método en la clase FacebookAuthentication, nos vamos al AuthenticationFirebaseDatasource, aquí vamos a crear un método para que nos cree un AuthCredential, necesitaremos un credencial de Facebook para reautenticarnos con Facebook antes de crear el vinculo entre otros proveedores, en nuestro caso con Email y Password. Crearemos el siguiente método:
Y a continuación crearemos el siguiente método para crear esta reautenticación con Facebook, crear un credencial de Email y Password válido y vincularlo con el current user, vamos a verlo paso a paso:
- Si te fijas el método recibe dos parámetros, que son el email y password que se recibirán desde las capas superiores (View-> ViewModel-> Repository-> Datasource).
- Obtenemos un credencial de algunos de los proveedor que el user esté usando. En nuestro caso será Facebook (es el único proveedor con el que hemos registrado al user)
- Reautenticamos la sesión del user, este paso es por seguridad.
- Una vez autenticado, vinculamos el credencial de email y password con Firebase.
Una vez hemos creado este método vamos a crear el método en el AuthenticationRepository:
y finalmente creamos el método en nuestro AuthenticationViewModel:
Este método que acabamos de crear en el ViewModel, necesitamos llamarlo desde la vista de ProfileView. Pero en esa vista no tenemos ningún Form para poderle pasar un email o password. Es por eso que añadiremos esta opción a nuestro Formulario actual. Vamos a crear una propiedad @State para poder expanding un formulario al pulsar en Vincular con Email
Y la vista final quedaría de la siguiente manera:
Si compilamos nuestra app deberíamos ver la opción de Vincula Facebook deshabilitada y solo estar disponible la opción de Vincula Email.
Si pulsamos en Vincula Email debería aparecer un formulario:
Aquí podemos añadir nuestras credenciales, añadiremos nuestro Email y Password. Al rellenar la información le damos al Button y si todo va bien debería salir el Alert y al dar Aceptar debería aparecer la opción de Vincula Email deshabilitada.
Si vamos a nuestro panel de Firebase, podemos ver que aparecen los dos proveedores.
Conclusión
Hoy hemos aprendido a como vincular distintos proveedores de autenticación de Firebase. De esta manera permitimos que un user pueda entrar con el sistema de autenticación que quiera (y que nuestra app soporte). Hemos visto a como vincular una cuenta con Facebook y más tarde hemos aprendido a vincular una cuenta con Email y Password.