@tgtone/auth-sdk 1.3.0 → 1.3.1

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.
@@ -0,0 +1,315 @@
1
+ # Guía de Migración a v1.3.0 - Session Revocation
2
+
3
+ Esta guía explica cómo migrar tus aplicaciones existentes para usar las nuevas funcionalidades de detección de sesión revocada.
4
+
5
+ ---
6
+
7
+ ## 📋 Resumen de Cambios
8
+
9
+ | Feature | Descripción |
10
+ |---------|-------------|
11
+ | `onSessionRevoked` | Callback ejecutado cuando usuario/tenant es eliminado |
12
+ | `heartbeatIntervalMs` | Intervalo de validación periódica de sesión |
13
+ | `startHeartbeat()` / `stopHeartbeat()` | Control manual del heartbeat |
14
+ | `getBlockedRedirectUrl()` | Genera URL de redirección para sesión revocada |
15
+ | `createAxiosInterceptor()` | Interceptor para Axios que maneja 401 |
16
+ | `createAuthFetch()` | Wrapper de fetch con manejo de sesión |
17
+
18
+ ---
19
+
20
+ ## 🔄 Migración por Tipo de App
21
+
22
+ ### 1. Apps React con Context (Console, Baco, Zenith)
23
+
24
+ **Antes (v1.2.x):**
25
+ ```tsx
26
+ // src/lib/auth-client.ts
27
+ import { TGTAuthClient } from '@tgtone/auth-sdk';
28
+
29
+ export const authClient = new TGTAuthClient({
30
+ identityUrl: 'https://identity.tgtone.cl',
31
+ appDomain: window.location.host,
32
+ debug: import.meta.env.DEV,
33
+ onAuthFailure: (error) => {
34
+ if (error?.code) {
35
+ window.location.href = `${identityUrl}/login?error=${error.code.toLowerCase()}`;
36
+ }
37
+ },
38
+ });
39
+ ```
40
+
41
+ **Después (v1.3.0):**
42
+ ```tsx
43
+ // src/lib/auth-client.ts
44
+ import { TGTAuthClient, AuthError, isRevocationError } from '@tgtone/auth-sdk';
45
+
46
+ const identityUrl = import.meta.env.VITE_IDENTITY_URL || 'https://identity.tgtone.cl';
47
+
48
+ export const authClient = new TGTAuthClient({
49
+ identityUrl,
50
+ appDomain: window.location.host,
51
+ debug: import.meta.env.DEV,
52
+
53
+ // 🆕 Validar sesión cada 5 minutos
54
+ heartbeatIntervalMs: 5 * 60 * 1000,
55
+
56
+ onAuthFailure: (error) => {
57
+ if (error?.code) {
58
+ window.location.href = `${identityUrl}/login?error=${error.code.toLowerCase()}`;
59
+ }
60
+ },
61
+
62
+ // 🆕 Manejar sesión revocada
63
+ onSessionRevoked: (error: AuthError) => {
64
+ console.log('[Auth] Sesión revocada:', error.code, error.message);
65
+ const blockedUrl = authClient.getBlockedRedirectUrl(error);
66
+ window.location.href = blockedUrl;
67
+ },
68
+ });
69
+ ```
70
+
71
+ ### 2. Apps con Hook useTGTAuth
72
+
73
+ **Antes (v1.2.x):**
74
+ ```tsx
75
+ import { useTGTAuth } from '@tgtone/auth-sdk';
76
+
77
+ function App() {
78
+ const { session, loading, logout } = useTGTAuth({
79
+ identityUrl: 'https://identity.tgtone.cl',
80
+ appDomain: 'zenith.tgtone.cl',
81
+ });
82
+
83
+ // ...
84
+ }
85
+ ```
86
+
87
+ **Después (v1.3.0):**
88
+ ```tsx
89
+ import { useTGTAuth } from '@tgtone/auth-sdk';
90
+
91
+ function App() {
92
+ const {
93
+ session,
94
+ loading,
95
+ logout,
96
+ revokedError, // 🆕 Error de sesión revocada
97
+ isHeartbeatActive // 🆕 Estado del heartbeat
98
+ } = useTGTAuth({
99
+ identityUrl: 'https://identity.tgtone.cl',
100
+ appDomain: 'zenith.tgtone.cl',
101
+ enableHeartbeat: true, // 🆕 Default: true
102
+ });
103
+
104
+ // El heartbeat se inicia automáticamente después del login
105
+ // ...
106
+ }
107
+ ```
108
+
109
+ ### 3. Landing Pages (sin redirección automática)
110
+
111
+ **Después (v1.3.0):**
112
+ ```tsx
113
+ import { useTGTAuth } from '@tgtone/auth-sdk';
114
+
115
+ function LandingApp() {
116
+ const { session, loading, revokedError } = useTGTAuth({
117
+ identityUrl: 'https://identity.tgtone.cl',
118
+ appDomain: 'tgtone.cl',
119
+ showRevokedState: true, // 🆕 No redirigir, mostrar estado
120
+ });
121
+
122
+ if (loading) return <Spinner />;
123
+
124
+ // 🆕 Manejar sesión revocada con UI personalizado
125
+ if (revokedError) {
126
+ return (
127
+ <RevokedSessionPage
128
+ error={revokedError}
129
+ onContactSupport={() => window.open('mailto:soporte@tgtone.cl')}
130
+ />
131
+ );
132
+ }
133
+
134
+ if (!session) {
135
+ return <PublicLanding onLogin={() => authClient.redirectToLogin()} />;
136
+ }
137
+
138
+ return <PrivateContent user={session.user} />;
139
+ }
140
+ ```
141
+
142
+ ### 4. Apps con Axios
143
+
144
+ **Después (v1.3.0):**
145
+ ```tsx
146
+ import axios from 'axios';
147
+ import { createAxiosInterceptor } from '@tgtone/auth-sdk/interceptor';
148
+ import { authClient } from './lib/auth-client';
149
+
150
+ const api = axios.create({
151
+ baseURL: '/api',
152
+ headers: { 'Content-Type': 'application/json' }
153
+ });
154
+
155
+ // 🆕 Configurar interceptor
156
+ const removeInterceptor = createAxiosInterceptor(api, authClient, {
157
+ handleRevoked: true,
158
+ excludeUrls: ['/public/health', '/public/metrics'],
159
+ onAuthError: (error) => {
160
+ // Opcional: logging, analytics
161
+ console.error('Auth error:', error.code);
162
+ },
163
+ });
164
+
165
+ export default api;
166
+ ```
167
+
168
+ ### 5. Apps con Fetch nativo
169
+
170
+ **Después (v1.3.0):**
171
+ ```tsx
172
+ import { createAuthFetch } from '@tgtone/auth-sdk/interceptor';
173
+ import { authClient } from './lib/auth-client';
174
+
175
+ // 🆕 Crear fetch con autenticación automática
176
+ const authFetch = createAuthFetch(authClient, {
177
+ handleRevoked: true,
178
+ excludeUrls: ['/public/'],
179
+ });
180
+
181
+ // Uso igual que fetch nativo
182
+ const response = await authFetch('/api/users');
183
+ const data = await response.json();
184
+ ```
185
+
186
+ ---
187
+
188
+ ## 🎯 Casos de Uso por Escenario
189
+
190
+ ### Escenario 1: Usuario eliminado mientras trabaja
191
+
192
+ ```
193
+ 1. Admin elimina usuario desde Console
194
+ 2. Usuario hace request API o heartbeat se ejecuta
195
+ 3. Backend retorna 401 + USER_NOT_FOUND
196
+ 4. SDK detecta error de revocación
197
+ 5. Se ejecuta onSessionRevoked callback
198
+ 6. Usuario es redirigido a /blocked?type=user
199
+ ```
200
+
201
+ ### Escenario 2: Tenant suspendido
202
+
203
+ ```
204
+ 1. Se suspende el tenant (falta de pago, etc.)
205
+ 2. Usuario continúa trabajando
206
+ 3. Heartbeat detecta TENANT_INACTIVE
207
+ 4. Usuario es redirigido a /blocked?type=tenant
208
+ ```
209
+
210
+ ### Escenario 3: Usuario desactivado
211
+
212
+ ```
213
+ 1. Admin desactiva usuario
214
+ 2. Backend retorna USER_INACTIVE
215
+ 3. Usuario ve página de blocked con mensaje apropiado
216
+ ```
217
+
218
+ ---
219
+
220
+ ## ⚙️ Configuración Avanzada
221
+
222
+ ### Deshabilitar Heartbeat
223
+
224
+ ```tsx
225
+ const authClient = new TGTAuthClient({
226
+ // ...
227
+ heartbeatIntervalMs: 0, // Deshabilitado
228
+ });
229
+ ```
230
+
231
+ ### Heartbeat más frecuente (1 minuto)
232
+
233
+ ```tsx
234
+ const authClient = new TGTAuthClient({
235
+ // ...
236
+ heartbeatIntervalMs: 60 * 1000, // 1 minuto
237
+ });
238
+ ```
239
+
240
+ ### Callback personalizado sin redirección
241
+
242
+ ```tsx
243
+ const authClient = new TGTAuthClient({
244
+ // ...
245
+ onSessionRevoked: (error) => {
246
+ // Loguear para analytics
247
+ analytics.track('session_revoked', { code: error.code });
248
+
249
+ // Mostrar modal en lugar de redirigir
250
+ showSessionRevokedModal(error);
251
+ },
252
+ });
253
+ ```
254
+
255
+ ---
256
+
257
+ ## 🧪 Testing
258
+
259
+ ### Simular sesión revocada
260
+
261
+ ```typescript
262
+ // En desarrollo, puedes simular el error:
263
+ const testError = {
264
+ code: 'USER_NOT_FOUND' as AuthErrorCode,
265
+ message: 'El usuario ha sido eliminado',
266
+ };
267
+
268
+ authClient.onSessionRevoked?.(testError);
269
+ ```
270
+
271
+ ### Verificar heartbeat
272
+
273
+ ```typescript
274
+ // Verificar si está activo
275
+ console.log('Heartbeat activo:', authClient.isHeartbeatActive());
276
+
277
+ // Iniciar manualmente
278
+ authClient.startHeartbeat();
279
+
280
+ // Detener
281
+ authClient.stopHeartbeat();
282
+ ```
283
+
284
+ ---
285
+
286
+ ## 📦 Checklist de Migración
287
+
288
+ - [ ] Actualizar `@tgtone/auth-sdk` a `^1.3.0`
289
+ - [ ] Agregar `heartbeatIntervalMs` a la configuración
290
+ - [ ] Agregar `onSessionRevoked` callback
291
+ - [ ] (Opcional) Configurar interceptor Axios
292
+ - [ ] (Opcional) Actualizar hook useTGTAuth
293
+ - [ ] Probar flujo de sesión revocada
294
+ - [ ] Verificar redirección a `/blocked`
295
+
296
+ ---
297
+
298
+ ## ❓ FAQ
299
+
300
+ **P: ¿El heartbeat afecta el rendimiento?**
301
+ R: No, es un request ligero cada 5 minutos por defecto.
302
+
303
+ **P: ¿Qué pasa si el backend está offline durante el heartbeat?**
304
+ R: El heartbeat ignora errores de red y reintenta en el próximo intervalo.
305
+
306
+ **P: ¿Puedo usar mi propia página de blocked?**
307
+ R: Sí, usa `onSessionRevoked` para manejar el error y mostrar tu propia UI.
308
+
309
+ **P: ¿Necesito configurar el interceptor si uso el heartbeat?**
310
+ R: No es obligatorio, pero recomendado para detectar errores en requests API también.
311
+
312
+ ---
313
+
314
+ **Versión:** 1.3.0
315
+ **Última actualización:** 2026-03-26
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tgtone/auth-sdk",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "description": "SDK de autenticación JWT + Bearer Token para el ecosistema TGT One",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",