impr3siones – #PR2 Inicio de sesión con Google
Ya tenemos la segunda PR de impr3siones en la que añadimos el inicio de sesión con cuenta de Google y dejamos configurada una función de Firebase que se ejecuta cuando un usuario crea su cuenta, es decir, hace el primer login.
Diseño del sistema de sesión
Para construir el login he implementado un patrón de observación. En nuestro caso cada componente del frontal que necesite saber si el usuario tiene la sesión iniciada, podrá subscribirse al Connector de manera que cuando haya un cambio en la sesión recibirá la notificación del cambio.
Este diseño nos permite que, independientemente de quién inicie o finalice la sesión, todos los componentes se actualicen a la vez. Aunque tiene un ligero problema, y es… ¿qué pasa cuando un componente se subscribe cuando ya hayamos iniciado sesión? En ese caso el componente no recibirá actualización de estado hasta que haya un cambio en la sesión. Tendremos que tenerlo en cuenta y, en caso de que sea necesario, cuando un componente se subscriba enviarle directamente una notificación con el estado actual.
Inicio de sesión con un proveedor de autenticación
El inicio de sesión con la cuenta de Google es algo que casi todos hemos hecho en Internet, si no ha sido con la cuenta de Google ha sido con la de Twitter, Facebook, Apple etc… Esta forma de iniciar sesión en una web con una cuenta de un tercero, el proveedor de autenticación, se realiza mediante mecanismos, como OAuth u OpenID, en los que el usuario no introduce sus credenciales en la web que quiere acceder, si no que para iniciar sesión es redirigido al proveedor de autenticación, se autentica, y es devuelto a la web inicial con un token que luego le permite a la web, comprobando con el servicio de autenticación, identificar al usuario
Detalle del proceso de login
Todo este proceso puede parecer un poco lioso, pero con un esquema se entiende mejor (o no 😅):
A continuación detallo los pasos a seguir para iniciar sesión, que fácil fácil no es
- El usuario accede a el servicio web, en nuestro caso es #impr3siones, y decide que quiere iniciar sesión.
- Es redirigido al proveedor de autenticación donde dice que quiere iniciar sesión para acceder a #impr3siones.
- El proveedor le da entonces un token de acceso, el cual tiene que entregárselo al servicio web.
- El usuario vuelve al servicio donde quiere iniciar sesión y entrega el token.
- El servicio va al proveedor de autenticación e intercambia ese token por la información del usuario, siempre que el token sea válido.
- Una vez comprobado que el token es válido, el proveedor de autenticación envía la información de inicio de sesión.
- El servicio da por buena la autenticación del usuario y le dice 👋.
Estos pasos estan resumidos y puede que el servicio web tenga que avisar al proveedor de autenticación antes de redirigir al usuario, o que haya mas comprobaciones entre medias, todo dependiendo de la implementación del protocolo de autenticación que emplee el proveedor de autenticación.
El login con Firebase
Una vez hemos visto todo ese lio de idas y venidas del usuario vemos que, cuando el usuario inicia sesión realmente está abandonando nuestra página web para luego volver, lo que hace que pierda el estado que tenía en nuestra web (a menos que lo conservemos), y que el patrón de observación encaje particularmente bien, puesto que el proceso de login con el sdk de Firebase es totalmente asíncrono.
Al ser un proceso asíncrono, el mecanismo que tenemos para saber cuando el usuario ha iniciado sesión es otra subscripción. Mediante esta subscripción el sdk nos informa cuando detecta un cambio de sesión, que puede ser cuando el usuario finaliza el proceso de inicio de sesión, cierra sesión o vuelve a la página con una sesión previa.
Nosotros en el fondo lo único que hacemos en propagar ese servicio de subscripción a partir del conector que tenemos con Firebase.
Alternativas y mejoras
Siempre hay otra manera de hacer las cosas, vamos a exponer algunas y también mejoras que podemos implementar en el futuro
Usar un contexto de react
Una opción, en vez de tener todos los componentes suscritos al connector, podría ser tener una única subscripción en un contexto, y que todos los componentes se encuentren dentro del mismo.
Esta alternativa es la que empleo en Manasav y tarjetadefelicion.es. No le veo problema pero en esta ocasión quería probar este otro enfoque, simplemente por probar cosas nuevas. Si vemos que no encaja bien siempre podemos crear el contexto y hacer la subscripción única.
Evitar el uso del conector directamente
Una buena idea será crear un hook, que se encargue de la subscripción.
Abstracción del conector en el frontal
En caso de que queramos un modo «demo», un nivel de abstracción en el frontal para poder interceptar al conector y falsear el inicio de sesión y evitar escrituras en la base de datos.
Próximos pasos
Aunque ya tenemos cuentas de usuario, está claro que habrá que añadir login con usuario y contraseña. Para ello necesitaremos enviar correos electrónicos y gestionar altas, bajas, verificaciones, cambios y olvidos de contraseña. De momento iremos tirando con las cuentas de Google.
El objetivo de la fase 1 del proyecto era la subida de archivos así que será por donde continuemos. Una vez tengamos el conector con la subida de archivos podremos empezar a pensar en el frontal, para ello habrá que darle una vuelta a los casos de uso para definir la interfaz y sobre todo las reglas de seguridad de la base de datos y de los archivos.
Cuando tengamos el frontal podemos añadir el proveedor de correos electrónicos ( y… ¿tal vez notificación por telegram 🤔? ) y la fase 1 estaría casi completa, pero no hay que olvidar el tema legal.
Los usuarios al iniciar sesión nos darán sus datos privados, y tendremos que redactar una política de privacidad y un términos y condiciones 🥱.