jwt_auth_cognito 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.
data/README.md ADDED
@@ -0,0 +1,384 @@
1
+ # JWT Auth Cognito
2
+
3
+ Una gema Ruby para validar tokens JWT de AWS Cognito de forma offline con funcionalidad de blacklist basada en Redis.
4
+
5
+ ## Características
6
+
7
+ - **Validación JWT Offline**: Valida tokens JWT de Cognito sin llamar a las APIs de AWS
8
+ - **Soporte JWKS**: Recuperación automática y cache de claves públicas desde el endpoint JWKS de Cognito
9
+ - **Blacklist de Tokens**: Gestión de revocación y blacklist de tokens basada en Redis con soporte TLS completo
10
+ - **Configuración Flexible**: Soporte para modos de validación seguro (producción) y básico (desarrollo)
11
+ - **Gestión de Tokens de Usuario**: Rastrear e invalidar todos los tokens de un usuario específico
12
+ - **Múltiples Tipos de Token**: Soporte para access tokens e ID tokens
13
+ - **Manejo Integral de Errores**: Degradación elegante cuando Redis no está disponible
14
+ - **Soporte TLS Avanzado**: Configuración completa de TLS para Redis con certificados CA
15
+
16
+ ## Instalación
17
+
18
+ Agrega esta línea al Gemfile de tu aplicación:
19
+
20
+ ```ruby
21
+ gem 'jwt_auth_cognito'
22
+ ```
23
+
24
+ Y luego ejecuta:
25
+
26
+ $ bundle install
27
+
28
+ O instálala directamente:
29
+
30
+ $ gem install jwt_auth_cognito
31
+
32
+ ## Configuración
33
+
34
+ Configura la gema en un inicializador (ej. `config/initializers/jwt_auth_cognito.rb`):
35
+
36
+ ```ruby
37
+ JwtAuthCognito.configure do |config|
38
+ # Requerido: Configuración de AWS Cognito
39
+ config.cognito_user_pool_id = 'us-east-1_abcdef123'
40
+ config.cognito_region = 'us-east-1'
41
+ config.cognito_client_id = 'tu-client-id' # Opcional, para validación de audiencia
42
+ config.cognito_client_secret = 'tu-client-secret' # Opcional, para mayor seguridad
43
+
44
+ # Requerido: Configuración de Redis para blacklisting
45
+ config.redis_host = 'localhost'
46
+ config.redis_port = 6379
47
+ config.redis_password = 'tu-password-redis' # Opcional
48
+ config.redis_db = 0
49
+
50
+ # Configuración TLS para Redis (Producción)
51
+ config.redis_ssl = true
52
+ config.redis_ca_cert_path = '/ruta/a/certificados'
53
+ config.redis_ca_cert_name = 'redis-ca.crt'
54
+ config.redis_tls_min_version = 'TLSv1.2'
55
+ config.redis_tls_max_version = 'TLSv1.3'
56
+ config.redis_verify_mode = 'peer'
57
+
58
+ # Opcional: Configuraciones de cache y validación
59
+ config.jwks_cache_ttl = 3600 # 1 hora
60
+ config.validation_mode = :secure # :secure o :basic
61
+ end
62
+ ```
63
+
64
+ ### Variables de Entorno
65
+
66
+ La gema soporta configuración mediante variables de entorno:
67
+
68
+ ```bash
69
+ # Configuración de Cognito
70
+ COGNITO_USER_POOL_ID=us-east-1_abcdef123
71
+ COGNITO_REGION=us-east-1
72
+ COGNITO_CLIENT_ID=tu-client-id
73
+ COGNITO_CLIENT_SECRET=tu-client-secret
74
+
75
+ # Configuración de Redis
76
+ REDIS_HOST=localhost
77
+ REDIS_PORT=6379
78
+ REDIS_PASSWORD=tu-password
79
+ REDIS_DB=0
80
+ REDIS_TLS=true
81
+
82
+ # Configuración TLS de Redis
83
+ REDIS_CA_CERT_PATH=/ruta/a/certificados
84
+ REDIS_CA_CERT_NAME=redis-ca.crt
85
+ REDIS_TLS_MIN_VERSION=TLSv1.2
86
+ REDIS_TLS_MAX_VERSION=TLSv1.3
87
+ REDIS_VERIFY_MODE=peer
88
+
89
+ # Configuración de cache
90
+ JWKS_CACHE_TTL=3600
91
+ ```
92
+
93
+ ## Uso
94
+
95
+ ### Validación Básica de Tokens
96
+
97
+ ```ruby
98
+ validator = JwtAuthCognito::JwtValidator.new
99
+
100
+ # Validar cualquier token JWT
101
+ result = validator.validate_token(jwt_token)
102
+
103
+ if result[:valid]
104
+ puts "¡Token válido!"
105
+ puts "ID de Usuario: #{result[:sub]}"
106
+ puts "Nombre de Usuario: #{result[:username]}"
107
+ puts "Tipo de Token: #{result[:token_use]}"
108
+ else
109
+ puts "Token inválido: #{result[:error]}"
110
+ end
111
+ ```
112
+
113
+ ### Validar Tipos Específicos de Token
114
+
115
+ ```ruby
116
+ # Validar específicamente access token
117
+ result = validator.validate_access_token(jwt_token)
118
+
119
+ # Validar específicamente ID token
120
+ result = validator.validate_id_token(jwt_token)
121
+ ```
122
+
123
+ ### Opciones Avanzadas de Validación
124
+
125
+ ```ruby
126
+ # Validar con requisitos personalizados
127
+ result = validator.validate_token(jwt_token, {
128
+ user_id: 'id-usuario-esperado',
129
+ client_id: 'client-id-esperado',
130
+ token_use: 'access',
131
+ required_scopes: ['read', 'write']
132
+ })
133
+ ```
134
+
135
+ ### Blacklist de Tokens
136
+
137
+ ```ruby
138
+ # Revocar un token específico
139
+ validator.revoke_token(jwt_token, user_id: 'usuario-123')
140
+
141
+ # Revocar todos los tokens de un usuario
142
+ validator.revoke_user_tokens('usuario-123')
143
+
144
+ # Verificar si un token está en blacklist
145
+ blacklisted = validator.validate_token(jwt_token)
146
+ # Retornará { valid: false, error: "Token has been revoked" }
147
+ ```
148
+
149
+ ### Validación en Lote
150
+
151
+ ```ruby
152
+ tokens = [token1, token2, token3]
153
+ results = validator.validate_multiple_tokens(tokens)
154
+
155
+ results.each_with_index do |result, index|
156
+ puts "Token #{index + 1}: #{result[:valid] ? 'Válido' : result[:error]}"
157
+ end
158
+ ```
159
+
160
+ ### Métodos Utilitarios
161
+
162
+ ```ruby
163
+ # Extraer token del header Authorization
164
+ token = validator.extract_token_from_header(request.headers['Authorization'])
165
+
166
+ # Obtener información del token
167
+ info = validator.get_token_info(token)
168
+ puts "Usuario: #{info[:username]}"
169
+ puts "Expira en: #{info[:expires_at]}"
170
+ puts "Tiene client secret: #{info[:has_client_secret]}"
171
+
172
+ # Verificar expiración
173
+ expired = validator.is_token_expired?(token)
174
+
175
+ # Obtener tiempo hasta expiración
176
+ seconds_to_expiry = validator.get_time_to_expiry(token)
177
+
178
+ # Calcular secret hash (para operaciones de Cognito)
179
+ # Útil si necesitas hacer operaciones directas con Cognito SDK
180
+ secret_hash = validator.calculate_secret_hash('username_or_email')
181
+ ```
182
+
183
+ ### Uso Directo de Servicios
184
+
185
+ ```ruby
186
+ # Usar servicios directamente para mayor control
187
+ blacklist_service = JwtAuthCognito::TokenBlacklistService.new
188
+ jwks_service = JwtAuthCognito::JwksService.new
189
+
190
+ # Agregar token a blacklist con TTL personalizado
191
+ blacklist_service.add_to_blacklist(token, user_id: 'usuario-123')
192
+
193
+ # Validar con JWKS
194
+ result = jwks_service.validate_token_with_jwks(token)
195
+ ```
196
+
197
+ ## Modos de Validación
198
+
199
+ ### Modo Seguro (Producción)
200
+ - Validación completa de firma JWKS
201
+ - Recuperación automática y cache de claves públicas
202
+ - Validación completa de claims
203
+ - Recomendado para entornos de producción
204
+
205
+ ### Modo Básico (Desarrollo)
206
+ - Solo validación de estructura del token
207
+ - Sin verificación de firma
208
+ - Validación más rápida para desarrollo/testing
209
+ - **NO recomendado para producción**
210
+
211
+ ```ruby
212
+ # Configurar modo de validación
213
+ JwtAuthCognito.configure do |config|
214
+ config.validation_mode = :basic # Para desarrollo
215
+ config.validation_mode = :secure # Para producción
216
+ end
217
+ ```
218
+
219
+ ## Manejo de Errores
220
+
221
+ La gema proporciona tipos de error específicos:
222
+
223
+ - `JwtAuthCognito::ValidationError`: Fallas de validación de tokens
224
+ - `JwtAuthCognito::TokenExpiredError`: Token expirado
225
+ - `JwtAuthCognito::TokenRevokedError`: Token revocado
226
+ - `JwtAuthCognito::BlacklistError`: Fallas en operaciones de Redis/blacklist
227
+ - `JwtAuthCognito::ConfigurationError`: Problemas de configuración
228
+ - `JwtAuthCognito::JWKSError`: Errores de JWKS
229
+ - `JwtAuthCognito::RedisConnectionError`: Problemas de conexión a Redis
230
+
231
+ ```ruby
232
+ begin
233
+ result = validator.validate_token(token)
234
+ rescue JwtAuthCognito::TokenExpiredError => e
235
+ puts "Token expirado: #{e.message}"
236
+ rescue JwtAuthCognito::BlacklistError => e
237
+ puts "Error de blacklist: #{e.message}"
238
+ end
239
+ ```
240
+
241
+ ## Integración con Rails
242
+
243
+ ### Ejemplo de Middleware
244
+
245
+ ```ruby
246
+ class JwtAuthenticationMiddleware
247
+ def initialize(app)
248
+ @app = app
249
+ @validator = JwtAuthCognito::JwtValidator.new
250
+ end
251
+
252
+ def call(env)
253
+ request = Rack::Request.new(env)
254
+ token = @validator.extract_token_from_header(request.get_header('HTTP_AUTHORIZATION'))
255
+
256
+ if token
257
+ result = @validator.validate_access_token(token)
258
+ if result[:valid]
259
+ env['current_user_id'] = result[:sub]
260
+ env['current_username'] = result[:username]
261
+ else
262
+ return unauthorized_response(result[:error])
263
+ end
264
+ end
265
+
266
+ @app.call(env)
267
+ end
268
+
269
+ private
270
+
271
+ def unauthorized_response(error)
272
+ [401, { 'Content-Type' => 'application/json' },
273
+ [{ error: 'No Autorizado', message: error }.to_json]]
274
+ end
275
+ end
276
+ ```
277
+
278
+ ### Helper para Controladores
279
+
280
+ ```ruby
281
+ module JwtAuthHelper
282
+ extend ActiveSupport::Concern
283
+
284
+ included do
285
+ before_action :authenticate_jwt_token!
286
+ end
287
+
288
+ private
289
+
290
+ def authenticate_jwt_token!
291
+ token = jwt_validator.extract_token_from_header(request.headers['Authorization'])
292
+ return render_unauthorized('Token faltante') unless token
293
+
294
+ result = jwt_validator.validate_access_token(token)
295
+
296
+ if result[:valid]
297
+ @current_user_id = result[:sub]
298
+ @current_username = result[:username]
299
+ else
300
+ render_unauthorized(result[:error])
301
+ end
302
+ end
303
+
304
+ def jwt_validator
305
+ @jwt_validator ||= JwtAuthCognito::JwtValidator.new
306
+ end
307
+
308
+ def render_unauthorized(message)
309
+ render json: { error: 'No Autorizado', message: message }, status: :unauthorized
310
+ end
311
+ end
312
+ ```
313
+
314
+ ### Integración con Llegando-Neo
315
+
316
+ ```ruby
317
+ # En config/initializers/jwt_auth_cognito.rb
318
+ JwtAuthCognito.configure do |config|
319
+ # Reutilizar configuración existente de Redis
320
+ redis_config = Rails.application.config_for(:redis)
321
+ config.redis_host = redis_config[:host]
322
+ config.redis_port = redis_config[:port]
323
+ config.redis_password = redis_config[:password]
324
+ config.redis_ssl = redis_config[:ssl]
325
+
326
+ # Configuración de Cognito desde secrets
327
+ config.cognito_user_pool_id = Rails.application.secrets.cognito_user_pool_id
328
+ config.cognito_region = Rails.application.secrets.cognito_region
329
+ config.cognito_client_id = Rails.application.secrets.cognito_client_id
330
+
331
+ config.validation_mode = Rails.env.production? ? :secure : :basic
332
+ end
333
+ ```
334
+
335
+ ## Compatibilidad
336
+
337
+ - **Ruby**: >= 2.7.0 (Compatible con llegando-neo Ruby 2.7.5)
338
+ - **Rails**: >= 5.0 (Compatible con llegando-neo Rails 5.2.6)
339
+ - **Redis**: >= 4.2.5 (Compatible con llegando-neo redis >= 4.2.5)
340
+
341
+ ## Desarrollo
342
+
343
+ Después de clonar el repositorio, ejecuta `bin/setup` para instalar dependencias. Luego, ejecuta `rake spec` para correr las pruebas. También puedes ejecutar `bin/console` para una consola interactiva que te permitirá experimentar.
344
+
345
+ Para instalar esta gema localmente, ejecuta `bundle exec rake install`. Para liberar una nueva versión, actualiza el número de versión en `version.rb`, y luego ejecuta `bundle exec rake release`.
346
+
347
+ ## Contribución
348
+
349
+ Los reportes de bugs y pull requests son bienvenidos en GitHub.
350
+
351
+ ## Licencia
352
+
353
+ La gema está disponible como código abierto bajo los términos de la [Licencia MIT](https://opensource.org/licenses/MIT).
354
+
355
+ ## Generación Automática de Configuración
356
+
357
+ ### Usando el generador de Rails
358
+
359
+ ```bash
360
+ # Generar configuración automáticamente
361
+ rails generate jwt_auth_cognito:install
362
+ ```
363
+
364
+ ### Usando tareas Rake
365
+
366
+ ```bash
367
+ # Instalar configuración
368
+ rake jwt_auth_cognito:install
369
+
370
+ # Ver configuración actual
371
+ rake jwt_auth_cognito:config
372
+
373
+ # Probar conexiones
374
+ rake jwt_auth_cognito:test_cognito
375
+ rake jwt_auth_cognito:test_redis
376
+
377
+ # Limpiar blacklist
378
+ rake jwt_auth_cognito:clear_blacklist
379
+ ```
380
+
381
+ Esto generará automáticamente:
382
+ - `config/initializers/jwt_auth_cognito.rb` - Archivo de configuración
383
+ - `.env.example` - Variables de entorno de ejemplo
384
+ - Configuración optimizada para tu proyecto Rails
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+ require "rubocop/rake_task"
6
+
7
+ RSpec::Core::RakeTask.new(:spec)
8
+ RuboCop::RakeTask.new
9
+
10
+ desc "Run tests"
11
+ task default: %i[spec rubocop]
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/jwt_auth_cognito/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "jwt_auth_cognito"
7
+ spec.version = JwtAuthCognito::VERSION
8
+ spec.authors = ["The Optimal"]
9
+ spec.email = ["contact@theoptimal.com"]
10
+
11
+ spec.summary = "Validación offline de JWT con AWS Cognito y blacklist Redis"
12
+ spec.description = "Gema Ruby para validar tokens JWT de AWS Cognito de forma offline con funcionalidad de blacklist basada en Redis y soporte TLS completo"
13
+ spec.homepage = "https://github.com/theoptimal/jwt-auth-cognito"
14
+ spec.license = "MIT"
15
+ spec.required_ruby_version = ">= 2.7.0"
16
+
17
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
18
+ spec.metadata["homepage_uri"] = spec.homepage
19
+ spec.metadata["source_code_uri"] = spec.homepage
20
+ spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/main/CHANGELOG.md"
21
+ spec.metadata["documentation_uri"] = "#{spec.homepage}/blob/main/README.md"
22
+ spec.metadata["bug_tracker_uri"] = "#{spec.homepage}/issues"
23
+
24
+ # Specify which files should be added to the gem when it is released.
25
+ spec.files = Dir.chdir(__dir__) do
26
+ files = Dir.glob("lib/**/*.{rb,rake,erb}") +
27
+ Dir.glob("*.{md,txt,yml}") +
28
+ ["Gemfile", "Rakefile", "jwt_auth_cognito.gemspec"]
29
+
30
+ # Add optional files if they exist
31
+ files << ".rspec" if File.exist?(".rspec")
32
+ files << ".rubocop.yml" if File.exist?(".rubocop.yml")
33
+
34
+ files
35
+ end
36
+ spec.bindir = "exe"
37
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
38
+ spec.require_paths = ["lib"]
39
+
40
+ # Dependencies - compatible with llegando-neo (Ruby 2.7.5, Rails 5.2.6)
41
+ spec.add_dependency "jwt", "~> 2.0"
42
+ spec.add_dependency "redis", ">= 4.2.5", "< 6.0" # Compatible with llegando-neo redis version
43
+ spec.add_dependency "openssl", ">= 2.1.0" # For TLS support
44
+ spec.add_dependency "json", "~> 2.0"
45
+
46
+ # Development dependencies
47
+ spec.add_development_dependency "rspec", "~> 3.0"
48
+ spec.add_development_dependency "bundler", ">= 1.17", "< 3.0"
49
+ spec.add_development_dependency "rake", "~> 13.0"
50
+ spec.add_development_dependency "rubocop", "~> 1.0"
51
+ spec.add_development_dependency "webmock", "~> 3.0"
52
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators'
4
+
5
+ module JwtAuthCognito
6
+ module Generators
7
+ class InstallGenerator < Rails::Generators::Base
8
+ desc "Genera el archivo de configuración inicial para jwt_auth_cognito"
9
+
10
+ source_root File.expand_path('templates', __dir__)
11
+
12
+ def create_initializer
13
+ say "Creando archivo de configuración jwt_auth_cognito..."
14
+ template 'jwt_auth_cognito.rb.erb', 'config/initializers/jwt_auth_cognito.rb'
15
+ say "✓ Archivo de configuración creado en config/initializers/jwt_auth_cognito.rb", :green
16
+ end
17
+
18
+ def create_env_example
19
+ if File.exist?('.env.example')
20
+ append_to_file '.env.example', env_variables
21
+ say "✓ Variables de entorno agregadas a .env.example", :green
22
+ else
23
+ create_file '.env.example', env_variables
24
+ say "✓ Archivo .env.example creado con variables de entorno", :green
25
+ end
26
+ end
27
+
28
+ def show_next_steps
29
+ say "\n" + "="*60, :blue
30
+ say "🎉 ¡Configuración de jwt_auth_cognito completada!", :green
31
+ say "="*60, :blue
32
+ say "\n📋 PRÓXIMOS PASOS:", :yellow
33
+ say "\n1. Configura las variables de entorno:", :cyan
34
+ say " - Copia .env.example a .env (si usas dotenv)"
35
+ say " - Configura las variables de AWS Cognito y Redis"
36
+
37
+ say "\n2. Variables de entorno requeridas:", :cyan
38
+ say " COGNITO_USER_POOL_ID=us-east-1_abcdef123"
39
+ say " COGNITO_REGION=us-east-1"
40
+ say " COGNITO_CLIENT_ID=tu-client-id"
41
+
42
+ say "\n3. Variables de entorno opcionales:", :cyan
43
+ say " COGNITO_CLIENT_SECRET=tu-client-secret (para mayor seguridad)"
44
+ say " REDIS_TLS=true (para Redis con TLS)"
45
+ say " REDIS_CA_CERT_PATH=/ruta/a/certificados"
46
+
47
+ say "\n4. Reinicia tu aplicación Rails", :cyan
48
+
49
+ say "\n📖 Documentación completa:", :yellow
50
+ say " Revisa el README.md de la gema para ejemplos de uso"
51
+ say "\n" + "="*60, :blue
52
+ end
53
+
54
+ private
55
+
56
+ def env_variables
57
+ <<~ENV_VARS
58
+
59
+ # JWT Auth Cognito - Configuración
60
+ COGNITO_USER_POOL_ID=us-east-1_tu_user_pool_id
61
+ COGNITO_REGION=us-east-1
62
+ COGNITO_CLIENT_ID=tu_cognito_client_id
63
+ COGNITO_CLIENT_SECRET=tu_cognito_client_secret
64
+
65
+ # Redis para blacklist de tokens
66
+ REDIS_HOST=localhost
67
+ REDIS_PORT=6379
68
+ REDIS_PASSWORD=tu_redis_password
69
+ REDIS_DB=0
70
+ REDIS_TLS=false
71
+
72
+ # Redis TLS (para producción)
73
+ REDIS_CA_CERT_PATH=/ruta/a/certificados
74
+ REDIS_CA_CERT_NAME=redis-ca.crt
75
+ REDIS_TLS_MIN_VERSION=TLSv1.2
76
+ REDIS_TLS_MAX_VERSION=TLSv1.3
77
+
78
+ # Configuración adicional
79
+ JWKS_CACHE_TTL=3600
80
+ ENV_VARS
81
+ end
82
+
83
+ def rails_env_production?
84
+ defined?(Rails) && Rails.env.production?
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,129 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Configuración de JWT Auth Cognito
4
+ # Generado automáticamente - puedes modificar según tus necesidades
5
+
6
+ JwtAuthCognito.configure do |config|
7
+ # =============================================================================
8
+ # CONFIGURACIÓN DE AWS COGNITO
9
+ # =============================================================================
10
+
11
+ # User Pool ID de tu Cognito (requerido)
12
+ config.cognito_user_pool_id = ENV['COGNITO_USER_POOL_ID']
13
+
14
+ # Región de AWS donde está tu Cognito (requerido)
15
+ config.cognito_region = ENV['COGNITO_REGION'] || ENV['AWS_REGION'] || 'us-east-1'
16
+
17
+ # Client ID de tu aplicación en Cognito (requerido para validación de audiencia)
18
+ config.cognito_client_id = ENV['COGNITO_CLIENT_ID']
19
+
20
+ # Client Secret de tu aplicación en Cognito (opcional, para mayor seguridad)
21
+ # Si tu User Pool App Client está configurado con client secret, esto es requerido
22
+ config.cognito_client_secret = ENV['COGNITO_CLIENT_SECRET']
23
+
24
+ # =============================================================================
25
+ # CONFIGURACIÓN DE REDIS (para blacklist de tokens)
26
+ # =============================================================================
27
+
28
+ <% if defined?(Rails) && File.exist?(Rails.root.join('config', 'redis.yml')) -%>
29
+ # Integración con configuración existente de Redis
30
+ begin
31
+ redis_config = Rails.application.config_for(:redis)
32
+ config.redis_host = redis_config[:host] || ENV['REDIS_HOST'] || 'localhost'
33
+ config.redis_port = redis_config[:port] || ENV['REDIS_PORT']&.to_i || 6379
34
+ config.redis_password = redis_config[:password] || ENV['REDIS_PASSWORD']
35
+ config.redis_db = redis_config[:db] || ENV['REDIS_DB']&.to_i || 0
36
+ config.redis_ssl = redis_config[:ssl] || ENV['REDIS_TLS'] == 'true'
37
+ rescue StandardError
38
+ # Fallback si config/redis.yml no existe o tiene problemas
39
+ <% end -%>
40
+ config.redis_host = ENV['REDIS_HOST'] || 'localhost'
41
+ config.redis_port = ENV['REDIS_PORT']&.to_i || 6379
42
+ config.redis_password = ENV['REDIS_PASSWORD']
43
+ config.redis_db = ENV['REDIS_DB']&.to_i || 0
44
+ config.redis_ssl = ENV['REDIS_TLS'] == 'true'
45
+ <% if defined?(Rails) && File.exist?(Rails.root.join('config', 'redis.yml')) -%>
46
+ end
47
+ <% end -%>
48
+
49
+ # Configuración de timeouts para Redis
50
+ config.redis_timeout = ENV['REDIS_TIMEOUT']&.to_i || 5
51
+ config.redis_connect_timeout = ENV['REDIS_CONNECT_TIMEOUT']&.to_i || 10
52
+ config.redis_read_timeout = ENV['REDIS_READ_TIMEOUT']&.to_i || 10
53
+
54
+ # =============================================================================
55
+ # CONFIGURACIÓN TLS PARA REDIS (PRODUCCIÓN)
56
+ # =============================================================================
57
+
58
+ # Configuración de certificados CA para Redis TLS
59
+ config.redis_ca_cert_path = ENV['REDIS_CA_CERT_PATH']
60
+ config.redis_ca_cert_name = ENV['REDIS_CA_CERT_NAME']
61
+
62
+ # Control de versiones TLS
63
+ config.redis_tls_min_version = ENV['REDIS_TLS_MIN_VERSION'] || 'TLSv1.2'
64
+ config.redis_tls_max_version = ENV['REDIS_TLS_MAX_VERSION'] || 'TLSv1.3'
65
+ config.redis_verify_mode = ENV['REDIS_VERIFY_MODE'] || 'peer'
66
+
67
+ # =============================================================================
68
+ # CONFIGURACIÓN DE VALIDACIÓN
69
+ # =============================================================================
70
+
71
+ # Modo de validación: :secure (producción) o :basic (desarrollo)
72
+ # - :secure: Validación completa con JWKS y verificación de firma
73
+ # - :basic: Validación básica sin verificación de firma (solo desarrollo)
74
+ <% if defined?(Rails) -%>
75
+ config.validation_mode = Rails.env.production? ? :secure : :basic
76
+ <% else -%>
77
+ config.validation_mode = ENV['RAILS_ENV'] == 'production' ? :secure : :basic
78
+ <% end -%>
79
+
80
+ # Tiempo de cache para claves JWKS (en segundos)
81
+ config.jwks_cache_ttl = ENV['JWKS_CACHE_TTL']&.to_i || 3600 # 1 hora
82
+ end
83
+
84
+ # =============================================================================
85
+ # CONFIGURACIÓN ADICIONAL (OPCIONAL)
86
+ # =============================================================================
87
+
88
+ # Ejemplo de middleware para proteger rutas API
89
+ # Descomenta y modifica según tus necesidades:
90
+ #
91
+ # class JwtCognitoMiddleware
92
+ # def initialize(app)
93
+ # @app = app
94
+ # @validator = JwtAuthCognito::JwtValidator.new
95
+ # end
96
+ #
97
+ # def call(env)
98
+ # request = Rack::Request.new(env)
99
+ #
100
+ # # Solo validar en rutas API que requieren autenticación
101
+ # if request.path.start_with?('/api/secure/')
102
+ # token = @validator.extract_token_from_header(request.get_header('HTTP_AUTHORIZATION'))
103
+ #
104
+ # if token
105
+ # result = @validator.validate_access_token(token)
106
+ # if result[:valid]
107
+ # env['current_user_id'] = result[:sub]
108
+ # env['current_username'] = result[:username]
109
+ # else
110
+ # return unauthorized_response(result[:error])
111
+ # end
112
+ # else
113
+ # return unauthorized_response('Token de autorización requerido')
114
+ # end
115
+ # end
116
+ #
117
+ # @app.call(env)
118
+ # end
119
+ #
120
+ # private
121
+ #
122
+ # def unauthorized_response(error)
123
+ # body = { error: 'No autorizado', message: error }.to_json
124
+ # [401, { 'Content-Type' => 'application/json' }, [body]]
125
+ # end
126
+ # end
127
+ #
128
+ # # Agregar el middleware a tu aplicación Rails:
129
+ # Rails.application.config.middleware.use JwtCognitoMiddleware