CIAM - Spinfood
Descripción general
Nombre | @Doris Gopar |
---|---|
Estado | ACTIVO |
Versión | 1.0 |
Propietario | @Doris Gopar |
Objetivo | El objetivo de este espacio es para documentar la integraciones de CIAM, que a fecha de hoy pertenecen al proyecto Spin+ y que la app B2C, B2B y Repartidores de Spinfood tendrá que integrar para que sus usuarios puedan autenticarse en el panorama Femsa y panorama Spinfood. |
Customer Identity and Access Management (CIAM), es un servicio que integra todo lo relacionado a la verificación de identidad, la autenticación y la autorización de usuarios, así como la centralización y el manejo de datos de usuario compartido por múltiples servicios.
Dentro de D@F, utilizaremos el CIAM para administrar el acceso a los usuarios así como la identificación de los mismos por parte de los servicios de las diferentes unidades de Negocio.
Como parte del proceso de validación de identidad, el CIAM incorpora procesos de KYC y AML o Anti lavado de dinero. Es responsabilidad del CIAM contener y dar soporte para que el usuario pueda realizar todas las verificaciones de identidad, así
como consultar servicios centralizados de información que nos provean de información de usuarios que estén en blacklist por temas de fraude o lavado de activos.
El CIAM se divide en 5 componentes principales
Autenticación (Onboarding y Login): Es el encargado de dar soporte al frontend para que el usuario pueda realizar todos los flujos de usuario tales como onboarding o singup, login, cambio de contraseña, Logout.
Autorización: Se encarga de validar si el usuario tiene una sesión activa y válida y que la misma tiene los permisos suficientes para acceder al recurso que solicitó.
Provee de la información de usuario necesaria para que el servicio pueda identificar al usuario que hace la petición de forma segura.
OTP: Un servicio de envío de Password de Uso único (One Time Password) a distintos medios. Normalmente son utilizados para validar que el usuario esta en
posesión del teléfono o email que dice tener, pero pueden ser utilizados como un segundo factor de autenticación 2FA.
KYC & AML: Permite al usuario realizar procesos avanzados de KYC para verificar la identidad del mismo y cotejar la información con registros de usuarios
identificados como fraude o sospechosos de lavado de activos.
User Management: Centraliza toda la información compartida del usuario que no sea propia de un servicio. permite obtener y actualizar estos datos, así como obtener registros de solo lectura del Data Lake u Otros servicios.
Diagrama Completo (Big Picture)
En el siguiente diagrama se puede observar conceptualmente los servicios ofrecidos por el CIAM, así como la interacción con otros servicios dentro del ecosistema Digital FEMSA. Con fondo amarillo se resalta todos los bloques que corresponden al CIAM
logrando en conjunto todo el soporte para Autenticación, Autorización, OTP, KYC/AML y user Management.
Resaltado en lineas punteadas, se encuentra el concepto de Caja Negra para el bloque de Autorización, en el que trabajando en conjunto SDK de Frontend con el Stack de
Seguridad del Backend, proveen de una solución transparente para la Autorización de request y acceso a los distintos servicios protegidos por Access Token.
Flujos de Autorización
Los flujos de Autorización validan la autenticidad del usuario y el nivel de acceso para
acceder a los endpoints de los servicios protegidos. utilizando un como
JWT Token
Access Token , verificamos que el mismo haya sido emitido por Auth0, y que no este
expirado. Mediante la utilización de un es posible renegociar un
Refresh token
Access
una vez el mismo haya expirado, este proceso sucede de forma automática sin necesidad de intervención por parte del usuario.
Token
En Combinación con un SDK Para el cliente, creamos un concepto de Caja negra, donde tanto los casos de autorización exitosa, como los denegados, se resuelven
integramente en comunicación con el Core del Frontend y los request son bloqueados para prevenir el acceso al servicio. Mediante este stack tecnológico las distintas unidades de negocio puede desarrollar sus aplicaciones y tener una comunicación transparente con el backend, asumiendo que las queries que lleguen al servidor esta validadas.
En los siguientes diagramas podemos observar los 2 extremos, identificados como
Client y Service, como el módulo cliente que viva dentro de la SuperApp y el servicio de Backend correspondiente a ese módulo o cualquier servicio protegido que el módulo desee acceder. Lo que queda en el centro, SDK, Imperva, Apigee, Nethone y
Notification Service, son parte del stack de autorización provisto por el CIAM, y conforman el concepto de Caja negra que asegura que el cliente esta autorizado y tiene los permisos necesarios para acceder al servicio requerido.
Happy Path
En el Happy Path, el usuario esta autenticado (Ha iniciado sesión) y posee un Access Token con el nivel de acceso necesario para acceder al servicio. Ninguna regla de seguridad detecta actividad sospechosa y la comunicación fluye sin errores de punta a punta.
El módulo cliente se comunica con el servicio con normalidad y no percibe ningún impacto en la comunicación.
sequenceDiagram
participant client as Client participant sdk as SDK participant imperva as Imperva participant apigee as ApiGee participant nethone as Nethone
participant notification as Notification Service participant service as Service
client->>sdk: GET /dummy sdk->>imperva: Proxy /dummy
imperva->>apigee: Proxy /dummy apigee-->>apigee: Check JWT
apigee->>nethone: GET /check nethone-->>apigee: 200
apigee->>service: Proxy /dummy service-->>client: 200
Network Attack
A pesar de que es poco probable que un Network Attack se produzca desde un cliente consumiendo el SDK, se gráfica que en caso Imperva detecte actividad sospechosa responderá con un error del tipo 4XX para indicar que no se puede acceder al servicio y el SDK indicará al Core que cierre la sesión del usuario y lo lleve a la pantalla de Login.
En este caso, el módulo cliente verá la comunicación y el flujo interrumpido y el core actuará para cerrar la sesión de usuario.
sequenceDiagram
participant client as Client participant sdk as SDK participant imperva as Imperva participant apigee as ApiGee participant nethone as Nethone
participant notification as Notification Service participant service as Service
client->>sdk: GET /dummy sdk->>imperva: Proxy /dummy imperva-->>sdk: 4XX
sdk-->>client: Denied - Back to Login
Token Inválido
Un Access Token inválido es aquel en que el Hash del payload no coincide con el calculado al recibir el request. Esto se puede deber a un error en ;a comunicación del Header, o un intento de ataque modificando el payload del JWT Token. En caso se
detecte un Access Token inválido, se procederá al cierre de sesión del usuario, informar al usuario de la detección de una actividad sospechosa e informar al Core que se cierre la sesión y se envíe al usuario a la pantalla de Login.
En este caso, el módulo cliente verá la comunicación y el flujo interrumpido y el core actuará para cerrar la sesión de usuario.
sequenceDiagram
participant client as Client participant sdk as SDK participant imperva as Imperva participant apigee as ApiGee participant nethone as Nethone
participant notification as Notification Service participant service as Service
client->>sdk: GET /dummy sdk->>imperva: Proxy /dummy
imperva-->>apigee: Proxy /dummy apigee-->>apigee: Check JWT apigee-->>sdk: 4XX Invalid Token
apigee-)notification: Send Notification to user sdk-->>client: Denied - Back to Login
Token Expirado
Este flujo sucederá con regularidad, y a pesar de rechazar la petición de forma inicial es considerado dentro de los flujos correctos. La idea es que de la mano del SDK, se evite tener que llegar a este flujo la mayoría de las veces al refrescar el token con anticipación a un query, pero llegado el caso se llegue a este punto, se podrá manejar de todas formas.
Por temas de seguridad, y dado que un Access Token es irrevocable, se establecerá un lifetime acotado para el Access Token, en caso el Access Token expire, se puede solicitar uno nuevo mediante el Refresh Token, que si puede ser revocado y tiene una duración mayor.
En caso detectemos que el token esta expirado, se le dará aviso al SDK, para que este negocie de forma automático un nuevo Access Token mediante la utilización del
Refresh Token, y una vez obtenido el nuevo Access Token, el SDK le dará aviso al
Core para que este decida si reintenta la comunicación o se deja esta responsabilidad al modulo cliente.
La renegociación del token se hace contra el servicio de autenticación del CIAM, y su funcionamiento se explicará luego.
sequenceDiagram
participant client as Client participant sdk as SDK participant imperva as Imperva
participant apigee as ApiGee participant nethone as Nethone
participant notification as Notification Service participant service as Service
client->>sdk: GET /dummy sdk->>imperva: Proxy /dummy
imperva-->>apigee: Proxy /dummy apigee-->>apigee: Check JWT apigee-->>sdk: 4XX Expired Token
sdk->>sdk: New Access & Refresh Token from CIAM sdk-->>service: Happy Path
Token Expirado & Refresh Token Expirado
Al contrario del caso anterior, este flujo no debería darse con frecuencia, y solo luego de un período prolongado de inactividad puede suceder. De igual forma vamos a establecer mecanismos en el SDK para evitar este tipo de llamados, pero en caso suceda la operatoria es similar al caso anterior hasta obtener la respuesta de que el Token esta expirado.
En este caso sin embargo, al intentar obtener un nuevo Access Token utilizando el servicio de autenticación del CIAM, este nos informará que el refresh token ya no es válido ya que el mismo expiró, y con esta respuesta, el SDK procederá a informar al Core del cierre de sesión para llevar al usuario a la página de Login.
sequenceDiagram
participant client as Client participant sdk as SDK participant imperva as Imperva participant apigee as ApiGee participant nethone as Nethone
participant notification as Notification Service participant service as Service
client->>sdk: GET /dummy sdk->>imperva: Proxy /dummy
imperva-->>apigee: Proxy /dummy apigee-->>apigee: Check JWT apigee-->>sdk: 4XX Expired Token
sdk->>sdk: New Access & Refresh Token from CIAM - Denied sdk-->>client: Denied - Back to Login
Token con Nivel de Seguridad Inferior
El refresh token permite al usuario obtener Access Token de forma automática y sin
intervención del mismo, lo que prolonga el tiempo de sesión abierta de forma indefinida mientras la aplicación este en uso. Por este motivo es imperativo establecer niveles de seguridad de los Access Token para bloquear ciertas acciones con un Access Token que se obtuvo de forma automática, entendiendo que el Mobil puede estar en posesión de otra persona.
Actividades como cambio de contraseña, realizar pagos o agregar tarjetas de crédito, van a requerir un nivel de seguridad mayor, el mismo puede ser provisto mediante ciertas challenges que el usuario deberá realizar para probar la identidad, tales como FaceID, FingerprintID o reingresar la contraseña. Este proceso le otorgará de forma temporal un Access Token de nivel de seguridad mayor que autorizará al usuario a realizar esa actividad.
El stack de autorización conocerá de antemano el nivel de seguridad requerido por el servicio. En caso un token de seguridad de nivel inferior llegue a un servicio que requiere uno de nivel mayor, el SDK recibirá una respuesta indicando que se debe solicitar una verificación para la obtención de un token de seguridad de nivel mayor para realizar la acción necesaria.
Esto se le informará al Core, el cual puede actuar en consecuencia solicitando un Challenge para obtener este token.
sequenceDiagram
participant client as Client participant sdk as SDK participant imperva as Imperva participant apigee as ApiGee participant nethone as Nethone
participant notification as Notification Service participant service as Service
client->>sdk: GET /dummy sdk->>imperva: Proxy /dummy
imperva-->>apigee: Proxy /dummy apigee-->>apigee: Check JWT apigee-->>sdk: 4XX Low level token sdk-->>client: Request Challenge
Nethone
Para detectar intentos de fraude, utilizaremos una herramienta que hace uso de Machine Learning para analizar el tráfico histórico de la cuenta e identificar si el request actual parece provenir del usuario real o de un usuario que intenta hacer fraude. Todo request será analizado por Nethone, y en caso detecte que la comunicación es válida, se habilitará la misma hacia el servidor.
En caso haya una actividad sospechosa, Nethone nos responderá con distintos grados de sospecha, en los que dividimos en,
Warning: No estamos seguros si el usuario es real, por lo que se le puede solicitar un Challenge para verificarlo
Deny: Detectó actividad sospechosa, y decidimos cerrar la sesión del usuario
Banned: Se supone que al usuario le han robado la cuenta, se cierra la cuenta de forma temporal y se informa al usuario al respecto. Deberá reactivarla desde el call center.
Warning
sequenceDiagram
participant client as Client participant sdk as SDK participant imperva as Imperva participant apigee as ApiGee participant nethone as Nethone
participant notification as Notification Service participant service as Service
client->>sdk: GET /dummy sdk->>imperva: Proxy /dummy
imperva-->>apigee: Proxy /dummy apigee-->>apigee: Check JWT apigee-->>nethone: GET /check nethone-->>apigee: 4XX - Warning apigee-->>sdk: 4XX - Warning sdk-->>client: Request Challenge
Denied
sequenceDiagram
participant client as Client participant sdk as SDK participant imperva as Imperva
participant apigee as ApiGee participant nethone as Nethone
participant notification as Notification Service participant service as Service
client->>sdk: GET /dummy sdk->>imperva: Proxy /dummy
imperva-->>apigee: Proxy /dummy apigee-->>apigee: Check JWT apigee-->>nethone: GET /check nethone-->>apigee: 4XX - Denied
apigee-)notification: Send Notification to user apigee-->>sdk: 4XX - Denied
sdk-->>client: Back to Login
Banned
sequenceDiagram
participant client as Client participant sdk as SDK participant imperva as Imperva participant apigee as ApiGee participant nethone as Nethone
participant notification as Notification Service participant service as Service
client->>sdk: GET /dummy sdk->>imperva: Proxy /dummy
imperva-->>apigee: Proxy /dummy apigee-->>apigee: Check JWT apigee-->>nethone: GET /check nethone-->>apigee: 4XX - Banned
apigee-)notification: Send Notification to user apigee-->>sdk: 4XX - Banned
sdk-->>client: Back to Login w/message
Flujos de Autenticación (Onboarding/Login)
El servicio de Autenticación (Onboarding and Login) del CIAM es el encargado de
interactuar con el frontend para permitir las actividades de usuarios relacionadas a la autenticación del mismo en el sistema.
SignUp (Onboarding) LogIn
LogOut
Cambio de Contraseña
Cambio de Teléfono/Email Token Refresh
Onboarding
Durante el flujo de Onboarding, nuevos usuarios o usuarios pre-acreditados se dan de alta en el sistema y crean todas las cuentas para operar con los servicios relacionados. El flujo de Onboarding se encarga de confirmar el numero telefónico, así como tambienr recaudar la información personal mínima necesario y la contraseña para la creación de la cuenta.
Como parte del flujo de Onboarding, se recopilan preferencias de usuario que serán útiles para la personalización de la experiencia.
El flujo de Onboarding hace uso del Servicio de OTP para la verificación del número telefónico y va a solicitar un token OTP para proceder.
sequenceDiagram
participant client as Client participant sdk as SDK participant ciam as CIAM participant otp as OTP participant nethone as Nethone participant auth0 as Auth0 participant db as User Mgmt
client->>sdk: Authentication.otp(phone, message) sdk->>otp: POST /otp {phone, message}
otp->>otp: Send SMS to User otp-->>sdk: 200
sdk->>client: OK
client->>sdk: Authentication.verifyOtp(phone, code) sdk->>otp: POST /otp/code {phone, code}
otp-->>sdk: 200 - OTPToken sdk->>client: OK
client->>sdk: Authentication.signup(user, pass, ...) sdk->>ciam: POST /signup {user, pass, ...} [OTPToken] ciam->>auth0: POST /signup {id, secret, user, pass, ...} auth0-->>sdk: 200 {accessToken, refreshToken}
ciam->>db: Store user data
sdk->>sdk: store {accessToken, refreshToken} sdk-->>client: OK
Login
El flujo de Login permite a un usuario iniciar sesión en su cuenta para acceder a los servicios. Se solicita como parte del servicio de Login el chequeo de que la cuenta exista previo a la solicitud de la contraseña, para esto se agrega un endpoint de verificación de cuenta, que estará protegido por Nethone u OTP antes de brindar dicha información para evitar el mal uso del endpoint.
Un usuario reingresando desde su dispositivo, no requerirá ningún challenge para hacer Login, en caso el usuario ingrese de un nuevo dispositivo, se le pedirá que reconfirme su número mediante el envío de OTP, para luego continuar a la pantalla de contraseña, o de Onboarding dependiendo el caso.
sequenceDiagram
participant client as Client participant sdk as SDK participant ciam as CIAM participant otp as OTP participant nethone as Nethone participant auth0 as Auth0 participant db as User Mgmt
client->>sdk: Authentication.checkUser(user, message) sdk->>ciam: GET /user/{userId} {message}
ciam->>nethone: GET /check nethone-->>ciam: 4XX
ciam->>otp: POST /otp (user, message) otp->>otp: Send OTP Message to User otp-->>sdk: 200 - Need OTP
sdk-->>client: OK Need OTP
client->>sdk: Authentication.verifyOtp(user, otp) sdk->>otp: POST /otp/code {phone, code}
otp-->>sdk: 200 - OTPToken (With user Data) sdk->>client: OK
client->>sdk: Authentication.login(user, pass) sdk->>ciam: POST /login {user, pass}
ciam->>auth0: POST /oauth/token [Resource Owner] {id, secret, user, pass} auth0-->>sdk: 200 {accessToken, refreshToken}
sdk->>sdk: store {accessToken, refreshToken} sdk-->>client: OK
Token Refresh
Para mantener abierta la sesión por tiempo “indeterminado” es necesario refrescar el Access Token y el Refresh Token con cierta periodicidad. Un usuario que reingrese y
haga uso de la aplicación en períodos menores a la vida del Refresh Token percibirá un tiempo de sesión infinito. Por el contrario, un usuario que no ingrese a la app luego de cierto tiempo, tendrá que realizar un Login nuevamente para reactivar su sesión.
El proceso de refresh token funciona de forma automática entre el SDK y el CIAM, y entrega cada vez un nuevo Access Token y un nuevo Refresh Token, invalidando por seguridad todos los refresh token previos.
sequenceDiagram
participant client as Client participant sdk as SDK participant ciam as CIAM participant otp as OTP participant nethone as Nethone participant auth0 as Auth0 participant db as User Mgmt
sdk->>ciam: POST /refresh {accessToken, refreshToken}
ciam->>auth0: Proxy /oauth/token [Refresh Token] {id, accessToken, refreshToken} auth0-->sdk: 200 {accessToken, refreshToken}
sdk->>sdk: store {accessToken, refreshToken}
Cambio de Contraseña
Si un usuario olvida su contraseña, se le va a ofrecer la posibilidad de cambiarla por una nueva. El flujo de cambio de contraseña se encarga de habilitar esta funcionalidad.
Para autorizar un cambio de contraseña, se deberá validar por medio de OTP, el medio de comunicación para realizar este cambio, habilitando luego de este paso el cambio de la contraseña.
Es importante mencionar que el sistema no almacena contraseñas como tal, sino un Hash de la misma, por lo que no es posible informarle al usuario de su contraseña.
El endpoint de cambio de contraseña solicitara un token OTP para habilitar el cambio.
sequenceDiagram
participant client as Client participant sdk as SDK
participant ciam as CIAM participant otp as OTP participant nethone as Nethone participant auth0 as Auth0 participant db as User Mgmt
client->>sdk: Authentication.otp(user, message) sdk->>otp: POST /otp {user, message}
otp->>otp: Send Message to User otp-->>sdk: 200
sdk->>client: OK
client->>sdk: Authentication.verifyOtp(phone, code) sdk->>otp: POST /otp/code {phone, code}
otp-->>sdk: 200 - OTPToken (With user Data) sdk->>client: OK
client->>sdk: Authentication.recover(user, pass,) sdk->>ciam: POST /recover {user, pass} [OTPToken]
ciam->>auth0: POST /recover {id, secret, user, pass, ...} auth0-->>sdk: 200
sdk-->>client: OK
OTP
One Time Password es un servicio de envío de contraseña de un único uso a un dispositivo por medio de un medio de comunicación como ser SMS, WhatsApp, EMail. El objetivo proncipal es validar que el usuario esta en poseciópn y tiene acceso a ese medio de comunicación. Algunos de los usos principales son,
Válidación de propiedad de email
Validación de propiedad de número telefónico Autenticación en 2 pasos o 2FA
Durante el flujo de Onboarding vamos a validar el número de teléfono del usuario, para lo que se hará uso del OTP como herramienta para dicho proceso. Dado que este proceso es genérico y no de uso exclusivo al CIAM, decidimos crearlo de forma genérica para que el mismo servicio pueda ser utilizado ya sea en modo B2C o B2B por otros servicios.
La validación por OTP consta de 2 pasos, que se ejecutan en secuencia
Envío del OTP
Se debe enviar un mensaje al canal seleccionado con el código generado. Este código es aleatorio y se puede utilizar solo dentro de un período de tiempo, pasado este tiempo el código se invalida.
Confirmación del Código recibido
Una vez ingresado el código recibido, se debe validar que es el correcto, este proceso compara el código informado con el que se generó y verifica que sea el que se envió previamente.
Para evitar intentos de fuerza bruta, se dispondrá de una cantidad máxima de reintentos para ingresar el código correcto. En caso se agote, se deberá solicitar uno nuevo, para lo que hay que dejar pasar un lapso de tiempo mínimo, y se limitará la cantidad de reenvíos diarios.
Token de OTP
En el caso que la verificación sea en formato B2C, se le enviará al frontend un token OTP, del tipo JWT, que pruebe que el canal fue confirmado por el cliente. Este token serea verificado, en caso sea incluido en el request, por el stack de autorización del
CIAM, y entregado al servicio de backend. El servicio de backend, puede luego confiar en la verificación sin necesidad de consultar al servicio de OTP internamente.
Roadmap
Estamos terminando las etapas de definición de los distintos servicios en paralelo a cerrar las pruebas de concepto y avanzar a toda velocidad hacia la etapa final. Para mediados de Febrero estimamos disponer de una versión inicial del CIAM que funcione tanto para la capa de autorización como para los flujos definidos por el Frontend.
Hacia finales de Febrero estaremos terminando las implementaciones de KYC/AML. Para finales de Marzo, Ya deberemos disponer del servicio completo de User Management, junto con la integración y migración de datos de usuarios actuales, así como la conexión a las otras verticales para el procesos de sincronización de altas de usuario.
Durante Abril, estaremos corriendo pruebas y ajustes finales para llegar con un sistema estable al MVP.