jerkjs 2.2.0 → 2.3.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.
@@ -0,0 +1,405 @@
1
+ # Manual para Implementar OAuth 2.0 con Google usando el Framework API SDK
2
+
3
+ ## Índice
4
+ 1. [Introducción](#introducción)
5
+ 2. [Requisitos Previos](#requisitos-previos)
6
+ 3. [Configuración en Google Cloud Console](#configuración-en-google-cloud-console)
7
+ 4. [Configuración del Framework API SDK](#configuración-del-framework-api-sdk)
8
+ 5. [Implementación del Flujo OAuth 2.0](#implementación-del-flujo-oauth-20)
9
+ 6. [Manejo de Tokens](#manejo-de-tokens)
10
+ 7. [Protección de Endpoints](#protección-de-endpoints)
11
+ 8. [Consideraciones de Seguridad](#consideraciones-de-seguridad)
12
+ 9. [Depuración y Troubleshooting](#depuración-y-troubleshooting)
13
+
14
+ ## Introducción
15
+
16
+ OAuth 2.0 es un protocolo de autorización que permite a aplicaciones de terceros obtener acceso limitado a cuentas de usuario de un servicio web. En este manual, aprenderás cómo implementar OAuth 2.0 con Google usando el Framework API SDK.
17
+
18
+ ## Requisitos Previos
19
+
20
+ - Cuenta de Google
21
+ - Acceso a Google Cloud Console
22
+ - Node.js instalado
23
+ - Framework API SDK instalado
24
+ - Conocimientos básicos de JavaScript y APIs REST
25
+
26
+ ## Configuración en Google Cloud Console
27
+
28
+ ### Paso 1: Crear un proyecto en Google Cloud Console
29
+
30
+ 1. Accede a [Google Cloud Console](https://console.cloud.google.com/)
31
+ 2. Haz clic en "Seleccionar un proyecto" o "Nuevo proyecto"
32
+ 3. Ingresa un nombre para tu proyecto
33
+ 4. Haz clic en "Crear"
34
+
35
+ ### Paso 2: Habilitar Google+ API (o las APIs que necesites)
36
+
37
+ 1. En el panel lateral izquierdo, haz clic en "APIs y servicios" > "Biblioteca"
38
+ 2. Busca "Google+ API" o las APIs que planeas usar (como People API)
39
+ 3. Haz clic en "Habilitar"
40
+
41
+ ### Paso 3: Crear credenciales OAuth 2.0
42
+
43
+ 1. En el panel lateral izquierdo, haz clic en "APIs y servicios" > "Credenciales"
44
+ 2. Haz clic en "Crear credenciales" > "ID de cliente OAuth 2.0"
45
+ 3. Si aún no has configurado el consentimiento OAuth, haz clic en "Configurar pantalla de consentimiento OAuth"
46
+ 4. Completa la información de la pantalla de consentimiento:
47
+ - Tipo de usuario: Público o Interno (según tu necesidad)
48
+ - Ingresa un nombre de aplicación
49
+ - Agrega direcciones de correo electrónico de desarrolladores
50
+ - Ingresa un dominio de aplicación (si aplica)
51
+ 5. Guarda la configuración de consentimiento
52
+
53
+ ### Paso 4: Configurar las credenciales
54
+
55
+ 1. De vuelta en la página de credenciales, haz clic en "Crear credenciales" > "ID de cliente OAuth 2.0"
56
+ 2. Selecciona "Aplicación web" como tipo de aplicación
57
+ 3. Ingresa un nombre para las credenciales
58
+ 4. En "URI de redirección autorizados", agrega las siguientes URLs:
59
+ - `http://localhost:8093/auth/callback` (ajusta el puerto según tu configuración)
60
+ - `http://localhost:3000/auth/callback` (si usas otro puerto)
61
+ - Cualquier otra URL de callback que vayas a usar
62
+ 5. Haz clic en "Crear"
63
+ 6. Guarda el "ID de cliente" y el "Secreto de cliente" que se mostrarán
64
+
65
+ ## Configuración del Framework API SDK
66
+
67
+ ### Paso 1: Instalar el Framework API SDK
68
+
69
+ ```bash
70
+ npm install apisdk
71
+ ```
72
+
73
+ ### Paso 2: Configurar variables de entorno
74
+
75
+ Crea un archivo `.env` en la raíz de tu proyecto:
76
+
77
+ ```env
78
+ OAUTH_CLIENT_ID=tu_client_id_aqui
79
+ OAUTH_CLIENT_SECRET=tu_client_secret_aqui
80
+ OAUTH_CALLBACK_URL=http://localhost:8093/auth/callback
81
+ ```
82
+
83
+ ### Paso 3: Importar los componentes necesarios
84
+
85
+ ```javascript
86
+ const {
87
+ APIServer,
88
+ Authenticator,
89
+ RouteLoader,
90
+ Logger,
91
+ TokenManager
92
+ } = require('apisdk');
93
+ ```
94
+
95
+ ## Implementación del Flujo OAuth 2.0
96
+
97
+ ### Paso 1: Configurar el servidor y autenticador
98
+
99
+ ```javascript
100
+ const server = new APIServer({
101
+ port: 8093,
102
+ host: 'localhost'
103
+ });
104
+
105
+ const authenticator = new Authenticator({ logger });
106
+
107
+ // Registrar la estrategia OAuth2
108
+ authenticator.use('google-oauth', authenticator.oauth2Strategy({
109
+ clientId: process.env.OAUTH_CLIENT_ID,
110
+ clientSecret: process.env.OAUTH_CLIENT_SECRET,
111
+ callbackURL: process.env.OAUTH_CALLBACK_URL,
112
+ authorizationURL: 'https://accounts.google.com/o/oauth2/v2/auth',
113
+ tokenURL: 'https://oauth2.googleapis.com/token'
114
+ }));
115
+
116
+ // Agregar autenticador al servidor
117
+ server.authenticator = authenticator;
118
+ ```
119
+
120
+ ### Paso 2: Crear el endpoint para iniciar OAuth
121
+
122
+ ```javascript
123
+ // Ruta para iniciar el flujo OAuth
124
+ router.get('/auth/google', (req, res) => {
125
+ // El framework maneja la redirección a Google
126
+ const authMiddleware = authenticator.authenticate('google-oauth');
127
+ authMiddleware(req, res, () => {});
128
+ });
129
+ ```
130
+
131
+ ### Paso 3: Crear el endpoint de callback
132
+
133
+ ```javascript
134
+ // Ruta para manejar el callback de OAuth
135
+ router.get('/auth/callback', async (req, res) => {
136
+ try {
137
+ // El framework maneja la autenticación y el intercambio de código por token
138
+ const authMiddleware = authenticator.authenticate('google-oauth', {
139
+ failureRedirect: '/login'
140
+ });
141
+
142
+ // Ejecutar middleware de autenticación
143
+ authMiddleware(req, res, async () => {
144
+ // Si llegamos aquí, la autenticación fue exitosa
145
+ if (req.user) {
146
+ // Generar token JWT para el usuario autenticado
147
+ const token = jwt.sign({
148
+ userId: req.user.id,
149
+ email: req.user.email,
150
+ name: req.user.name
151
+ }, process.env.JWT_SECRET);
152
+
153
+ // Redirigir con token o mostrar página de éxito
154
+ res.writeHead(302, { 'Location': `/dashboard?token=${token}` });
155
+ res.end();
156
+ } else {
157
+ res.writeHead(401, { 'Content-Type': 'application/json' });
158
+ res.end(JSON.stringify({ error: 'Autenticación fallida' }));
159
+ }
160
+ });
161
+ } catch (error) {
162
+ console.error('Error en callback OAuth:', error);
163
+ res.writeHead(500, { 'Content-Type': 'application/json' });
164
+ res.end(JSON.stringify({ error: 'Error interno del servidor' }));
165
+ }
166
+ });
167
+ ```
168
+
169
+ ## Manejo de Tokens
170
+
171
+ ### Paso 1: Configurar TokenManager
172
+
173
+ ```javascript
174
+ const tokenManager = new TokenManager({
175
+ storage: 'memory' // Opciones: 'memory', 'json', 'database'
176
+ });
177
+ ```
178
+
179
+ ### Paso 2: Generar tokens JWT
180
+
181
+ ```javascript
182
+ // Generar token JWT después de autenticación exitosa
183
+ const generateToken = (userData) => {
184
+ return jwt.sign(
185
+ {
186
+ userId: userData.id,
187
+ email: userData.email,
188
+ name: userData.name,
189
+ provider: 'google'
190
+ },
191
+ process.env.JWT_SECRET,
192
+ { expiresIn: '1h' }
193
+ );
194
+ };
195
+ ```
196
+
197
+ ### Paso 3: Validar tokens
198
+
199
+ ```javascript
200
+ // Middleware para validar tokens JWT
201
+ const validateToken = (req, res, next) => {
202
+ const authHeader = req.headers.authorization;
203
+ const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN
204
+
205
+ if (!token) {
206
+ res.writeHead(401, { 'Content-Type': 'application/json' });
207
+ res.end(JSON.stringify({ error: 'Token no proporcionado' }));
208
+ return;
209
+ }
210
+
211
+ jwt.verify(token, process.env.JWT_SECRET, (err, decoded) => {
212
+ if (err) {
213
+ res.writeHead(403, { 'Content-Type': 'application/json' });
214
+ res.end(JSON.stringify({ error: 'Token inválido' }));
215
+ return;
216
+ }
217
+
218
+ req.user = decoded;
219
+ next();
220
+ });
221
+ };
222
+ ```
223
+
224
+ ## Protección de Endpoints
225
+
226
+ ### Paso 1: Proteger rutas individuales
227
+
228
+ ```javascript
229
+ // Proteger una ruta específica
230
+ router.get('/profile', validateToken, (req, res) => {
231
+ res.writeHead(200, { 'Content-Type': 'application/json' });
232
+ res.end(JSON.stringify({
233
+ user: req.user,
234
+ message: 'Perfil de usuario protegido'
235
+ }));
236
+ });
237
+ ```
238
+
239
+ ### Paso 2: Proteger rutas usando el framework
240
+
241
+ ```javascript
242
+ // Usar la estrategia JWT del framework
243
+ authenticator.use('jwt-auth', (req, options = {}) => {
244
+ const authHeader = req.headers.authorization;
245
+ const token = authHeader && authHeader.split(' ')[1];
246
+
247
+ if (!token) return false;
248
+
249
+ try {
250
+ const decoded = jwt.verify(token, process.env.JWT_SECRET);
251
+ req.user = decoded;
252
+ return true;
253
+ } catch (error) {
254
+ return false;
255
+ }
256
+ });
257
+
258
+ // Proteger ruta con autenticación JWT
259
+ router.get('/protected', authenticator.authenticate('jwt-auth'), (req, res) => {
260
+ res.writeHead(200, { 'Content-Type': 'application/json' });
261
+ res.end(JSON.stringify({ message: 'Contenido protegido', user: req.user }));
262
+ });
263
+ ```
264
+
265
+ ## Consideraciones de Seguridad
266
+
267
+ ### 1. Almacenamiento de credenciales
268
+
269
+ - Nunca almacenes credenciales en el código fuente
270
+ - Usa variables de entorno o servicios de gestión de secretos
271
+ - Rotar periódicamente los secrets
272
+
273
+ ### 2. Validación de tokens
274
+
275
+ - Siempre valida tokens antes de conceder acceso
276
+ - Implementa expiración de tokens
277
+ - Considera usar refresh tokens para largas sesiones
278
+
279
+ ### 3. Configuración de Google
280
+
281
+ - Limita las URLs de redirección a solo las que necesitas
282
+ - Usa HTTPS en producción
283
+ - Monitorea el uso de tus credenciales
284
+
285
+ ### 4. Manejo de errores
286
+
287
+ - No reveles información sensible en mensajes de error
288
+ - Implementa logging adecuado para auditoría
289
+ - Maneja correctamente los casos de fallo de autenticación
290
+
291
+ ## Depuración y Troubleshooting
292
+
293
+ ### Problemas comunes y soluciones
294
+
295
+ #### 1. Error: "redirect_uri_mismatch"
296
+ - **Causa**: La URL de redirección no coincide con las registradas en Google Cloud Console
297
+ - **Solución**: Verifica que la URL en tu código coincida exactamente con las registradas
298
+
299
+ #### 2. Error: "invalid_client"
300
+ - **Causa**: Client ID o Client Secret incorrectos
301
+ - **Solución**: Verifica que las credenciales sean correctas y no estén truncadas
302
+
303
+ #### 3. Token expirado
304
+ - **Causa**: El access token ha expirado
305
+ - **Solución**: Implementa refresh tokens o solicita nuevo acceso
306
+
307
+ ### Herramientas de depuración
308
+
309
+ ```javascript
310
+ // Habilitar logging detallado
311
+ const logger = new Logger({ level: 'debug' });
312
+
313
+ // Verificar estado de autenticación
314
+ console.log('Usuario autenticado:', req.user);
315
+ console.log('Headers:', req.headers);
316
+ console.log('Query params:', req.query);
317
+ ```
318
+
319
+ ### Pruebas
320
+
321
+ ```javascript
322
+ // Prueba de endpoint protegido
323
+ const testProtectedEndpoint = async (token) => {
324
+ const response = await fetch('http://localhost:8093/protected', {
325
+ headers: {
326
+ 'Authorization': `Bearer ${token}`
327
+ }
328
+ });
329
+
330
+ const data = await response.json();
331
+ console.log('Respuesta del endpoint protegido:', data);
332
+ };
333
+ ```
334
+
335
+ ## Ejemplo Completo
336
+
337
+ Aquí tienes un ejemplo completo de implementación:
338
+
339
+ ```javascript
340
+ const {
341
+ APIServer,
342
+ Authenticator,
343
+ Router,
344
+ Logger
345
+ } = require('apisdk');
346
+
347
+ const jwt = require('jsonwebtoken');
348
+
349
+ async function startServer() {
350
+ const server = new APIServer({
351
+ port: 8093,
352
+ host: 'localhost'
353
+ });
354
+
355
+ const logger = new Logger({ level: 'info' });
356
+ const router = new Router();
357
+ const authenticator = new Authenticator({ logger });
358
+
359
+ // Configurar estrategia OAuth2
360
+ authenticator.use('google-oauth', authenticator.oauth2Strategy({
361
+ clientId: process.env.OAUTH_CLIENT_ID,
362
+ clientSecret: process.env.OAUTH_CLIENT_SECRET,
363
+ callbackURL: process.env.OAUTH_CALLBACK_URL,
364
+ }));
365
+
366
+ // Agregar autenticador al servidor
367
+ server.authenticator = authenticator;
368
+
369
+ // Ruta para iniciar OAuth
370
+ router.get('/auth/google', (req, res) => {
371
+ authenticator.authenticate('google-oauth')(req, res, () => {});
372
+ });
373
+
374
+ // Ruta de callback
375
+ router.get('/auth/callback', (req, res) => {
376
+ authenticator.authenticate('google-oauth', {
377
+ successRedirect: '/dashboard',
378
+ failureRedirect: '/login'
379
+ })(req, res, () => {});
380
+ });
381
+
382
+ // Ruta protegida
383
+ router.get('/dashboard', (req, res) => {
384
+ if (req.user) {
385
+ res.writeHead(200, { 'Content-Type': 'application/json' });
386
+ res.end(JSON.stringify({ message: 'Bienvenido al dashboard', user: req.user }));
387
+ } else {
388
+ res.writeHead(401, { 'Content-Type': 'application/json' });
389
+ res.end(JSON.stringify({ error: 'No autorizado' }));
390
+ }
391
+ });
392
+
393
+ // Agregar rutas al servidor
394
+ for (const route of router.getRoutes()) {
395
+ server.addRoute(route.method, route.path, route.handler);
396
+ }
397
+
398
+ server.start();
399
+ logger.info('Servidor iniciado en http://localhost:8093');
400
+ }
401
+
402
+ startServer();
403
+ ```
404
+
405
+ Este manual proporciona una guía completa para implementar OAuth 2.0 con Google usando el Framework API SDK, desde la configuración inicial hasta la implementación completa y consideraciones de seguridad.