La compañía ya cuenta con un servicio OAuth 2.0, por lo que se implementa el flujo Authorization Code Flow with PKCE (Proof Key for Code Exchange), recomendado para aplicaciones móviles y SPA por su mayor seguridad.
Es un flujo estándar para la seguridad de aplicaciones modernas. PKCE protege contra la intercepción del código de autorización, garantizando que solo tu aplicación pueda obtener los tokens. La combinación de tokens de acceso y de refresco proporciona una sesión segura y duradera, mientras que la capa biométrica final ofrece una experiencia de usuario fluida y conveniente para inicios de sesión posteriores.
sequenceDiagram
participant App as App Móvil / SPA
participant OAuth as OAuth Server
Existente
Note over App: 1. Generar code_verifier random
Note over App: code_challenge = SHA256(code_verifier)
App->>OAuth: 2. Solicitud de autorización
+ code_challenge
+ code_challenge_method = S256
Note over OAuth: 3. Usuario ingresa credenciales
user + password
Note over OAuth: 4. [OPCIONAL] Factor adicional
OTP/SMS
OAuth-->>App: 5. Authorization Code
válido 60 segundos
App->>OAuth: 6. Intercambio código por tokens
+ code_verifier para validar
Note over OAuth: Valida:
SHA256(code_verifier) == code_challenge
OAuth-->>App: 7. Access Token JWT 15 min
+ Refresh Token 30 días
+ ID Token info usuario
Note over App: 8. [OPCIONAL] Solicitud de biometría
Face ID / Touch ID
App->>App: 9. Validación biométrica local
Device Secure Enclave
Note over App: 10. Token biométrico adicional
almacenado localmente
| Componente | Descripción | Duración |
|---|---|---|
| code_verifier | Cadena aleatoria de 43-128 caracteres | Un solo uso |
| code_challenge | SHA256(code_verifier) en base64url | Un solo uso |
| authorization_code | Código temporal para intercambiar por tokens | 60 segundos |
| access_token | JWT firmado con claims del usuario | 15 minutos |
| refresh_token | Token opaco para renovar access_token | 30 días |
| id_token | JWT con información del usuario (OpenID) | 15 minutos |
Durante el proceso de registro (onboarding), el sistema captura y valida la identidad del usuario mediante reconocimiento facial con liveness detection.
sequenceDiagram
participant U as Usuario
App Móvil
participant AUTH as MS-Autenticación
participant SMS as SMS/Email
Gateway
participant KYC as MS-KYC
participant OCR as OCR Engine
Tesseract.js
participant BIO as MS-Biometría
participant REKN as AWS Rekognition
Azure Face API
participant VAULT as HashiCorp Vault
Note over U,VAULT: PASO 1: Registro Inicial
U->>AUTH: GraphQL Mutation: registerUser
{nombre, email, teléfono, fecha, password}
AUTH->>AUTH: Valida unicidad email/teléfono
AUTH->>AUTH: Hash contraseña (bcrypt, salt: 12)
AUTH->>AUTH: Crea usuario
status: PENDING_VERIFICATION
AUTH->>AUTH: Genera OTP 6 dígitos
válido 10 min
AUTH->>SMS: Envía OTP por SMS/Email
AUTH-->>U: 200 OK - Solicita OTP
U->>U: Usuario ingresa OTP
U->>AUTH: POST /api/auth/verify-otp
{sessionId, otp}
AUTH->>AUTH: Valida OTP (máximo 3 intentos)
alt OTP Válido
AUTH->>AUTH: Status: PENDING_IDENTITY
AUTH-->>U: ✓ OTP Correcto - Siguiente paso
else OTP Inválido
AUTH-->>U: ✗ OTP Incorrecto - Reintentar
U->>AUTH: Reintenta OTP
end
Note over U,VAULT: PASO 2: Verificación de Identidad (KYC)
U->>U: Captura foto documento
frente y reverso
U->>KYC: POST /api/documents/upload
{images}
KYC->>OCR: Procesa en Worker Thread
OCR->>OCR: OCR extrae datos
Nombre, Número ID, Fecha nacimiento
OCR->>KYC: Datos extraídos
KYC->>KYC: Valida autenticidad
Marcas de agua, Hologramas
KYC->>KYC: Compara datos con registro
Similarity > 90%
KYC->>KYC: Valida watchlist
AML/CFT OFAC ONU
alt Validación OK
KYC->>AUTH: Status: PENDING_BIOMETRIC
KYC-->>U: ✓ Documentos verificados
else Validación Fallida
KYC-->>U: ✗ Documentos rechazados
Registro cancelado
end
Note over U,VAULT: PASO 3: Registro Biométrico
U->>U: Graba video selfie 3-5 seg
Mueve cabeza, parpadea
U->>BIO: POST /api/biometric/register-face
{video}
BIO->>BIO: Procesa en Worker Thread
BIO->>BIO: Liveness Detection
Movimiento, Parpadeo, Textura
BIO->>REKN: Extrae vectores faciales
embeddings
REKN-->>BIO: Face embeddings + confidence
BIO->>BIO: Compara rostro vs documento
Similarity > 95%
BIO->>VAULT: Almacena embeddings cifrados
AES-256
VAULT-->>BIO: ✓ Almacenado
alt Biometría Válida
BIO->>AUTH: Status: ACTIVE
BIO-->>U: ✓ Registro biométrico exitoso
else Biometría Fallida (intento 1-2)
BIO-->>U: ✗ Intento fallido
Reintentar (máx 3)
U->>BIO: Nuevo intento
else Biometría Fallida (intento 3)
BIO-->>U: ✗ Registro rechazado
Máximo de intentos alcanzado
end
Note over U,VAULT: PASO 4: Activación de Cuenta
AUTH->>SMS: Notificación cuenta activada
SMS-->>U: SMS/Email: "Cuenta activada"
AUTH-->>U: Biometría habilitada
Face ID / Touch ID
U->>U: Usuario puede hacer login
Note over U: ✓ Onboarding Completo
Usuario: ACTIVE
Una vez completado el onboarding, el usuario puede autenticarse mediante múltiples métodos, ordenados por nivel de seguridad:
| Método | Tecnología | Seguridad | UX | Tiempo |
|---|---|---|---|---|
| Face ID / Face Recognition | Biometría facial + Liveness | Muy Alta | Excelente | ~2 segundos |
| Touch ID / Fingerprint | Sensor biométrico dispositivo | Muy Alta | Excelente | ~1 segundo |
| Usuario + Contraseña + OTP | TOTP (Google Authenticator) | Alta | Buena | ~15 segundos |
| Usuario + Contraseña | Bcrypt hash + Salt | Media | Estándar | ~10 segundos |
| PIN de 6 dígitos | Cifrado local | Media | Rápida | ~3 segundos |
sequenceDiagram
participant U as Usuario
participant APP as App Móvil
participant OS as Sistema Operativo
iOS/Android
participant SE as Secure Enclave
Face ID/Touch ID/Fingerprint
participant KS as Keychain iOS
Keystore Android
participant AUTH as MS-Autenticación
participant VAULT as HashiCorp Vault
Note over U,VAULT: Flujo de Login Biométrico (< 3 segundos)
U->>APP: Abre aplicación bancaria
APP->>OS: Detecta soporte de biometría
OS-->>APP: ✓ Biometría disponible
APP->>OS: Solicita autenticación biométrica
OS->>U: Muestra prompt
Face ID / Touch ID / Fingerprint
alt iOS
U->>SE: Face ID / Touch ID
SE->>SE: Valida en Secure Enclave
else Android
U->>SE: BiometricPrompt API
SE->>SE: Valida en hardware
end
alt Biometría Exitosa
SE-->>OS: ✓ Autenticación exitosa
OS-->>APP: ✓ Biometría válida
APP->>KS: Recupera token biométrico local
KS-->>APP: Token cifrado
APP->>AUTH: POST /api/auth/biometric-login
{biometricToken, deviceId}
AUTH->>AUTH: Valida token biométrico
AUTH->>VAULT: Solicita embeddings del usuario
VAULT-->>AUTH: Embeddings cifrados (AES-256)
AUTH->>AUTH: Compara embeddings
Similarity > 95%
AUTH->>AUTH: Genera JWT tokens
AUTH-->>APP: 200 OK
{accessToken (15min), refreshToken (30d)}
APP->>APP: Almacena tokens en Keychain/Keystore
APP-->>U: ✓ Login exitoso
Redirige a dashboard
Note over U: Total: ~2 segundos
else Biometría Fallida
SE-->>OS: ✗ Autenticación fallida
OS-->>APP: ✗ Biometría inválida
APP-->>U: ✗ Autenticación rechazada
Intenta con contraseña
Note over U: Fallback a login tradicional
end
flowchart TD
%% Contenedor principal del clúster
subgraph "🔒 HASHICORP VAULT CLUSTER"
%% Nodos de Vault
subgraph " "
direction LR
v1["fa:fa-server Vault 1
(Active)"]:::activeNode
v2["fa:fa-server Vault 2
(Standby)"]:::standbyNode
v3["fa:fa-server Vault 3
(Standby)"]:::standbyNode
end
%% Backend de almacenamiento
storage["fa:fa-database Storage Backend
(Consul/etcd)"]:::storageStyle
%% --- Conexiones Internas ---
%% Comunicación para Alta Disponibilidad (HA)
v1 <--> v2
v2 <--> v3
%% Conexión de todos los nodos al storage
v1 & v2 & v3 ==> storage
end
%% --- Consumidores Externos ---
subgraph " "
direction LR
k8s["fa:fa-dharmachakra Kubernetes
(Secrets Injection)"]:::consumerStyle
apps["fa:fa-mobile-alt Apps
(API Keys)"]:::consumerStyle
cicd["fa:fa-cogs CI/CD
(Deploy Secrets)"]:::consumerStyle
end
%% --- Flujo de Secretos (Externo) ---
%% El nodo ACTIVO es el que sirve los secretos
v1 -- "🔑 Serves Secrets" --> k8s
v1 -- "🔑 Serves Secrets" --> apps
v1 -- "🔑 Serves Secrets" --> cicd
%% --- ESTILOS ---
%% Estilos para Nodos
classDef activeNode fill:#E8F8F5,stroke:#1ABC9C,stroke-width:3px,color:#212529,rx:10,ry:10
classDef standbyNode fill:#F4F6F7,stroke:#909497,stroke-width:2px,color:#343A40,rx:10,ry:10
classDef storageStyle fill:#FEF9E7,stroke:#F39C12,stroke-width:2px,color:#212529,rx:10,ry:10
classDef consumerStyle fill:#EBF5FB,stroke:#3498DB,stroke-width:2px,color:#212529,rx:10,ry:10
%% Estilos para el Contenedor del Clúster
classDef mainCluster fill:#F8F9FA,stroke:#495057,stroke-width:2px,stroke-dasharray: 5 5,rx:15,ry:15
class mainCluster subgraphStyle
%% Estilos para las Líneas/Conexiones
%% Enlaces de HA (punteados y delgados)
linkStyle 0,1 stroke:#909497,stroke-width:2px,stroke-dasharray: 3 3
%% Enlace principal de entrega de secretos (grueso y de color)
linkStyle 5,6,7 stroke:#1ABC9C,stroke-width:3px
| Evento | Umbral | Acción |
|---|---|---|
| Login fallido | 3 intentos en 5 minutos | Activar CAPTCHA |
| Login fallido | 5 intentos en 15 minutos | Bloqueo temporal (30 min) |
| Login fallido | 10 intentos en 1 hora | Bloqueo cuenta (requiere reset) |
| Requests de login | >10 req/min desde misma IP | Rate limiting + CAPTCHA |
| Solicitudes OTP | >3 en 10 minutos | Bloqueo temporal |
| Plataforma | Tecnología | API | Storage |
|---|---|---|---|
| iOS | Face ID / Touch ID | LocalAuthentication framework | Secure Enclave (hardware) |
| Android | Face Recognition / Fingerprint | BiometricPrompt API | Android Keystore (hardware-backed) |
| Proveedor | Servicio | Capacidad | Costo |
|---|---|---|---|
| AWS Rekognition | Face Comparison + Liveness | Similarity score, detección de vida | $1.00 por 1,000 imágenes |
| Azure Face API | Face Verification + Liveness | Similarity score, anti-spoofing | $1.00 por 1,000 transacciones |
| Google Cloud Vision | Face Detection | Detección facial, landmarks | $1.50 por 1,000 imágenes |
¿Qué es Liveness Detection? Técnica para detectar si la persona frente a la cámara es real (no una foto, video o máscara).
Técnicas Implementadas:
{
// Registered claims (RFC 7519)
"iss": "https://auth.bp-bank.com", // Issuer
"sub": "user-uuid-12345", // Subject (user ID)
"aud": "bp-banking-app", // Audience
"exp": 1696684800, // Expiration (15 min)
"iat": 1696683900, // Issued at
"jti": "jwt-uuid-67890", // JWT ID (para revocación)
// Custom claims
"email": "usuario@example.com",
"name": "Juan Pérez",
"roles": ["customer"],
"permissions": [
"accounts:read",
"transactions:read",
"transfers:create"
],
"mfa_verified": true,
"biometric_enabled": true,
"account_ids": ["acc-111", "acc-222"],
// Security
"ip": "192.168.1.100",
"device_id": "device-uuid-999"
}
ISO 27001 - Control A.9 (Access Control):
PCI DSS Requirement 8:
GDPR Art. 32 - Security Measures:
GLBA - Safeguards Rule: