CIAM - Spinfood

 Descripción general

Nombre

@Doris Gopar

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.