@neodaten/auth-native 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +200 -2
- package/dist/almacen-con-desbloqueo.d.ts +19 -0
- package/dist/almacen-con-desbloqueo.js +117 -0
- package/dist/almacen-con-desbloqueo.js.map +1 -0
- package/dist/almacen-seguro.d.ts +5 -0
- package/dist/almacen-seguro.js +2 -0
- package/dist/almacen-seguro.js.map +1 -0
- package/dist/base64url.d.ts +3 -0
- package/dist/base64url.js +40 -0
- package/dist/base64url.js.map +1 -0
- package/dist/bienvenida/bienvenida-con-ultima-cuenta.d.ts +13 -0
- package/dist/bienvenida/bienvenida-con-ultima-cuenta.js +73 -0
- package/dist/bienvenida/bienvenida-con-ultima-cuenta.js.map +1 -0
- package/dist/bienvenida/estado-de-la-bienvenida.d.ts +14 -0
- package/dist/bienvenida/estado-de-la-bienvenida.js +18 -0
- package/dist/bienvenida/estado-de-la-bienvenida.js.map +1 -0
- package/dist/bienvenida/index.d.ts +5 -0
- package/dist/bienvenida/index.js +5 -0
- package/dist/bienvenida/index.js.map +1 -0
- package/dist/bienvenida/marca-de-la-bienvenida.d.ts +12 -0
- package/dist/bienvenida/marca-de-la-bienvenida.js +2 -0
- package/dist/bienvenida/marca-de-la-bienvenida.js.map +1 -0
- package/dist/bienvenida/textos-de-la-bienvenida.d.ts +9 -0
- package/dist/bienvenida/textos-de-la-bienvenida.js +12 -0
- package/dist/bienvenida/textos-de-la-bienvenida.js.map +1 -0
- package/dist/bienvenida/use-bienvenida.d.ts +13 -0
- package/dist/bienvenida/use-bienvenida.js +42 -0
- package/dist/bienvenida/use-bienvenida.js.map +1 -0
- package/dist/canal-del-canje.d.ts +3 -0
- package/dist/canal-del-canje.js +22 -0
- package/dist/canal-del-canje.js.map +1 -0
- package/dist/cliente-de-identidad-nativa.d.ts +32 -0
- package/dist/cliente-de-identidad-nativa.js +179 -0
- package/dist/cliente-de-identidad-nativa.js.map +1 -0
- package/dist/criptografia.d.ts +15 -0
- package/dist/criptografia.js +28 -0
- package/dist/criptografia.js.map +1 -0
- package/dist/error-de-identidad.d.ts +6 -0
- package/dist/error-de-identidad.js +29 -0
- package/dist/error-de-identidad.js.map +1 -0
- package/dist/expo/crear-almacen-expo.d.ts +17 -0
- package/dist/expo/crear-almacen-expo.js +30 -0
- package/dist/expo/crear-almacen-expo.js.map +1 -0
- package/dist/expo/index.d.ts +1 -0
- package/dist/expo/index.js +2 -0
- package/dist/expo/index.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/keychain/crear-almacen-keychain.d.ts +34 -0
- package/dist/keychain/crear-almacen-keychain.js +46 -0
- package/dist/keychain/crear-almacen-keychain.js.map +1 -0
- package/dist/keychain/index.d.ts +1 -0
- package/dist/keychain/index.js +2 -0
- package/dist/keychain/index.js.map +1 -0
- package/dist/llaves-del-emisor.d.ts +4 -0
- package/dist/llaves-del-emisor.js +42 -0
- package/dist/llaves-del-emisor.js.map +1 -0
- package/dist/login-hospedado.d.ts +29 -0
- package/dist/login-hospedado.js +123 -0
- package/dist/login-hospedado.js.map +1 -0
- package/dist/navegacion-del-login.d.ts +20 -0
- package/dist/navegacion-del-login.js +27 -0
- package/dist/navegacion-del-login.js.map +1 -0
- package/dist/pantalla/index.d.ts +2 -0
- package/dist/pantalla/index.js +3 -0
- package/dist/pantalla/index.js.map +1 -0
- package/dist/pantalla/manejador-de-carga.d.ts +11 -0
- package/dist/pantalla/manejador-de-carga.js +12 -0
- package/dist/pantalla/manejador-de-carga.js.map +1 -0
- package/dist/pantalla/pantalla-de-login-hospedado.d.ts +6 -0
- package/dist/pantalla/pantalla-de-login-hospedado.js +30 -0
- package/dist/pantalla/pantalla-de-login-hospedado.js.map +1 -0
- package/dist/passkey-de-la-bienvenida.d.ts +20 -0
- package/dist/passkey-de-la-bienvenida.js +50 -0
- package/dist/passkey-de-la-bienvenida.js.map +1 -0
- package/dist/pkce.d.ts +8 -0
- package/dist/pkce.js +13 -0
- package/dist/pkce.js.map +1 -0
- package/dist/respuesta-del-emisor.d.ts +17 -0
- package/dist/respuesta-del-emisor.js +70 -0
- package/dist/respuesta-del-emisor.js.map +1 -0
- package/dist/sesion-guardada.d.ts +12 -0
- package/dist/sesion-guardada.js +44 -0
- package/dist/sesion-guardada.js.map +1 -0
- package/dist/sha256.d.ts +1 -0
- package/dist/sha256.js +84 -0
- package/dist/sha256.js.map +1 -0
- package/dist/textos-del-desbloqueo.d.ts +7 -0
- package/dist/textos-del-desbloqueo.js +7 -0
- package/dist/textos-del-desbloqueo.js.map +1 -0
- package/dist/ticket-de-atestacion.d.ts +21 -0
- package/dist/ticket-de-atestacion.js +33 -0
- package/dist/ticket-de-atestacion.js.map +1 -0
- package/dist/ultima-cuenta.d.ts +13 -0
- package/dist/ultima-cuenta.js +67 -0
- package/dist/ultima-cuenta.js.map +1 -0
- package/dist/validar-id-token.d.ts +15 -0
- package/dist/validar-id-token.js +86 -0
- package/dist/validar-id-token.js.map +1 -0
- package/dist/vuelo-unico.d.ts +1 -0
- package/dist/vuelo-unico.js +10 -0
- package/dist/vuelo-unico.js.map +1 -0
- package/package.json +61 -3
package/README.md
CHANGED
|
@@ -1,3 +1,201 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @neodaten/auth-native
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Cliente de identidad para apps React Native del ecosistema. La app entra por el login hospedado del
|
|
4
|
+
emisor del proyecto (`…/p/<slug>`) con `authorization_code` + PKCE S256 y renueva con el refresh
|
|
5
|
+
rotativo. Sin dependencias: usa `fetch`, `crypto.getRandomValues` y un almacén seguro que inyecta la
|
|
6
|
+
app.
|
|
7
|
+
|
|
8
|
+
## Uso
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import { crearClienteDeIdentidadNativa, type AlmacenSeguro } from '@neodaten/auth-native';
|
|
12
|
+
|
|
13
|
+
const identidad = crearClienteDeIdentidadNativa({
|
|
14
|
+
emisor: 'https://auth.neodaten.com/p/luup',
|
|
15
|
+
coreApiUrl: 'https://auth.neodaten.com/api',
|
|
16
|
+
clienteId: 'luup-ios',
|
|
17
|
+
recurso: 'urn:neodaten:api:luup',
|
|
18
|
+
redireccion: 'com.crashapp.neodaten:/oauth/callback',
|
|
19
|
+
almacen,
|
|
20
|
+
proveedorDeAtestacion,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const login = await identidad.abrirLoginHospedado();
|
|
24
|
+
login.url;
|
|
25
|
+
login.decidir({ url, esMarcoPrincipal });
|
|
26
|
+
await login.completar(urlDelRegreso);
|
|
27
|
+
const token = await identidad.tokenDeAcceso();
|
|
28
|
+
await identidad.cerrarSesion();
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
- `abrirLoginHospedado()` lee el discovery (el `issuer` tiene que ser el emisor configurado), genera
|
|
32
|
+
PKCE, `state` y `nonce`, y con `proveedorDeAtestacion` pide el ticket de atestación
|
|
33
|
+
(`/auth/atestacion/reto` y `/auth/atestacion/ticket`) y lo manda como `atestacion`. Sin proveedor
|
|
34
|
+
abre sin ticket.
|
|
35
|
+
- `origenDelLogin` es el origen de login-web cuando no comparte host con el emisor (en local,
|
|
36
|
+
`http://localhost:3305`). Por omisión es el del emisor; tiene que ser https salvo localhost o
|
|
37
|
+
loopback con un emisor también local, y nunca se toma del regreso.
|
|
38
|
+
- `decidir()` solo carga los orígenes del emisor, del `authorization_endpoint` y del login; Turnstile
|
|
39
|
+
(`challenges.cloudflare.com`) solo dentro de un iframe. El regreso a `redireccion` desde el marco
|
|
40
|
+
principal es el `callback`; lo demás se descarta.
|
|
41
|
+
- `completar()` se usa una sola vez: valida `state` e `iss`, canjea el código con el
|
|
42
|
+
`code_verifier`, valida el id_token (firma ES256 con el JWKS del emisor, `iss`, `aud`/`azp`,
|
|
43
|
+
`nonce`, `exp`, `iat`, `sub`) y guarda la sesión en el almacén.
|
|
44
|
+
- `cerrarSesion()` revoca el refresh y borra el almacén.
|
|
45
|
+
- Firma: con `crypto.subtle` se verifica ES256 contra el JWKS del emisor. Sin él (Hermes) no se
|
|
46
|
+
verifica la firma y se confía en el TLS del canje (OIDC Core 3.1.3.7, punto 6): el id_token solo
|
|
47
|
+
se toma de la respuesta del endpoint de token (que tiene que ser https, salvo localhost con un
|
|
48
|
+
emisor también local), nunca de la URL, y se siguen exigiendo `iss`,
|
|
49
|
+
`aud`, `azp`, `nonce`, `exp` e `iat`. PKCE usa un SHA-256 propio. Solo hace falta
|
|
50
|
+
`crypto.getRandomValues`; sin él, `abrirLoginHospedado()` da `sin_criptografia`.
|
|
51
|
+
- La aplicación tiene que ser NATIVE en la consola, con `<bundle>:/oauth/callback` como URL de
|
|
52
|
+
retorno y de cierre de sesión.
|
|
53
|
+
|
|
54
|
+
## Pantalla
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
import { PantallaDeLoginHospedado } from '@neodaten/auth-native/pantalla';
|
|
58
|
+
|
|
59
|
+
<PantallaDeLoginHospedado
|
|
60
|
+
login={login}
|
|
61
|
+
alEntrar={() => navegar('inicio')}
|
|
62
|
+
alFallar={(error) => mostrar(error)}
|
|
63
|
+
alDescartarEnlace={(url) => registrar(url)}
|
|
64
|
+
/>;
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
WebView a pantalla completa, incógnita, sin cache ni cookies compartidas, sin puente JS, sin
|
|
68
|
+
ventanas nuevas ni archivos locales. Toda navegación pasa por `login.decidir()`
|
|
69
|
+
(`originWhitelist: ['*']` para que react-native-webview no mande las URLs ajenas a
|
|
70
|
+
`Linking.openURL`). Requiere `react` y `react-native-webview` >=13.15.0 <15 en la app.
|
|
71
|
+
|
|
72
|
+
## Desbloqueo con Face ID, Touch ID o huella
|
|
73
|
+
|
|
74
|
+
`AlmacenConDesbloqueo` extiende `AlmacenSeguro`: guarda la sesión en el llavero normal y, con el
|
|
75
|
+
desbloqueo activo, mueve el refresh a un elemento del llavero que solo se abre con la biometría del
|
|
76
|
+
set actual del dispositivo (`BIOMETRY_CURRENT_SET`, `WHEN_PASSCODE_SET_THIS_DEVICE_ONLY`). La app
|
|
77
|
+
solo crea el almacén con el adaptador de su librería, se lo pasa al cliente y conecta un interruptor
|
|
78
|
+
en Mi cuenta.
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
almacen.desbloqueoDisponible(); // Promise<boolean>: si es false, no se muestra el interruptor
|
|
82
|
+
almacen.desbloqueoActivo(); // Promise<boolean>
|
|
83
|
+
almacen.activarDesbloqueo(); // pide el biométrico y protege el refresh
|
|
84
|
+
almacen.desactivarDesbloqueo(); // pide el biométrico y regresa el refresh al llavero normal
|
|
85
|
+
almacen.bloquear(); // olvida el desbloqueo en memoria; la siguiente lectura vuelve a pedirlo
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
- Con el desbloqueo activo, la primera lectura de la sesión (`tokenDeAcceso()`, `renovar()`) pide
|
|
89
|
+
el biométrico una vez; mientras la app siga viva usa el refresh desbloqueado en memoria. Para
|
|
90
|
+
volver a pedirlo al regresar a primer plano, llama `almacen.bloquear()` desde `AppState`.
|
|
91
|
+
- Si cancelan o el sistema rechaza el aviso, sale `ErrorDeIdentidad` con `desbloqueo_cancelado`: la
|
|
92
|
+
sesión se conserva y la app ofrece `TEXTOS_DEL_DESBLOQUEO.entrarConCodigo`, que abre el login
|
|
93
|
+
hospedado.
|
|
94
|
+
- Si el sistema invalidó la llave (cambiaron los rostros o las huellas), sale
|
|
95
|
+
`desbloqueo_invalidado`: el paquete ya borró la sesión local y la app manda al login.
|
|
96
|
+
- `cerrarSesion()` borra todo y apaga el desbloqueo. Si no confirman el biométrico, igual borra la
|
|
97
|
+
sesión local, solo que no puede revocar el refresh.
|
|
98
|
+
- Errores al activar: `desbloqueo_no_disponible` (sin biometría), `sin_sesion` y
|
|
99
|
+
`desbloqueo_cancelado`. `esErrorDeDesbloqueo(error)` reconoce los dos de la lectura.
|
|
100
|
+
- Con expo-secure-store en Android, guardar en el elemento protegido también pide el biométrico, así
|
|
101
|
+
que cada rotación del refresh con el desbloqueo activo lo vuelve a pedir. En iOS no: el elemento se
|
|
102
|
+
borra y se crea de nuevo, y crear no pide autenticación.
|
|
103
|
+
- Con react-native-keychain en Android, una llave invalidada se reporta igual que una cancelación:
|
|
104
|
+
llega como `desbloqueo_cancelado` y se resuelve al entrar con código, que reemplaza la llave.
|
|
105
|
+
|
|
106
|
+
Los textos (`TEXTOS_DEL_DESBLOQUEO`) están en español de México y cada adaptador acepta los propios
|
|
107
|
+
como segundo argumento:
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
import { TEXTOS_DEL_DESBLOQUEO } from '@neodaten/auth-native';
|
|
111
|
+
|
|
112
|
+
const textos = { ...TEXTOS_DEL_DESBLOQUEO, motivo: 'Confirma que eres tú para ver tus pedidos.' };
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### App Expo (COMA, conductor de OneChain, Baki, PROTEQA)
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
import * as SecureStore from 'expo-secure-store';
|
|
119
|
+
import { crearAlmacenExpo } from '@neodaten/auth-native/expo';
|
|
120
|
+
|
|
121
|
+
const almacen = crearAlmacenExpo(SecureStore);
|
|
122
|
+
const identidad = crearClienteDeIdentidadNativa({ ...opciones, almacen });
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Usa `requireAuthentication: true`, `keychainAccessible: WHEN_PASSCODE_SET_THIS_DEVICE_ONLY` y
|
|
126
|
+
`authenticationPrompt` con el motivo; la disponibilidad sale de `canUseBiometricAuthentication()`.
|
|
127
|
+
En `app.json`, el plugin declara el texto de Face ID:
|
|
128
|
+
|
|
129
|
+
```json
|
|
130
|
+
[
|
|
131
|
+
"expo-secure-store",
|
|
132
|
+
{ "faceIDPermission": "Usamos Face ID para que entres a tu cuenta sin escribir un código." }
|
|
133
|
+
]
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### App RN CLI (Luup)
|
|
137
|
+
|
|
138
|
+
```ts
|
|
139
|
+
import * as Keychain from 'react-native-keychain';
|
|
140
|
+
import { crearAlmacenKeychain } from '@neodaten/auth-native/keychain';
|
|
141
|
+
|
|
142
|
+
const almacen = crearAlmacenKeychain(Keychain);
|
|
143
|
+
const identidad = crearClienteDeIdentidadNativa({ ...opciones, almacen });
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Usa `accessControl: BIOMETRY_CURRENT_SET`, `accessible: WHEN_PASSCODE_SET_THIS_DEVICE_ONLY` y, en
|
|
147
|
+
Android, `storage: STORAGE_TYPE.RSA`: se cifra con la llave pública sin pedir el biométrico y solo
|
|
148
|
+
descifrar lo pide, así la rotación del refresh no interrumpe. El valor cabe en un bloque RSA de 2048
|
|
149
|
+
bits (hasta 245 bytes). La llave de Android que crea la librería acepta también el código del
|
|
150
|
+
dispositivo y no se invalida al cambiar las huellas. La disponibilidad sale de `getSupportedBiometryType()`. En `ios/<App>/Info.plist`:
|
|
151
|
+
|
|
152
|
+
```xml
|
|
153
|
+
<key>NSFaceIDUsageDescription</key>
|
|
154
|
+
<string>Usamos Face ID para que entres a tu cuenta sin escribir un código.</string>
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Ninguna de las dos entradas suma dependencias: la app inyecta el módulo y el paquete lo tipa con una
|
|
158
|
+
interfaz que coincide con su API pública.
|
|
159
|
+
|
|
160
|
+
## Bienvenida con la última cuenta y passkey
|
|
161
|
+
|
|
162
|
+
Después de «Salir», la bienvenida saluda a la última cuenta y entra con la passkey del sistema (Face ID, Touch ID o huella) sin abrir el login hospedado. La passkey se sigue creando en el login hospedado, con la oferta que aparece tras el SMS.
|
|
163
|
+
|
|
164
|
+
**Requisitos en el core:**
|
|
165
|
+
|
|
166
|
+
- la aplicación nativa de primera parte tiene `settings.passkeyEnLaBienvenida`;
|
|
167
|
+
- el proyecto admite passkey como primer factor.
|
|
168
|
+
|
|
169
|
+
**El cliente recibe un `ProveedorDePasskey`:**
|
|
170
|
+
|
|
171
|
+
- `biometria()` devuelve `'rostro' | 'huella' | 'otra'`, o `null` si el sistema no admite passkeys;
|
|
172
|
+
- `firmar(opcionesJson)` recibe `PublicKeyCredentialRequestOptionsJSON` y devuelve el `AuthenticationResponseJSON` como texto. Si la persona cancela, rechaza con `ErrorDeIdentidad('acceso_cancelado')`. Si no hay credencial en el dispositivo, rechaza con `ErrorDeIdentidad('sin_passkey')`.
|
|
173
|
+
|
|
174
|
+
```ts
|
|
175
|
+
const cliente = crearClienteDeIdentidadNativa({ ...opciones, proveedorDePasskey });
|
|
176
|
+
const { estado, entrando, error, entrarConPasskey, usarOtraCuenta } = useBienvenida(cliente);
|
|
177
|
+
const resultado = await entrarConPasskey();
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Qué significa cada `resultado`:
|
|
181
|
+
|
|
182
|
+
- `'dentro'`: la sesión ya está guardada.
|
|
183
|
+
- `'cancelado'`: no se hace nada.
|
|
184
|
+
- `'abrir_login'`: se abre el login hospedado.
|
|
185
|
+
- `'reintentar'`: hay que mostrar `error`.
|
|
186
|
+
|
|
187
|
+
**Qué se guarda y cuándo se borra:**
|
|
188
|
+
|
|
189
|
+
- La última cuenta (`neodaten.ultima-cuenta`) guarda solo `sub`, nombre, el teléfono enmascarado a cuatro dígitos y `tienePasskey`.
|
|
190
|
+
- Se escribe en cada login y en cada renovación.
|
|
191
|
+
- `cerrarSesion()` la conserva y `usarOtraCuenta()` la borra.
|
|
192
|
+
- Los alcances por omisión incluyen `profile phone` para que el `id_token` traiga el nombre, el teléfono y `tiene_passkey`.
|
|
193
|
+
|
|
194
|
+
El contrato completo del reto y del grant `urn:neodaten:grant-type:passkey` está en la descripción OpenAPI de `POST /api/oidc/{proyecto}/nativa/passkey/reto`.
|
|
195
|
+
|
|
196
|
+
## Publicación
|
|
197
|
+
|
|
198
|
+
`pnpm --filter @neodaten/auth-native empaquetar` compila a `dist/` con `tsc`. El workflow
|
|
199
|
+
`publicar-auth-native.yml` publica en npm con la publicación de confianza, sin procedencia porque el repositorio es privado, al empujar el tag `auth-native-v<versión>`
|
|
200
|
+
sobre un commit de `main`; la versión del tag tiene que coincidir con la de `package.json`. En npm
|
|
201
|
+
hay que dar de alta la publicación de confianza para este paquete y este workflow.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { AlmacenSeguro } from './almacen-seguro';
|
|
2
|
+
export interface AlmacenConDesbloqueo extends AlmacenSeguro {
|
|
3
|
+
desbloqueoDisponible(): Promise<boolean>;
|
|
4
|
+
desbloqueoActivo(): Promise<boolean>;
|
|
5
|
+
activarDesbloqueo(): Promise<void>;
|
|
6
|
+
desactivarDesbloqueo(): Promise<void>;
|
|
7
|
+
bloquear(): void;
|
|
8
|
+
}
|
|
9
|
+
export interface AlmacenProtegido {
|
|
10
|
+
leer(llave: string): Promise<string | null>;
|
|
11
|
+
escribir(llave: string, valor: string): Promise<void>;
|
|
12
|
+
borrar(llave: string): Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
export interface PiezasDelAlmacenConDesbloqueo {
|
|
15
|
+
comun: AlmacenSeguro;
|
|
16
|
+
protegido: AlmacenProtegido;
|
|
17
|
+
biometriaDisponible: () => Promise<boolean>;
|
|
18
|
+
}
|
|
19
|
+
export declare function crearAlmacenConDesbloqueo({ comun, protegido, biometriaDisponible, }: PiezasDelAlmacenConDesbloqueo): AlmacenConDesbloqueo;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { ErrorDeIdentidad } from './error-de-identidad';
|
|
2
|
+
import { LLAVE_DE_LA_SESION, LLAVE_DEL_REFRESCO } from './sesion-guardada';
|
|
3
|
+
import { crearVueloUnico } from './vuelo-unico';
|
|
4
|
+
const LLAVE_DEL_INTERRUPTOR = 'neodaten.desbloqueo';
|
|
5
|
+
const DESBLOQUEO_ACTIVO = 'activo';
|
|
6
|
+
const comoCancelado = (error) => {
|
|
7
|
+
if (error instanceof ErrorDeIdentidad)
|
|
8
|
+
throw error;
|
|
9
|
+
throw new ErrorDeIdentidad('desbloqueo_cancelado', { cause: error });
|
|
10
|
+
};
|
|
11
|
+
export function crearAlmacenConDesbloqueo({ comun, protegido, biometriaDisponible, }) {
|
|
12
|
+
let refrescoDesbloqueado = null;
|
|
13
|
+
let generacion = 0;
|
|
14
|
+
const desbloqueoActivo = async () => (await comun.obtener(LLAVE_DEL_INTERRUPTOR)) === DESBLOQUEO_ACTIVO;
|
|
15
|
+
function olvidarRefrescoDesbloqueado() {
|
|
16
|
+
refrescoDesbloqueado = null;
|
|
17
|
+
generacion += 1;
|
|
18
|
+
}
|
|
19
|
+
function recordarRefrescoDesbloqueado(refresco) {
|
|
20
|
+
refrescoDesbloqueado = refresco;
|
|
21
|
+
generacion += 1;
|
|
22
|
+
}
|
|
23
|
+
async function apagarDesbloqueo() {
|
|
24
|
+
olvidarRefrescoDesbloqueado();
|
|
25
|
+
await protegido.borrar(LLAVE_DEL_REFRESCO);
|
|
26
|
+
await comun.borrar(LLAVE_DEL_INTERRUPTOR);
|
|
27
|
+
}
|
|
28
|
+
async function olvidarSesionInvalidada() {
|
|
29
|
+
await apagarDesbloqueo();
|
|
30
|
+
await comun.borrar(LLAVE_DE_LA_SESION);
|
|
31
|
+
await comun.borrar(LLAVE_DEL_REFRESCO);
|
|
32
|
+
throw new ErrorDeIdentidad('desbloqueo_invalidado');
|
|
33
|
+
}
|
|
34
|
+
async function leerRefrescoProtegido() {
|
|
35
|
+
const refresco = await protegido.leer(LLAVE_DEL_REFRESCO).catch(comoCancelado);
|
|
36
|
+
if (refresco === null)
|
|
37
|
+
return olvidarSesionInvalidada();
|
|
38
|
+
return refresco;
|
|
39
|
+
}
|
|
40
|
+
const desbloquear = crearVueloUnico(async () => {
|
|
41
|
+
if (refrescoDesbloqueado !== null)
|
|
42
|
+
return refrescoDesbloqueado;
|
|
43
|
+
const generacionDeLaLectura = generacion;
|
|
44
|
+
const refresco = await leerRefrescoProtegido();
|
|
45
|
+
if (generacionDeLaLectura === generacion)
|
|
46
|
+
refrescoDesbloqueado = refresco;
|
|
47
|
+
if (refrescoDesbloqueado === null)
|
|
48
|
+
throw new ErrorDeIdentidad('desbloqueo_cancelado');
|
|
49
|
+
return refrescoDesbloqueado;
|
|
50
|
+
});
|
|
51
|
+
async function protegerRefresco(refresco) {
|
|
52
|
+
await protegido.borrar(LLAVE_DEL_REFRESCO);
|
|
53
|
+
await protegido.escribir(LLAVE_DEL_REFRESCO, refresco).catch(comoCancelado);
|
|
54
|
+
}
|
|
55
|
+
async function comprobarRefrescoProtegido(refresco) {
|
|
56
|
+
const leido = await protegido.leer(LLAVE_DEL_REFRESCO).catch(async (error) => {
|
|
57
|
+
await protegido.borrar(LLAVE_DEL_REFRESCO);
|
|
58
|
+
return comoCancelado(error);
|
|
59
|
+
});
|
|
60
|
+
if (leido === refresco)
|
|
61
|
+
return;
|
|
62
|
+
await protegido.borrar(LLAVE_DEL_REFRESCO);
|
|
63
|
+
throw new ErrorDeIdentidad('desbloqueo_no_disponible');
|
|
64
|
+
}
|
|
65
|
+
async function refrescoParaProteger() {
|
|
66
|
+
if (!(await biometriaDisponible()))
|
|
67
|
+
throw new ErrorDeIdentidad('desbloqueo_no_disponible');
|
|
68
|
+
const refresco = await comun.obtener(LLAVE_DEL_REFRESCO);
|
|
69
|
+
if (refresco === null)
|
|
70
|
+
throw new ErrorDeIdentidad('sin_sesion');
|
|
71
|
+
return refresco;
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
async obtener(llave) {
|
|
75
|
+
if (!(await desbloqueoActivo()))
|
|
76
|
+
return comun.obtener(llave);
|
|
77
|
+
if (llave === LLAVE_DEL_REFRESCO)
|
|
78
|
+
return desbloquear();
|
|
79
|
+
if (llave === LLAVE_DE_LA_SESION)
|
|
80
|
+
await desbloquear();
|
|
81
|
+
return comun.obtener(llave);
|
|
82
|
+
},
|
|
83
|
+
async guardar(llave, valor) {
|
|
84
|
+
if (llave !== LLAVE_DEL_REFRESCO || !(await desbloqueoActivo())) {
|
|
85
|
+
return comun.guardar(llave, valor);
|
|
86
|
+
}
|
|
87
|
+
recordarRefrescoDesbloqueado(valor);
|
|
88
|
+
await protegerRefresco(valor);
|
|
89
|
+
},
|
|
90
|
+
async borrar(llave) {
|
|
91
|
+
if (llave === LLAVE_DEL_REFRESCO)
|
|
92
|
+
await apagarDesbloqueo();
|
|
93
|
+
await comun.borrar(llave);
|
|
94
|
+
},
|
|
95
|
+
desbloqueoDisponible: biometriaDisponible,
|
|
96
|
+
desbloqueoActivo,
|
|
97
|
+
async activarDesbloqueo() {
|
|
98
|
+
if (await desbloqueoActivo())
|
|
99
|
+
return;
|
|
100
|
+
const refresco = await refrescoParaProteger();
|
|
101
|
+
await protegerRefresco(refresco);
|
|
102
|
+
await comprobarRefrescoProtegido(refresco);
|
|
103
|
+
await comun.borrar(LLAVE_DEL_REFRESCO);
|
|
104
|
+
await comun.guardar(LLAVE_DEL_INTERRUPTOR, DESBLOQUEO_ACTIVO);
|
|
105
|
+
recordarRefrescoDesbloqueado(refresco);
|
|
106
|
+
},
|
|
107
|
+
async desactivarDesbloqueo() {
|
|
108
|
+
if (!(await desbloqueoActivo()))
|
|
109
|
+
return;
|
|
110
|
+
const refresco = await desbloquear();
|
|
111
|
+
await comun.guardar(LLAVE_DEL_REFRESCO, refresco);
|
|
112
|
+
await apagarDesbloqueo();
|
|
113
|
+
},
|
|
114
|
+
bloquear: olvidarRefrescoDesbloqueado,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=almacen-con-desbloqueo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"almacen-con-desbloqueo.js","sourceRoot":"","sources":["../src/almacen-con-desbloqueo.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,MAAM,qBAAqB,GAAG,qBAAqB,CAAC;AACpD,MAAM,iBAAiB,GAAG,QAAQ,CAAC;AAsBnC,MAAM,aAAa,GAAG,CAAC,KAAc,EAAS,EAAE;IAC9C,IAAI,KAAK,YAAY,gBAAgB;QAAE,MAAM,KAAK,CAAC;IACnD,MAAM,IAAI,gBAAgB,CAAC,sBAAsB,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;AACvE,CAAC,CAAC;AAEF,MAAM,UAAU,yBAAyB,CAAC,EACxC,KAAK,EACL,SAAS,EACT,mBAAmB,GACW;IAC9B,IAAI,oBAAoB,GAAkB,IAAI,CAAC;IAC/C,IAAI,UAAU,GAAG,CAAC,CAAC;IAEnB,MAAM,gBAAgB,GAAG,KAAK,IAAsB,EAAE,CACpD,CAAC,MAAM,KAAK,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC,KAAK,iBAAiB,CAAC;IAErE,SAAS,2BAA2B;QAClC,oBAAoB,GAAG,IAAI,CAAC;QAC5B,UAAU,IAAI,CAAC,CAAC;IAClB,CAAC;IAED,SAAS,4BAA4B,CAAC,QAAgB;QACpD,oBAAoB,GAAG,QAAQ,CAAC;QAChC,UAAU,IAAI,CAAC,CAAC;IAClB,CAAC;IAED,KAAK,UAAU,gBAAgB;QAC7B,2BAA2B,EAAE,CAAC;QAC9B,MAAM,SAAS,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;QAC3C,MAAM,KAAK,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC;IAC5C,CAAC;IAED,KAAK,UAAU,uBAAuB;QACpC,MAAM,gBAAgB,EAAE,CAAC;QACzB,MAAM,KAAK,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;QACvC,MAAM,KAAK,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;QACvC,MAAM,IAAI,gBAAgB,CAAC,uBAAuB,CAAC,CAAC;IACtD,CAAC;IAED,KAAK,UAAU,qBAAqB;QAClC,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QAC/E,IAAI,QAAQ,KAAK,IAAI;YAAE,OAAO,uBAAuB,EAAE,CAAC;QACxD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM,WAAW,GAAG,eAAe,CAAC,KAAK,IAAqB,EAAE;QAC9D,IAAI,oBAAoB,KAAK,IAAI;YAAE,OAAO,oBAAoB,CAAC;QAC/D,MAAM,qBAAqB,GAAG,UAAU,CAAC;QACzC,MAAM,QAAQ,GAAG,MAAM,qBAAqB,EAAE,CAAC;QAC/C,IAAI,qBAAqB,KAAK,UAAU;YAAE,oBAAoB,GAAG,QAAQ,CAAC;QAC1E,IAAI,oBAAoB,KAAK,IAAI;YAAE,MAAM,IAAI,gBAAgB,CAAC,sBAAsB,CAAC,CAAC;QACtF,OAAO,oBAAoB,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,KAAK,UAAU,gBAAgB,CAAC,QAAgB;QAC9C,MAAM,SAAS,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;QAC3C,MAAM,SAAS,CAAC,QAAQ,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IAC9E,CAAC;IAED,KAAK,UAAU,0BAA0B,CAAC,QAAgB;QACxD,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,KAAc,EAAE,EAAE;YACpF,MAAM,SAAS,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;YAC3C,OAAO,aAAa,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC,CAAC,CAAC;QACH,IAAI,KAAK,KAAK,QAAQ;YAAE,OAAO;QAC/B,MAAM,SAAS,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;QAC3C,MAAM,IAAI,gBAAgB,CAAC,0BAA0B,CAAC,CAAC;IACzD,CAAC;IAED,KAAK,UAAU,oBAAoB;QACjC,IAAI,CAAC,CAAC,MAAM,mBAAmB,EAAE,CAAC;YAAE,MAAM,IAAI,gBAAgB,CAAC,0BAA0B,CAAC,CAAC;QAC3F,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;QACzD,IAAI,QAAQ,KAAK,IAAI;YAAE,MAAM,IAAI,gBAAgB,CAAC,YAAY,CAAC,CAAC;QAChE,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,OAAO;QACL,KAAK,CAAC,OAAO,CAAC,KAAK;YACjB,IAAI,CAAC,CAAC,MAAM,gBAAgB,EAAE,CAAC;gBAAE,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YAC7D,IAAI,KAAK,KAAK,kBAAkB;gBAAE,OAAO,WAAW,EAAE,CAAC;YACvD,IAAI,KAAK,KAAK,kBAAkB;gBAAE,MAAM,WAAW,EAAE,CAAC;YACtD,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;QAED,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK;YACxB,IAAI,KAAK,KAAK,kBAAkB,IAAI,CAAC,CAAC,MAAM,gBAAgB,EAAE,CAAC,EAAE,CAAC;gBAChE,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;YACrC,CAAC;YACD,4BAA4B,CAAC,KAAK,CAAC,CAAC;YACpC,MAAM,gBAAgB,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,KAAK;YAChB,IAAI,KAAK,KAAK,kBAAkB;gBAAE,MAAM,gBAAgB,EAAE,CAAC;YAC3D,MAAM,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC;QAED,oBAAoB,EAAE,mBAAmB;QACzC,gBAAgB;QAEhB,KAAK,CAAC,iBAAiB;YACrB,IAAI,MAAM,gBAAgB,EAAE;gBAAE,OAAO;YACrC,MAAM,QAAQ,GAAG,MAAM,oBAAoB,EAAE,CAAC;YAC9C,MAAM,gBAAgB,CAAC,QAAQ,CAAC,CAAC;YACjC,MAAM,0BAA0B,CAAC,QAAQ,CAAC,CAAC;YAC3C,MAAM,KAAK,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;YACvC,MAAM,KAAK,CAAC,OAAO,CAAC,qBAAqB,EAAE,iBAAiB,CAAC,CAAC;YAC9D,4BAA4B,CAAC,QAAQ,CAAC,CAAC;QACzC,CAAC;QAED,KAAK,CAAC,oBAAoB;YACxB,IAAI,CAAC,CAAC,MAAM,gBAAgB,EAAE,CAAC;gBAAE,OAAO;YACxC,MAAM,QAAQ,GAAG,MAAM,WAAW,EAAE,CAAC;YACrC,MAAM,KAAK,CAAC,OAAO,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC;YAClD,MAAM,gBAAgB,EAAE,CAAC;QAC3B,CAAC;QAED,QAAQ,EAAE,2BAA2B;KACtC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"almacen-seguro.js","sourceRoot":"","sources":["../src/almacen-seguro.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const ALFABETO = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
|
|
2
|
+
const BITS_POR_SIMBOLO = 6;
|
|
3
|
+
const BITS_POR_BYTE = 8;
|
|
4
|
+
const MASCARA_DEL_SIMBOLO = 0b111111;
|
|
5
|
+
const MASCARA_DEL_BYTE = 0xff;
|
|
6
|
+
const FORMA_BASE64URL = /^[A-Za-z0-9_-]*$/;
|
|
7
|
+
export const aBase64url = (bytes) => {
|
|
8
|
+
let texto = '';
|
|
9
|
+
let acumulado = 0;
|
|
10
|
+
let bits = 0;
|
|
11
|
+
for (const byte of bytes) {
|
|
12
|
+
acumulado = (acumulado << BITS_POR_BYTE) | byte;
|
|
13
|
+
bits += BITS_POR_BYTE;
|
|
14
|
+
while (bits >= BITS_POR_SIMBOLO) {
|
|
15
|
+
bits -= BITS_POR_SIMBOLO;
|
|
16
|
+
texto += ALFABETO[(acumulado >> bits) & MASCARA_DEL_SIMBOLO];
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
if (bits > 0)
|
|
20
|
+
texto += ALFABETO[(acumulado << (BITS_POR_SIMBOLO - bits)) & MASCARA_DEL_SIMBOLO];
|
|
21
|
+
return texto;
|
|
22
|
+
};
|
|
23
|
+
export const deBase64url = (texto) => {
|
|
24
|
+
if (!FORMA_BASE64URL.test(texto))
|
|
25
|
+
return null;
|
|
26
|
+
const bytes = [];
|
|
27
|
+
let acumulado = 0;
|
|
28
|
+
let bits = 0;
|
|
29
|
+
for (const simbolo of texto) {
|
|
30
|
+
acumulado = (acumulado << BITS_POR_SIMBOLO) | ALFABETO.indexOf(simbolo);
|
|
31
|
+
bits += BITS_POR_SIMBOLO;
|
|
32
|
+
if (bits >= BITS_POR_BYTE) {
|
|
33
|
+
bits -= BITS_POR_BYTE;
|
|
34
|
+
bytes.push((acumulado >> bits) & MASCARA_DEL_BYTE);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return new Uint8Array(bytes);
|
|
38
|
+
};
|
|
39
|
+
export const textoABytes = (texto) => new TextEncoder().encode(texto);
|
|
40
|
+
//# sourceMappingURL=base64url.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base64url.js","sourceRoot":"","sources":["../src/base64url.ts"],"names":[],"mappings":"AAAA,MAAM,QAAQ,GAAG,kEAAkE,CAAC;AACpF,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAC3B,MAAM,aAAa,GAAG,CAAC,CAAC;AACxB,MAAM,mBAAmB,GAAG,QAAQ,CAAC;AACrC,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAC9B,MAAM,eAAe,GAAG,kBAAkB,CAAC;AAE3C,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAAiB,EAAU,EAAE;IACtD,IAAI,KAAK,GAAG,EAAE,CAAC;IACf,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,SAAS,GAAG,CAAC,SAAS,IAAI,aAAa,CAAC,GAAG,IAAI,CAAC;QAChD,IAAI,IAAI,aAAa,CAAC;QACtB,OAAO,IAAI,IAAI,gBAAgB,EAAE,CAAC;YAChC,IAAI,IAAI,gBAAgB,CAAC;YACzB,KAAK,IAAI,QAAQ,CAAC,CAAC,SAAS,IAAI,IAAI,CAAC,GAAG,mBAAmB,CAAC,CAAC;QAC/D,CAAC;IACH,CAAC;IACD,IAAI,IAAI,GAAG,CAAC;QAAE,KAAK,IAAI,QAAQ,CAAC,CAAC,SAAS,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC,GAAG,mBAAmB,CAAC,CAAC;IAChG,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,KAAa,EAAqB,EAAE;IAC9D,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAC9C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,MAAM,OAAO,IAAI,KAAK,EAAE,CAAC;QAC5B,SAAS,GAAG,CAAC,SAAS,IAAI,gBAAgB,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACxE,IAAI,IAAI,gBAAgB,CAAC;QACzB,IAAI,IAAI,IAAI,aAAa,EAAE,CAAC;YAC1B,IAAI,IAAI,aAAa,CAAC;YACtB,KAAK,CAAC,IAAI,CAAC,CAAC,SAAS,IAAI,IAAI,CAAC,GAAG,gBAAgB,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;IACD,OAAO,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;AAC/B,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,KAAa,EAAc,EAAE,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import type { ClienteDeIdentidadNativa } from '../cliente-de-identidad-nativa';
|
|
3
|
+
import type { MarcaDeLaBienvenida } from './marca-de-la-bienvenida';
|
|
4
|
+
import { type TextosDeLaBienvenida } from './textos-de-la-bienvenida';
|
|
5
|
+
export interface PropiedadesDeLaBienvenida {
|
|
6
|
+
cliente: Pick<ClienteDeIdentidadNativa, 'ultimaCuenta' | 'biometriaDeLaPasskey' | 'entrarConPasskey' | 'usarOtraCuenta'>;
|
|
7
|
+
marca: MarcaDeLaBienvenida;
|
|
8
|
+
alEntrar: () => void;
|
|
9
|
+
alAbrirElLogin: () => void;
|
|
10
|
+
sinUltimaCuenta: ReactNode;
|
|
11
|
+
textos?: Partial<TextosDeLaBienvenida>;
|
|
12
|
+
}
|
|
13
|
+
export declare function BienvenidaConUltimaCuenta({ cliente, marca, alEntrar, alAbrirElLogin, sinUltimaCuenta, textos, }: PropiedadesDeLaBienvenida): string | number | bigint | boolean | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | import("react/jsx-runtime").JSX.Element | null | undefined;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { ActivityIndicator, Pressable, StyleSheet, Text, View } from 'react-native';
|
|
3
|
+
import { TEXTOS_DE_LA_BIENVENIDA } from './textos-de-la-bienvenida';
|
|
4
|
+
import { useBienvenida } from './use-bienvenida';
|
|
5
|
+
const seguirSegun = ({ alEntrar, alAbrirElLogin }) => (resultado) => {
|
|
6
|
+
if (resultado === 'dentro')
|
|
7
|
+
alEntrar();
|
|
8
|
+
if (resultado === 'abrir_login')
|
|
9
|
+
alAbrirElLogin();
|
|
10
|
+
};
|
|
11
|
+
function BotonPrincipal({ contexto, biometria, }) {
|
|
12
|
+
const { bienvenida, marca, textos, alAbrirElLogin } = contexto;
|
|
13
|
+
const entrarConPasskey = () => void bienvenida.entrarConPasskey().then(seguirSegun(contexto));
|
|
14
|
+
const etiqueta = biometria === null ? textos.entrar : textos.entrarCon[biometria];
|
|
15
|
+
return (_jsx(Pressable, { accessibilityRole: "button", disabled: bienvenida.entrando, onPress: biometria === null ? alAbrirElLogin : entrarConPasskey, style: [estilos.boton, { backgroundColor: marca.colorDelBoton }], children: bienvenida.entrando ? (_jsx(ActivityIndicator, { color: marca.colorDelTextoDelBoton })) : (_jsxs(View, { style: estilos.fila, children: [biometria === null ? null : marca.iconos?.[biometria], _jsx(Text, { style: [
|
|
16
|
+
estilos.textoDelBoton,
|
|
17
|
+
{ color: marca.colorDelTextoDelBoton, fontFamily: marca.tipografia },
|
|
18
|
+
], children: etiqueta })] })) }));
|
|
19
|
+
}
|
|
20
|
+
function Enlace({ texto, alTocar, marca, }) {
|
|
21
|
+
return (_jsx(Pressable, { accessibilityRole: "link", onPress: alTocar, style: estilos.enlace, children: _jsx(Text, { style: [
|
|
22
|
+
estilos.textoDelEnlace,
|
|
23
|
+
{ color: marca.colorSecundario, fontFamily: marca.tipografia },
|
|
24
|
+
], children: texto }) }));
|
|
25
|
+
}
|
|
26
|
+
function Saludo({ cuenta, contexto }) {
|
|
27
|
+
const { marca, textos } = contexto;
|
|
28
|
+
return (_jsxs(View, { style: estilos.saludo, children: [marca.logo, _jsx(Text, { style: [estilos.titulo, { color: marca.colorDelTexto, fontFamily: marca.tipografia }], children: textos.saludo(cuenta.nombre) }), cuenta.telefonoEnmascarado === null ? null : (_jsx(Text, { style: [estilos.telefono, { color: marca.colorSecundario, fontFamily: marca.tipografia }], children: cuenta.telefonoEnmascarado }))] }));
|
|
29
|
+
}
|
|
30
|
+
function ConUltimaCuenta({ cuenta, biometria, contexto, }) {
|
|
31
|
+
const { bienvenida, marca, textos, alAbrirElLogin } = contexto;
|
|
32
|
+
const usarOtraCuenta = () => void bienvenida.usarOtraCuenta().then(alAbrirElLogin);
|
|
33
|
+
return (_jsxs(View, { style: [estilos.pantalla, { backgroundColor: marca.colorDeFondo }], children: [_jsx(Saludo, { cuenta: cuenta, contexto: contexto }), bienvenida.error === null ? null : (_jsx(Text, { style: [estilos.error, { color: marca.colorDelTexto }], children: bienvenida.error.message })), _jsx(BotonPrincipal, { contexto: contexto, biometria: biometria }), biometria === null ? null : (_jsx(Enlace, { texto: textos.entrarDeOtraForma, alTocar: alAbrirElLogin, marca: marca })), _jsx(Enlace, { texto: textos.usarOtraCuenta, alTocar: usarOtraCuenta, marca: marca })] }));
|
|
34
|
+
}
|
|
35
|
+
export function BienvenidaConUltimaCuenta({ cliente, marca, alEntrar, alAbrirElLogin, sinUltimaCuenta, textos, }) {
|
|
36
|
+
const bienvenida = useBienvenida(cliente);
|
|
37
|
+
const contexto = {
|
|
38
|
+
bienvenida,
|
|
39
|
+
marca,
|
|
40
|
+
textos: { ...TEXTOS_DE_LA_BIENVENIDA, ...textos },
|
|
41
|
+
alEntrar,
|
|
42
|
+
alAbrirElLogin,
|
|
43
|
+
};
|
|
44
|
+
const { estado } = bienvenida;
|
|
45
|
+
if (estado.tipo === 'cargando') {
|
|
46
|
+
return _jsx(View, { style: [estilos.pantalla, { backgroundColor: marca.colorDeFondo }] });
|
|
47
|
+
}
|
|
48
|
+
if (estado.tipo === 'sin_cuenta')
|
|
49
|
+
return sinUltimaCuenta;
|
|
50
|
+
return (_jsx(ConUltimaCuenta, { cuenta: estado.cuenta, biometria: estado.biometria, contexto: contexto }));
|
|
51
|
+
}
|
|
52
|
+
const ESPACIO = 16;
|
|
53
|
+
const RADIO_DEL_BOTON = 14;
|
|
54
|
+
const ALTO_DEL_BOTON = 52;
|
|
55
|
+
const estilos = StyleSheet.create({
|
|
56
|
+
pantalla: { flex: 1, justifyContent: 'center', padding: ESPACIO * 2, gap: ESPACIO },
|
|
57
|
+
saludo: { alignItems: 'center', gap: ESPACIO / 2, marginBottom: ESPACIO },
|
|
58
|
+
titulo: { fontSize: 28, fontWeight: '600', textAlign: 'center' },
|
|
59
|
+
telefono: { fontSize: 16, textAlign: 'center' },
|
|
60
|
+
error: { fontSize: 14, textAlign: 'center' },
|
|
61
|
+
boton: {
|
|
62
|
+
minHeight: ALTO_DEL_BOTON,
|
|
63
|
+
borderRadius: RADIO_DEL_BOTON,
|
|
64
|
+
alignItems: 'center',
|
|
65
|
+
justifyContent: 'center',
|
|
66
|
+
paddingHorizontal: ESPACIO,
|
|
67
|
+
},
|
|
68
|
+
fila: { flexDirection: 'row', alignItems: 'center', gap: ESPACIO / 2 },
|
|
69
|
+
textoDelBoton: { fontSize: 17, fontWeight: '600' },
|
|
70
|
+
enlace: { alignItems: 'center', paddingVertical: ESPACIO / 2 },
|
|
71
|
+
textoDelEnlace: { fontSize: 16 },
|
|
72
|
+
});
|
|
73
|
+
//# sourceMappingURL=bienvenida-con-ultima-cuenta.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bienvenida-con-ultima-cuenta.js","sourceRoot":"","sources":["../../src/bienvenida/bienvenida-con-ultima-cuenta.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { BiometriaDelDispositivo } from '../passkey-de-la-bienvenida';
|
|
2
|
+
import type { UltimaCuenta } from '../ultima-cuenta';
|
|
3
|
+
export type EstadoDeLaBienvenida = {
|
|
4
|
+
tipo: 'cargando';
|
|
5
|
+
} | {
|
|
6
|
+
tipo: 'sin_cuenta';
|
|
7
|
+
} | {
|
|
8
|
+
tipo: 'con_cuenta';
|
|
9
|
+
cuenta: UltimaCuenta;
|
|
10
|
+
biometria: BiometriaDelDispositivo | null;
|
|
11
|
+
};
|
|
12
|
+
export type ResultadoDeLaPasskey = 'dentro' | 'cancelado' | 'abrir_login' | 'reintentar';
|
|
13
|
+
export declare const estadoDeLaBienvenida: (cuenta: UltimaCuenta | null, biometria: BiometriaDelDispositivo | null) => EstadoDeLaBienvenida;
|
|
14
|
+
export declare const resultadoDelError: (error: unknown) => ResultadoDeLaPasskey;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ErrorDeIdentidad } from '../error-de-identidad';
|
|
2
|
+
const ERRORES_QUE_SE_REINTENTAN = new Set([
|
|
3
|
+
'sin_conexion',
|
|
4
|
+
'servicio_no_disponible',
|
|
5
|
+
]);
|
|
6
|
+
export const estadoDeLaBienvenida = (cuenta, biometria) => {
|
|
7
|
+
if (cuenta === null)
|
|
8
|
+
return { tipo: 'sin_cuenta' };
|
|
9
|
+
return { tipo: 'con_cuenta', cuenta, biometria: cuenta.tienePasskey ? biometria : null };
|
|
10
|
+
};
|
|
11
|
+
export const resultadoDelError = (error) => {
|
|
12
|
+
if (!(error instanceof ErrorDeIdentidad))
|
|
13
|
+
throw error;
|
|
14
|
+
if (error.codigo === 'acceso_cancelado')
|
|
15
|
+
return 'cancelado';
|
|
16
|
+
return ERRORES_QUE_SE_REINTENTAN.has(error.codigo) ? 'reintentar' : 'abrir_login';
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=estado-de-la-bienvenida.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"estado-de-la-bienvenida.js","sourceRoot":"","sources":["../../src/bienvenida/estado-de-la-bienvenida.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAiC,MAAM,uBAAuB,CAAC;AAWxF,MAAM,yBAAyB,GAA0C,IAAI,GAAG,CAAC;IAC/E,cAAc;IACd,wBAAwB;CACzB,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,MAA2B,EAC3B,SAAyC,EACnB,EAAE;IACxB,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;IACnD,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AAC3F,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,KAAc,EAAwB,EAAE;IACxE,IAAI,CAAC,CAAC,KAAK,YAAY,gBAAgB,CAAC;QAAE,MAAM,KAAK,CAAC;IACtD,IAAI,KAAK,CAAC,MAAM,KAAK,kBAAkB;QAAE,OAAO,WAAW,CAAC;IAC5D,OAAO,yBAAyB,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,aAAa,CAAC;AACpF,CAAC,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { estadoDeLaBienvenida, resultadoDelError, type EstadoDeLaBienvenida, type ResultadoDeLaPasskey, } from './estado-de-la-bienvenida';
|
|
2
|
+
export { useBienvenida, type Bienvenida } from './use-bienvenida';
|
|
3
|
+
export { BienvenidaConUltimaCuenta, type PropiedadesDeLaBienvenida, } from './bienvenida-con-ultima-cuenta';
|
|
4
|
+
export type { MarcaDeLaBienvenida } from './marca-de-la-bienvenida';
|
|
5
|
+
export { TEXTOS_DE_LA_BIENVENIDA, type TextosDeLaBienvenida } from './textos-de-la-bienvenida';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { estadoDeLaBienvenida, resultadoDelError, } from './estado-de-la-bienvenida';
|
|
2
|
+
export { useBienvenida } from './use-bienvenida';
|
|
3
|
+
export { BienvenidaConUltimaCuenta, } from './bienvenida-con-ultima-cuenta';
|
|
4
|
+
export { TEXTOS_DE_LA_BIENVENIDA } from './textos-de-la-bienvenida';
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/bienvenida/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,iBAAiB,GAGlB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,aAAa,EAAmB,MAAM,kBAAkB,CAAC;AAClE,OAAO,EACL,yBAAyB,GAE1B,MAAM,gCAAgC,CAAC;AAExC,OAAO,EAAE,uBAAuB,EAA6B,MAAM,2BAA2B,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import type { BiometriaDelDispositivo } from '../passkey-de-la-bienvenida';
|
|
3
|
+
export interface MarcaDeLaBienvenida {
|
|
4
|
+
colorDeFondo: string;
|
|
5
|
+
colorDelTexto: string;
|
|
6
|
+
colorSecundario: string;
|
|
7
|
+
colorDelBoton: string;
|
|
8
|
+
colorDelTextoDelBoton: string;
|
|
9
|
+
tipografia?: string;
|
|
10
|
+
logo?: ReactNode;
|
|
11
|
+
iconos?: Partial<Record<BiometriaDelDispositivo, ReactNode>>;
|
|
12
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"marca-de-la-bienvenida.js","sourceRoot":"","sources":["../../src/bienvenida/marca-de-la-bienvenida.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { BiometriaDelDispositivo } from '../passkey-de-la-bienvenida';
|
|
2
|
+
export interface TextosDeLaBienvenida {
|
|
3
|
+
saludo: (nombre: string | null) => string;
|
|
4
|
+
entrarCon: Readonly<Record<BiometriaDelDispositivo, string>>;
|
|
5
|
+
entrar: string;
|
|
6
|
+
entrarDeOtraForma: string;
|
|
7
|
+
usarOtraCuenta: string;
|
|
8
|
+
}
|
|
9
|
+
export declare const TEXTOS_DE_LA_BIENVENIDA: TextosDeLaBienvenida;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export const TEXTOS_DE_LA_BIENVENIDA = {
|
|
2
|
+
saludo: (nombre) => (nombre === null ? 'Hola de nuevo' : `Hola, ${nombre}`),
|
|
3
|
+
entrarCon: {
|
|
4
|
+
rostro: 'Entrar con Face ID',
|
|
5
|
+
huella: 'Entrar con huella',
|
|
6
|
+
otra: 'Entrar con passkey',
|
|
7
|
+
},
|
|
8
|
+
entrar: 'Entrar',
|
|
9
|
+
entrarDeOtraForma: 'Entrar de otra forma',
|
|
10
|
+
usarOtraCuenta: 'Usar otra cuenta',
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=textos-de-la-bienvenida.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"textos-de-la-bienvenida.js","sourceRoot":"","sources":["../../src/bienvenida/textos-de-la-bienvenida.ts"],"names":[],"mappings":"AAUA,MAAM,CAAC,MAAM,uBAAuB,GAAyB;IAC3D,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC;IAC3E,SAAS,EAAE;QACT,MAAM,EAAE,oBAAoB;QAC5B,MAAM,EAAE,mBAAmB;QAC3B,IAAI,EAAE,oBAAoB;KAC3B;IACD,MAAM,EAAE,QAAQ;IAChB,iBAAiB,EAAE,sBAAsB;IACzC,cAAc,EAAE,kBAAkB;CACnC,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ClienteDeIdentidadNativa } from '../cliente-de-identidad-nativa';
|
|
2
|
+
import { ErrorDeIdentidad } from '../error-de-identidad';
|
|
3
|
+
import { type EstadoDeLaBienvenida, type ResultadoDeLaPasskey } from './estado-de-la-bienvenida';
|
|
4
|
+
export interface Bienvenida {
|
|
5
|
+
estado: EstadoDeLaBienvenida;
|
|
6
|
+
entrando: boolean;
|
|
7
|
+
error: ErrorDeIdentidad | null;
|
|
8
|
+
entrarConPasskey(): Promise<ResultadoDeLaPasskey>;
|
|
9
|
+
usarOtraCuenta(): Promise<void>;
|
|
10
|
+
}
|
|
11
|
+
type Cliente = Pick<ClienteDeIdentidadNativa, 'ultimaCuenta' | 'biometriaDeLaPasskey' | 'entrarConPasskey' | 'usarOtraCuenta'>;
|
|
12
|
+
export declare function useBienvenida(cliente: Cliente): Bienvenida;
|
|
13
|
+
export {};
|