Pantalla: Biometria
Identificador: SCR-AUTH-006
Modulo: MTS-AUTH-001 - Autenticacion y Seguridad
Version: 1.0.0
Fecha: 2025-12-05
Autor: MobileUxUiDrone (Eight of Eight)
Estado: Especificado
| Atributo |
Valor |
| Nombre |
Biometria |
| Proposito |
Desbloqueo local de app con FaceID/TouchID/Fingerprint |
| Tipo |
Full Screen (prompt nativo + fallback) |
| Acceso |
Automatico al abrir app con sesion valida |
| Prioridad |
Alta |
NOTA: La biometria es solo para desbloqueo LOCAL de la app, NO para autenticacion en Firebase.
2. Wireframe ASCII
2.1. Estado: Prompt Biometrico (Nativo)
2.1.1. iOS Face ID
+------------------------------------------+
| |
| |
| +----------+ |
| | MEDTIME | |
| +----------+ |
| |
| |
| +--------------------------------------+ |
| | | |
| | +--------------------------------+ | |
| | | [Face ID Icon] | | |
| | | | | |
| | | Face ID para MedTime | | | <- Prompt nativo iOS
| | | | | |
| | | [Cancelar] | | |
| | +--------------------------------+ | |
| | | |
| +--------------------------------------+ |
| |
+------------------------------------------+
2.1.2. Android Fingerprint
+------------------------------------------+
| |
| +----------+ |
| | MEDTIME | |
| +----------+ |
| |
| |
| +--------------------------------------+ |
| | | |
| | +--------------------------------+ | |
| | | [Fingerprint Icon] | | |
| | | | | |
| | | Toca el sensor de huellas | | | <- Bottom sheet Android
| | | para desbloquear | | |
| | | | | |
| | | [Usar PIN] [Cancelar] | | |
| | +--------------------------------+ | |
| | | |
| +--------------------------------------+ |
| |
+------------------------------------------+
2.2. Estado: Fallback a PIN
+------------------------------------------+
| |
| +----------+ |
| | MEDTIME | |
| +----------+ |
| |
| Ingresa tu PIN |
| |
| Biometria no disponible. Usa tu PIN |
| para desbloquear. |
| |
| +----+ +----+ +----+ +----+ |
| | | | | | | | | |
| | * | | * | | | | | | <- 4-6 digitos segun config
| | | | | | | | | |
| +----+ +----+ +----+ +----+ |
| |
| |
| +------------------------------------+ |
| | 1 | 2 | 3 | | |
| +---+---+---+ | |
| | 4 | 5 | 6 | | |
| +---+---+---+ | |
| | 7 | 8 | 9 | | |
| +---+---+---+ | |
| | | 0 | X | | |
| +---+---+---+ | |
| |
| [Olvidaste tu PIN?] |
| |
+------------------------------------------+
2.3. Estado: Biometria Fallida
+------------------------------------------+
| |
| +----------+ |
| | MEDTIME | |
| +----------+ |
| |
| |
| +--------------------------------------+ |
| | | |
| | +--------------------------------+ | |
| | | [Face ID Icon - Red] | | |
| | | | | |
| | | No reconocido | | |
| | | Intenta de nuevo | | |
| | | | | |
| | | Intentos: 2 de 3 | | |
| | | | | |
| | | [Usar PIN] [Intentar de nuevo]| | |
| | +--------------------------------+ | |
| | | |
| +--------------------------------------+ |
| |
+------------------------------------------+
2.4. Estado: PIN Bloqueado
+------------------------------------------+
| |
| +----------+ |
| | [!] | |
| | Warning | |
| +----------+ |
| |
| PIN bloqueado |
| |
| Has excedido el numero de intentos |
| de PIN. Espera antes de reintentar. |
| |
| +------------------------------------+ |
| | 04:32 | | <- Countdown
| +------------------------------------+ |
| |
| |
| O inicia sesion nuevamente con |
| Google o Apple. |
| |
| +------------------------------------+ |
| | Iniciar sesion nuevamente | |
| +------------------------------------+ |
| |
+------------------------------------------+
2.5. Estado: Exito
+------------------------------------------+
| |
| |
| |
| +----------+ |
| | | |
| | [Check] | |
| | Verde | |
| | | |
| +----------+ |
| |
| Desbloqueado |
| |
| |
| |
+------------------------------------------+
(Auto-transicion a Dashboard en 0.5s)
3. Componentes UI
3.1. Logo MedTime
| Propiedad |
Valor |
| Tamano |
60x60dp |
| Posicion |
Center, 15% from top |
| Proposito |
Branding durante unlock |
3.2. Prompt Biometrico (Nativo)
3.2.1. iOS
| Propiedad |
Valor |
| API |
LAContext.evaluatePolicy |
| Reason |
"Face ID para MedTime" / "Touch ID para MedTime" |
| Fallback title |
"Usar PIN" |
3.2.2. Android
| Propiedad |
Valor |
| API |
BiometricPrompt |
| Title |
"Desbloquear MedTime" |
| Subtitle |
"Usa tu huella o rostro" |
| Negative button |
"Usar PIN" |
| Propiedad |
Valor |
| Componente |
CMP-INP-003 (PIN Input) |
| Variante |
Segun config usuario (4 o 6 digitos) |
| Cell size |
44x52dp |
| Mascara |
Punto negro (no muestra digitos) |
| Auto-submit |
Si, al completar |
3.4. Teclado Numerico
| Propiedad |
Valor |
| Layout |
Grid 3x4 |
| Key size |
72x56dp |
| Key font |
xl (20sp) |
| Delete key |
Backspace icon |
| Haptic |
Si, cada tecla |
3.5. Countdown Timer
| Propiedad |
Valor |
| Formato |
MM:SS |
| Tipografia |
3xl (30sp), bold |
| Color |
neutral.900 |
3.6. Link Olvidaste PIN
| Propiedad |
Valor |
| Texto |
"Olvidaste tu PIN?" |
| Tipografia |
sm (14sp), primary |
| Touch target |
44dp height |
| Accion |
Ir a SCR-AUTH-004 |
3.7. Success Animation
| Propiedad |
Valor |
| Icono |
Checkmark circle |
| Tamano |
64x64dp |
| Color |
success |
| Animacion |
Scale 0.8->1.0, fade in |
| Duracion |
200ms |
| Haptic |
Success pattern |
4. Comportamientos
4.1. Flujo de Biometria
flowchart TD
A[App Open] --> B{Sesion valida?}
B -->|No| C[Ir a Login]
B -->|Si| D{Biometria habilitada?}
D -->|No| E[Ir a PIN]
D -->|Si| F[Mostrar prompt biometrico]
F --> G{Resultado?}
G -->|Exito| H[Desbloquear -> Dashboard]
G -->|Fallo| I{Intentos < 3?}
G -->|Cancelar| E
I -->|Si| F
I -->|No| E
E --> J[Ingreso PIN]
J --> K{PIN correcto?}
K -->|Si| H
K -->|No| L{Intentos < 5?}
L -->|Si| J
L -->|No| M[Bloqueo temporal]
M --> N{Cooldown completo?}
N -->|Si| J
N -->|No| O[Mostrar countdown]
O --> N
4.2. Gestos
| Gesto |
Elemento |
Accion |
| Biometric |
Sensor |
Desbloquear |
| Tap |
Key 0-9 |
Ingresar digito PIN |
| Tap |
Key X |
Borrar ultimo digito |
| Long press |
Key X |
Borrar todo |
| Tap |
Olvidaste PIN? |
Ir a recovery |
| Tap |
Usar PIN (bio prompt) |
Cambiar a PIN |
| Tap |
Iniciar sesion (bloqueado) |
Ir a login |
4.3. Auto-trigger Biometria
COMPORTAMIENTO:
1. App abre con sesion valida
2. Si biometria habilitada, trigger automatico
3. Prompt nativo aparece inmediatamente
4. Si usuario cancela o falla 3 veces, fallback a PIN
5. Si PIN falla 5 veces, bloqueo temporal
CONFIGURACION:
- biometricEnabled: true/false (UserDefaults/SharedPrefs)
- pinLength: 4 o 6 (configurado en onboarding)
5. Estados y Transiciones
5.1. Diagrama de Estados
stateDiagram-v2
[*] --> CheckingSession: App open
CheckingSession --> BiometricPrompt: Sesion valida + bio habilitado
CheckingSession --> PINInput: Sesion valida + bio deshabilitado
CheckingSession --> Login: Sesion invalida
BiometricPrompt --> BiometricSuccess: Bio exitoso
BiometricPrompt --> BiometricFail: Bio fallido
BiometricPrompt --> PINInput: Cancelar / Usar PIN
BiometricFail --> BiometricPrompt: Intentos < 3
BiometricFail --> PINInput: Intentos >= 3
PINInput --> PINValidating: PIN completo
PINValidating --> Success: PIN correcto
PINValidating --> PINError: PIN incorrecto
PINError --> PINInput: Intentos < 5
PINError --> PINBlocked: Intentos >= 5
PINBlocked --> PINInput: Cooldown completo
PINBlocked --> Login: Tap "Iniciar sesion"
BiometricSuccess --> Success
Success --> [*]: Nav a Dashboard
Login --> [*]: Nav a SCR-AUTH-002
5.2. Transiciones
| De |
A |
Trigger |
Animacion |
| CheckingSession |
BiometricPrompt |
Auto |
Fade in prompt |
| BiometricPrompt |
Success |
Bio OK |
Checkmark + haptic |
| BiometricPrompt |
PINInput |
Tap Usar PIN |
Fade transition |
| PINInput |
Success |
PIN OK |
Checkmark + haptic |
| PINInput |
PINError |
PIN malo |
Shake |
| Success |
Dashboard |
0.5s delay |
Fade out |
6. Bloqueo Progresivo
6.1. Reglas de Intentos
6.1.1. Biometria
| Intentos fallidos |
Accion |
| 1-2 |
Permitir reintento |
| 3 |
Fallback a PIN |
6.1.2. PIN
| Intentos fallidos |
Accion |
| 1-4 |
Mostrar intentos restantes |
| 5 |
Bloqueo 1 minuto |
| 6 |
Bloqueo 5 minutos |
| 7 |
Bloqueo 15 minutos |
| 8+ |
Bloqueo 1 hora |
6.2. Persistencia de Bloqueo
ALMACENAMIENTO:
- pinBlockedUntil: timestamp en SharedPrefs/UserDefaults
- Sobrevive app kill
- Se verifica al iniciar pantalla PIN
COMPORTAMIENTO:
- Si blocked, mostrar countdown
- Refresh cada segundo
- Al completar, habilitar inputs
7. Accesibilidad
7.1. Labels y Hints
| Elemento |
accessibilityLabel |
accessibilityHint |
| Bio prompt (iOS) |
"Face ID para MedTime" |
- |
| Bio prompt (Android) |
"Usa tu huella para desbloquear" |
- |
| PIN input |
"PIN de desbloqueo, {n} de {total} digitos" |
"Ingresa tu PIN" |
| Key 0-9 |
"{numero}" |
- |
| Key delete |
"Borrar" |
"Borra el ultimo digito" |
| Usar PIN |
"Usar PIN" |
"Desbloquea con tu PIN en lugar de biometria" |
| Olvidaste PIN |
"Olvidaste tu PIN" |
"Ir a opciones de recuperacion" |
| Timer |
"Bloqueado. Espera {tiempo}" |
- |
7.2. Orden de Foco
7.2.1. Con biometria
- Bio prompt (sistema)
- Boton Usar PIN (si visible)
7.2.2. Con PIN
- Titulo
- PIN input (anuncia estado)
- Teclado numerico
- Link Olvidaste PIN
7.3. Screen Reader Announcements
| Evento |
Anuncio |
Prioridad |
| Bio prompt |
"Usa Face ID para desbloquear MedTime" |
Alta |
| Bio fail |
"No reconocido. {n} intentos restantes" |
Alta |
| Bio to PIN |
"Usa tu PIN para desbloquear" |
Alta |
| PIN digit |
"Digito {n} de {total}" |
Media |
| PIN error |
"PIN incorrecto. {n} intentos restantes" |
Alta |
| PIN blocked |
"PIN bloqueado. Espera {tiempo}" |
Alta |
| Success |
"Desbloqueado" |
Alta |
7.4. Contraste y Tamanos
| Elemento |
Min Size |
Contraste |
| PIN cells |
44x52dp |
4.5:1 |
| Keyboard keys |
72x56dp |
4.5:1 |
| Titulo |
20sp |
4.5:1 |
| Timer |
30sp |
4.5:1 |
| Links |
14sp |
4.5:1 |
8. Seguridad
8.1. Proteccion de PIN
| Aspecto |
Implementacion |
| Display |
Puntos negros (nunca digitos) |
| Almacenamiento |
Hash Argon2id + salt en Keychain/Keystore |
| Comparacion |
Server-side timing-safe compare |
| Screenshot |
Bloqueado en esta pantalla |
| Screen recording |
Bloqueado |
8.2. Biometria
| Aspecto |
Implementacion |
| iOS |
LAContext con .deviceOwnerAuthenticationWithBiometrics |
| Android |
BiometricPrompt con BIOMETRIC_STRONG |
| Fallback |
Siempre a PIN de app, NUNCA a PIN del sistema |
| Almacenamiento |
Master key protegida por biometria en Secure Enclave/StrongBox |
9. Datos Requeridos
interface BiometricScreenData {
biometricEnabled: boolean;
biometricType: 'face' | 'fingerprint' | 'none';
pinLength: 4 | 6;
pinAttemptsRemaining: number;
blockedUntil?: Date;
}
9.2. Output Events
| Evento |
Payload |
Destino |
| onBiometricSuccess |
- |
Dashboard |
| onBiometricFail |
attempts_remaining |
Retry o PIN |
| onPINComplete |
pin_hash |
Validation |
| onPINSuccess |
- |
Dashboard |
| onPINFail |
attempts_remaining |
Error state |
| onForgotPIN |
- |
SCR-AUTH-004 |
| onRelogin |
- |
SCR-AUTH-002 |
10.1. iOS Especifico
// LAContext configuration
let context = LAContext()
context.localizedFallbackTitle = "Usar PIN"
context.localizedCancelTitle = "Cancelar"
let reason = "Desbloquea MedTime"
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics,
localizedReason: reason) { ... }
10.2. Android Especifico
// BiometricPrompt configuration
val promptInfo = BiometricPrompt.PromptInfo.Builder()
.setTitle("Desbloquear MedTime")
.setSubtitle("Usa tu huella o rostro")
.setNegativeButtonText("Usar PIN")
.setAllowedAuthenticators(BIOMETRIC_STRONG)
.build()
11. Metricas
11.1. Analytics Events
| Evento |
Parametros |
| screen_view |
screen_name: "biometric_unlock" |
| biometric_attempt |
type: "face"/"fingerprint" |
| biometric_success |
type, time_ms |
| biometric_failure |
type, attempt_number |
| biometric_to_pin |
reason: "cancelled"/"failed" |
| pin_attempt |
- |
| pin_success |
time_ms, attempts_used |
| pin_failure |
attempt_number |
| pin_blocked |
duration_seconds |
| unlock_success |
method: "biometric"/"pin" |
12. Referencias
Documento generado por MobileUxUiDrone (Eight of Eight)