jwt_auth_cognito 1.0.0.pre.beta.2 → 1.0.0.pre.beta.4
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +7 -0
- data/CHANGELOG.md +13 -1
- data/CLAUDE.md +74 -43
- data/README.md +132 -11
- data/bitbucket-pipelines.yml +17 -15
- data/jwt_auth_cognito.gemspec +0 -2
- data/lib/jwt_auth_cognito/configuration.rb +3 -6
- data/lib/jwt_auth_cognito/jwt_validator.rb +8 -79
- data/lib/jwt_auth_cognito/redis_service.rb +11 -9
- data/lib/jwt_auth_cognito/version.rb +1 -1
- metadata +2 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 265f4f1001ed0adae7545f86aa2589b9d290581afec125118e9630a17bd6b66a
|
4
|
+
data.tar.gz: 506db504efbff37dd02a58aef7e500274d7fcdb87e65de0b121ff9abe6a40c8c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: df9ee430a4c8b03c30701f612ddb41630c0563b2476800426abc05ccc2de87376c1dab736233c19a6da544f34efdf9cf84e1d989414a9790e1552d2dbbd67db5
|
7
|
+
data.tar.gz: 9199048166b82dd476b88083a5b4272b391d792d4d8992d5ed8f04ebf9e85951a000f783be728ed8900e29afc9527038f6a6a0edb867d9cbe78a7ff20e52cab3
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
7
7
|
|
8
8
|
## [Unreleased]
|
9
9
|
|
10
|
+
## [1.0.0-beta.3] - 2025-01-16
|
11
|
+
|
12
|
+
### Fixed
|
13
|
+
|
14
|
+
- **System API Key Bypass**: Fixed appId validation to correctly bypass for system API keys
|
15
|
+
- System API keys now have transversal access to all applications as intended
|
16
|
+
- App API keys continue to be restricted to their specific application
|
17
|
+
- Uses existing `can_access_app?` method from `ApiKeyValidator` for consistent logic
|
18
|
+
- Maintains security while allowing system-level administrative access
|
19
|
+
|
20
|
+
## [1.0.0-beta.2] - 2025-01-16
|
21
|
+
|
10
22
|
### Improved
|
11
23
|
|
12
24
|
- **Documentation Enhancement**: Added Redis configuration documentation to main usage patterns
|
@@ -31,7 +43,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
31
43
|
- Extracción inteligente de detalles de error
|
32
44
|
- Códigos de error estandarizados
|
33
45
|
|
34
|
-
- **Validación Enriquecida**: Nuevo método `
|
46
|
+
- **Validación Enriquecida**: Nuevo método `validate_enriched`
|
35
47
|
- Validación de tokens con datos contextuales del usuario
|
36
48
|
- Recuperación automática de permisos, organizaciones y aplicaciones
|
37
49
|
- Degradación elegante si la recuperación de datos falla
|
data/CLAUDE.md
CHANGED
@@ -37,22 +37,16 @@ gem build jwt_auth_cognito.gemspec
|
|
37
37
|
bundle exec rake install
|
38
38
|
|
39
39
|
# Test gem packaging
|
40
|
-
gem contents jwt_auth_cognito-0.
|
41
|
-
|
42
|
-
# Version management (
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
#
|
48
|
-
|
49
|
-
|
50
|
-
rake release:stable # Stable release (requires confirmation)
|
51
|
-
|
52
|
-
# Direct publishing
|
53
|
-
rake publish:beta # Build and publish beta version
|
54
|
-
rake publish:rc # Build and publish RC version
|
55
|
-
rake publish:stable # Build and publish stable (requires confirmation)
|
40
|
+
gem contents jwt_auth_cognito-1.0.0-beta.4.gem
|
41
|
+
|
42
|
+
# Version management (Manual in version.rb file)
|
43
|
+
# Edit lib/jwt_auth_cognito/version.rb to update VERSION constant
|
44
|
+
# Example: VERSION = '1.0.0-beta.5'
|
45
|
+
|
46
|
+
# The CI/CD pipeline handles automatic deployment:
|
47
|
+
# - Beta releases: Automatic deployment when pushed to develop branch
|
48
|
+
# - RC releases: Automatic deployment when tagged with v*-rc.*
|
49
|
+
# - Stable releases: Manual deployment when tagged with v[0-9]*.*
|
56
50
|
```
|
57
51
|
|
58
52
|
### Configuration Generation
|
@@ -70,18 +64,19 @@ rake jwt_auth_cognito:test_cognito # Test Cognito connection
|
|
70
64
|
## Architecture Overview
|
71
65
|
|
72
66
|
### Core Components
|
73
|
-
- **JwtValidator**: Main validation orchestrator that coordinates JWKS validation, blacklist checking,
|
67
|
+
- **JwtValidator**: Main validation orchestrator that coordinates JWKS validation, blacklist checking, user data retrieval, and API key validation
|
74
68
|
- **JwksService**: Handles AWS Cognito JWKS fetching, caching, and signature validation
|
75
69
|
- **RedisService**: Low-level Redis operations with comprehensive TLS support and retry logic
|
76
70
|
- **TokenBlacklistService**: High-level token revocation and blacklist management
|
77
71
|
- **UserDataService**: User data retrieval from Redis with caching and auth-service compatibility
|
72
|
+
- **ApiKeyValidator**: API key validation with system and app-level access control
|
78
73
|
- **ErrorUtils**: Centralized error handling and categorization system
|
79
74
|
- **SSMService**: AWS Parameter Store integration for secure certificate management (auth-service compatible)
|
80
75
|
- **Configuration**: Centralized configuration with environment variable fallbacks
|
81
76
|
|
82
77
|
### Key Design Patterns
|
83
78
|
|
84
|
-
**Service Layer Architecture**: Each major functionality (JWT validation, JWKS handling, Redis operations, blacklisting, user data retrieval) is isolated into dedicated service classes that can be used independently or orchestrated through JwtValidator.
|
79
|
+
**Service Layer Architecture**: Each major functionality (JWT validation, JWKS handling, Redis operations, blacklisting, user data retrieval, API key validation) is isolated into dedicated service classes that can be used independently or orchestrated through JwtValidator.
|
85
80
|
|
86
81
|
**Configuration Management**: Dual configuration approach supporting both programmatic configuration and environment variables, with automatic fallback chain for maximum flexibility.
|
87
82
|
|
@@ -109,9 +104,9 @@ rake jwt_auth_cognito:test_cognito # Test Cognito connection
|
|
109
104
|
# 3. Environment variable
|
110
105
|
|
111
106
|
# SSM configuration (matching auth-service pattern)
|
112
|
-
config.
|
113
|
-
config.
|
114
|
-
# Results in SSM parameter: /
|
107
|
+
config.redis_ca_cert_path = "redis" # SSM path segment
|
108
|
+
config.redis_ca_cert_name = "ca-cert" # Certificate name
|
109
|
+
# Results in SSM parameter: /redis/ca-cert
|
115
110
|
|
116
111
|
# Automatic fallback to file system
|
117
112
|
config.redis_ca_cert_path = "/path/to/certs"
|
@@ -145,6 +140,12 @@ ENV['REDIS_CA_CERT'] = "-----BEGIN CERTIFICATE-----..."
|
|
145
140
|
- **Backward Compatibility**: All functionality works without client secret configuration
|
146
141
|
- **Security Integration**: Secret hash automatically included in blacklist operations when configured
|
147
142
|
|
143
|
+
### System API Key Support
|
144
|
+
- **System API Key Bypass**: API keys with scope 'system' can access any application (transversal access)
|
145
|
+
- **App API Key Restrictions**: API keys with scope 'app' are restricted to their specific application
|
146
|
+
- **Automatic Detection**: Uses existing `can_access_app?` method from `ApiKeyValidator` for consistent logic
|
147
|
+
- **Security Maintained**: Preserves security boundaries while enabling administrative functionality
|
148
|
+
|
148
149
|
## 🚀 Main Usage Pattern with Redis Connection
|
149
150
|
|
150
151
|
### ✨ Complete Setup with Redis Connection
|
@@ -169,18 +170,30 @@ validator = JwtAuthCognito.create_cognito_validator(
|
|
169
170
|
ca_cert_name: ENV['REDIS_CA_CERT_NAME'],
|
170
171
|
verify_mode: ENV['REDIS_VERIFY_MODE'] || 'peer'
|
171
172
|
},
|
172
|
-
|
173
|
+
enable_api_key_validation: true, # Enable API key validation
|
174
|
+
enable_user_data_retrieval: true # Enable user data enrichment
|
173
175
|
)
|
174
176
|
|
175
177
|
# Initialize Redis connection and services
|
176
178
|
validator.initialize!
|
177
179
|
|
178
180
|
# 🌟 Main validation method with complete functionality
|
179
|
-
result = validator.
|
181
|
+
result = validator.validate_enriched(token)
|
182
|
+
|
183
|
+
# Advanced usage with options
|
184
|
+
result = validator.validate_enriched(
|
185
|
+
token,
|
186
|
+
api_key, # Optional API key
|
187
|
+
{
|
188
|
+
force_secure: true, # Force JWKS validation
|
189
|
+
require_app_access: true # Verify app access
|
190
|
+
}
|
191
|
+
)
|
180
192
|
|
181
193
|
if result[:valid]
|
182
194
|
puts "✅ Valid token:"
|
183
195
|
puts "User: #{result[:sub]}"
|
196
|
+
puts "API Key: #{result[:api_key][:name]}" if result[:api_key]
|
184
197
|
puts "Permissions: #{result[:user_permissions]}"
|
185
198
|
puts "Organizations: #{result[:user_organizations]}"
|
186
199
|
puts "Applications: #{result[:applications]}"
|
@@ -215,9 +228,9 @@ REDIS_READ_TIMEOUT=10
|
|
215
228
|
|
216
229
|
### TLS/SSL Certificate Configuration
|
217
230
|
```bash
|
218
|
-
# AWS SSM Parameter Store (
|
219
|
-
|
220
|
-
|
231
|
+
# AWS SSM Parameter Store (auth-service compatibility)
|
232
|
+
REDIS_CA_CERT_PATH=redis # SSM path segment
|
233
|
+
REDIS_CA_CERT_NAME=ca-cert # SSM parameter name
|
221
234
|
|
222
235
|
# Local file system fallback
|
223
236
|
REDIS_CA_CERT_PATH=/path/to/certs
|
@@ -228,8 +241,8 @@ REDIS_CA_CERT="-----BEGIN CERTIFICATE-----..."
|
|
228
241
|
|
229
242
|
# TLS settings
|
230
243
|
REDIS_VERIFY_MODE=peer # 'peer' or 'none'
|
231
|
-
REDIS_TLS_MIN_VERSION=
|
232
|
-
REDIS_TLS_MAX_VERSION=
|
244
|
+
REDIS_TLS_MIN_VERSION=TLSv1_2
|
245
|
+
REDIS_TLS_MAX_VERSION=TLSv1_3
|
233
246
|
```
|
234
247
|
|
235
248
|
### AWS Configuration (for SSM)
|
@@ -240,15 +253,18 @@ AWS_SECRET_ACCESS_KEY=your-secret-key
|
|
240
253
|
# Or use IAM roles/instance profiles
|
241
254
|
```
|
242
255
|
|
243
|
-
###
|
256
|
+
### Feature Configuration
|
244
257
|
```bash
|
258
|
+
# API Key validation settings
|
259
|
+
ENABLE_API_KEY_VALIDATION=true # Enable API key validation functionality
|
260
|
+
|
245
261
|
# User data retrieval settings
|
246
|
-
ENABLE_USER_DATA_RETRIEVAL=true
|
262
|
+
ENABLE_USER_DATA_RETRIEVAL=true # Enable user data enrichment functionality
|
247
263
|
INCLUDE_APPLICATIONS=true
|
248
264
|
INCLUDE_ORGANIZATIONS=true
|
249
265
|
INCLUDE_ROLES=true
|
250
266
|
INCLUDE_EFFECTIVE_PERMISSIONS=false
|
251
|
-
USER_DATA_CACHE_TIMEOUT=300
|
267
|
+
USER_DATA_CACHE_TIMEOUT=300 # 5 minutes
|
252
268
|
```
|
253
269
|
|
254
270
|
### Caching and Performance
|
@@ -309,31 +325,46 @@ The gem uses Bitbucket Pipelines for automated deployment to RubyGems.org:
|
|
309
325
|
|
310
326
|
#### Pipeline Configuration
|
311
327
|
- **Beta releases** (`v*-beta.*`): Automatic deployment
|
312
|
-
- **RC releases** (`v*-rc.*`): Automatic deployment
|
328
|
+
- **RC releases** (`v*-rc.*`): Automatic deployment
|
313
329
|
- **Stable releases** (`v[0-9]*.*`): Manual deployment with confirmation
|
314
330
|
- **Testing**: Automated on all branches with comprehensive test suite
|
315
331
|
|
332
|
+
#### RubyGems Credentials Setup
|
333
|
+
The pipeline uses environment variable `RUBYGEMS_API_KEY` with correct YAML format:
|
334
|
+
```bash
|
335
|
+
# Pipeline creates credentials file with correct format:
|
336
|
+
printf ':rubygems_api_key: %s\n' "$RUBYGEMS_API_KEY" > ~/.gem/credentials
|
337
|
+
# Note: The colon prefix is required for valid YAML format
|
338
|
+
# Using printf to avoid YAML parsing issues with echo and colons
|
339
|
+
```
|
340
|
+
|
316
341
|
#### Deployment Commands
|
317
342
|
|
318
|
-
####
|
343
|
+
#### Version Management Process
|
344
|
+
|
345
|
+
**1. Update Version Number**
|
319
346
|
```bash
|
320
|
-
#
|
321
|
-
|
322
|
-
|
323
|
-
git push origin develop
|
324
|
-
# → Pipeline automatically creates and publishes beta version
|
347
|
+
# Edit the version file manually
|
348
|
+
vim lib/jwt_auth_cognito/version.rb
|
349
|
+
# Update VERSION constant: VERSION = '1.0.0-beta.5'
|
325
350
|
```
|
326
351
|
|
327
|
-
|
352
|
+
**2. Automatic Beta Deployment**
|
328
353
|
```bash
|
329
|
-
#
|
330
|
-
git
|
354
|
+
# Push to develop branch - automatic beta deployment
|
355
|
+
git add lib/jwt_auth_cognito/version.rb
|
356
|
+
git commit -m "bump: version 1.0.0-beta.5"
|
357
|
+
git push origin develop
|
358
|
+
# → Pipeline automatically publishes beta version to RubyGems
|
359
|
+
```
|
331
360
|
|
361
|
+
**3. Manual Tag Deployment (Alternative)**
|
362
|
+
```bash
|
332
363
|
# RC release
|
333
|
-
git tag
|
364
|
+
git tag v1.0.0-rc.1 && git push origin v1.0.0-rc.1
|
334
365
|
|
335
366
|
# Stable release
|
336
|
-
git tag
|
367
|
+
git tag v1.0.0 && git push origin v1.0.0
|
337
368
|
```
|
338
369
|
|
339
370
|
#### Helper Scripts
|
data/README.md
CHANGED
@@ -49,10 +49,10 @@ JwtAuthCognito.configure do |config|
|
|
49
49
|
config.redis_password = 'tu-password-redis' # Opcional
|
50
50
|
config.redis_db = 0
|
51
51
|
|
52
|
-
# Configuración TLS para Redis (Producción)
|
52
|
+
# Configuración TLS para Redis (Producción - compatible con auth-service)
|
53
53
|
config.redis_ssl = true
|
54
|
-
config.redis_ca_cert_path = '
|
55
|
-
config.redis_ca_cert_name = '
|
54
|
+
config.redis_ca_cert_path = 'redis' # AWS SSM path
|
55
|
+
config.redis_ca_cert_name = 'ca-cert' # AWS SSM parameter name
|
56
56
|
config.redis_tls_min_version = 'TLSv1.2'
|
57
57
|
config.redis_tls_max_version = 'TLSv1.3'
|
58
58
|
config.redis_verify_mode = 'peer'
|
@@ -60,6 +60,10 @@ JwtAuthCognito.configure do |config|
|
|
60
60
|
# Opcional: Configuraciones de cache y validación
|
61
61
|
config.jwks_cache_ttl = 3600 # 1 hora
|
62
62
|
config.validation_mode = :secure # :secure o :basic
|
63
|
+
|
64
|
+
# Opcional: Habilitar funcionalidades específicas
|
65
|
+
config.enable_api_key_validation = true # Validación de API keys
|
66
|
+
config.enable_user_data_retrieval = true # Enriquecimiento de datos de usuario
|
63
67
|
end
|
64
68
|
```
|
65
69
|
|
@@ -81,17 +85,30 @@ REDIS_PASSWORD=tu-password
|
|
81
85
|
REDIS_DB=0
|
82
86
|
REDIS_TLS=true
|
83
87
|
|
84
|
-
# Configuración TLS de Redis
|
85
|
-
REDIS_CA_CERT_PATH
|
86
|
-
REDIS_CA_CERT_NAME=
|
87
|
-
REDIS_TLS_MIN_VERSION=
|
88
|
-
REDIS_TLS_MAX_VERSION=
|
88
|
+
# Configuración TLS de Redis (compatible con auth-service)
|
89
|
+
REDIS_CA_CERT_PATH=redis # Para AWS SSM (path del parámetro)
|
90
|
+
REDIS_CA_CERT_NAME=ca-cert # Para AWS SSM (nombre del parámetro)
|
91
|
+
REDIS_TLS_MIN_VERSION=TLSv1_2
|
92
|
+
REDIS_TLS_MAX_VERSION=TLSv1_3
|
89
93
|
REDIS_VERIFY_MODE=peer
|
90
94
|
|
91
95
|
# Configuración de cache
|
92
96
|
JWKS_CACHE_TTL=3600
|
97
|
+
|
98
|
+
# Habilitar funcionalidades específicas
|
99
|
+
ENABLE_API_KEY_VALIDATION=true # Validación de API keys
|
100
|
+
ENABLE_USER_DATA_RETRIEVAL=true # Enriquecimiento de datos de usuario
|
93
101
|
```
|
94
102
|
|
103
|
+
### Opciones de Configuración Boolean
|
104
|
+
|
105
|
+
La gema soporta las siguientes opciones boolean para habilitar funcionalidades específicas:
|
106
|
+
|
107
|
+
- **`enable_api_key_validation`** - Habilita la validación de API keys para control de acceso a nivel de sistema y aplicación (default: false)
|
108
|
+
- **`enable_user_data_retrieval`** - Habilita el enriquecimiento de datos de usuario con permisos, organizaciones y aplicaciones (default: false)
|
109
|
+
|
110
|
+
Estas opciones permiten control granular sobre qué características están activas, optimizando el rendimiento habilitando solo la funcionalidad necesaria.
|
111
|
+
|
95
112
|
## Uso
|
96
113
|
|
97
114
|
### Validación Básica de Tokens
|
@@ -135,7 +152,7 @@ validator = JwtAuthCognito::JwtValidator.new
|
|
135
152
|
validator.initialize! # Inicializar servicios
|
136
153
|
|
137
154
|
# Validación enriquecida con datos de usuario desde Redis
|
138
|
-
result = validator.
|
155
|
+
result = validator.validate_enriched(jwt_token)
|
139
156
|
|
140
157
|
if result[:valid]
|
141
158
|
puts "Token válido!"
|
@@ -159,6 +176,109 @@ if result[:valid]
|
|
159
176
|
end
|
160
177
|
```
|
161
178
|
|
179
|
+
#### Opciones Avanzadas para validate_enriched
|
180
|
+
|
181
|
+
El método `validate_enriched` acepta múltiples parámetros para casos de uso específicos:
|
182
|
+
|
183
|
+
```ruby
|
184
|
+
# Sintaxis completa
|
185
|
+
result = validator.validate_enriched(token, api_key, options)
|
186
|
+
|
187
|
+
# 1. Solo token (caso más simple)
|
188
|
+
result = validator.validate_enriched(jwt_token)
|
189
|
+
|
190
|
+
# 2. Con API key
|
191
|
+
result = validator.validate_enriched(jwt_token, api_key)
|
192
|
+
|
193
|
+
# 3. Con opciones adicionales
|
194
|
+
result = validator.validate_enriched(jwt_token, nil, {
|
195
|
+
force_secure: true, # Forzar validación segura (JWKS)
|
196
|
+
require_app_access: true # Requerir acceso a aplicación específica
|
197
|
+
})
|
198
|
+
|
199
|
+
# 4. Con API key y opciones
|
200
|
+
result = validator.validate_enriched(jwt_token, api_key, {
|
201
|
+
force_secure: true,
|
202
|
+
require_app_access: true
|
203
|
+
})
|
204
|
+
|
205
|
+
# 5. Solo con opciones (sin API key)
|
206
|
+
result = validator.validate_enriched(jwt_token, nil, {
|
207
|
+
force_secure: false, # Usar modo básico de validación
|
208
|
+
require_app_access: false # No verificar acceso a aplicación
|
209
|
+
})
|
210
|
+
```
|
211
|
+
|
212
|
+
**Parámetros disponibles:**
|
213
|
+
|
214
|
+
- **`token`** (String): JWT token a validar
|
215
|
+
- **`api_key`** (String, opcional): API key para validación adicional
|
216
|
+
- **`options`** (Hash, opcional):
|
217
|
+
- `force_secure`: Forzar validación JWKS incluso en desarrollo
|
218
|
+
- `require_app_access`: Verificar que el usuario tenga acceso a la aplicación del API key
|
219
|
+
|
220
|
+
```ruby
|
221
|
+
# Ejemplo con todas las opciones
|
222
|
+
result = validator.validate_enriched(
|
223
|
+
jwt_token,
|
224
|
+
'api-key-64-hex-characters',
|
225
|
+
{
|
226
|
+
force_secure: true,
|
227
|
+
require_app_access: true
|
228
|
+
}
|
229
|
+
)
|
230
|
+
|
231
|
+
if result[:valid]
|
232
|
+
puts "✅ Validación completa exitosa"
|
233
|
+
puts "Usuario: #{result[:sub]}"
|
234
|
+
puts "API Key: #{result[:api_key][:name]}"
|
235
|
+
puts "Permisos: #{result[:user_permissions]}"
|
236
|
+
puts "Apps disponibles: #{result[:applications]&.map { |app| app['appId'] }}"
|
237
|
+
else
|
238
|
+
puts "❌ Error: #{result[:error]}"
|
239
|
+
end
|
240
|
+
```
|
241
|
+
|
242
|
+
### Validación con API Keys
|
243
|
+
|
244
|
+
Para usar validación de API keys, habilita la funcionalidad en la configuración:
|
245
|
+
|
246
|
+
```ruby
|
247
|
+
# Configurar con validación de API keys habilitada
|
248
|
+
JwtAuthCognito.configure do |config|
|
249
|
+
# ... configuración básica ...
|
250
|
+
config.enable_api_key_validation = true
|
251
|
+
end
|
252
|
+
|
253
|
+
validator = JwtAuthCognito::JwtValidator.new
|
254
|
+
validator.initialize!
|
255
|
+
|
256
|
+
# Validar token con API key opcional
|
257
|
+
api_key = 'api-key-64-hex-characters-1234567890abcdef1234567890abcdef12345678'
|
258
|
+
result = validator.validate(jwt_token, api_key: api_key)
|
259
|
+
|
260
|
+
if result[:valid]
|
261
|
+
puts "✅ Token y API key válidos"
|
262
|
+
puts "Usuario: #{result[:sub]}"
|
263
|
+
|
264
|
+
# Información del API key
|
265
|
+
if result[:api_key_data]
|
266
|
+
key_data = result[:api_key_data]
|
267
|
+
puts "API Key: #{key_data[:name]}"
|
268
|
+
puts "Scope: #{key_data[:scope]}"
|
269
|
+
puts "Permisos: #{key_data[:permissions].join(', ')}"
|
270
|
+
puts "App ID: #{key_data[:app_id]}" if key_data[:app_id]
|
271
|
+
end
|
272
|
+
else
|
273
|
+
puts "❌ Error: #{result[:error]}"
|
274
|
+
end
|
275
|
+
```
|
276
|
+
|
277
|
+
**Tipos de API Keys soportados:**
|
278
|
+
- **System API Keys** (`scope: 'system'`) - Acceso transversal a todas las aplicaciones
|
279
|
+
- **App API Keys** (`scope: 'app'`) - Acceso restringido a una aplicación específica
|
280
|
+
- **Client API Keys** (`scope: 'client'`) - Para aplicaciones cliente
|
281
|
+
|
162
282
|
### Factory Method para Configuración Simplificada (Nuevo v0.3.0)
|
163
283
|
|
164
284
|
```ruby
|
@@ -179,14 +299,15 @@ validator = JwtAuthCognito.create_cognito_validator(
|
|
179
299
|
ca_cert_path: ENV['REDIS_CA_CERT_PATH'],
|
180
300
|
ca_cert_name: ENV['REDIS_CA_CERT_NAME']
|
181
301
|
},
|
182
|
-
|
302
|
+
enable_api_key_validation: true, # Habilitar validación de API keys
|
303
|
+
enable_user_data_retrieval: true # Habilitar enriquecimiento de datos
|
183
304
|
)
|
184
305
|
|
185
306
|
# Inicializar conexiones (incluye Redis)
|
186
307
|
validator.initialize!
|
187
308
|
|
188
309
|
# Usar inmediatamente con validación enriquecida
|
189
|
-
result = validator.
|
310
|
+
result = validator.validate_enriched(token)
|
190
311
|
|
191
312
|
if result[:valid]
|
192
313
|
puts "✅ Token válido con datos enriquecidos:"
|
data/bitbucket-pipelines.yml
CHANGED
@@ -1,5 +1,10 @@
|
|
1
|
-
# Bitbucket Pipeline para jwt_auth_cognito Ruby Gem
|
1
|
+
# Bitbucket Pipeline para jwt_auth_cognito Ruby Gem
|
2
2
|
# Configuración CI/CD para RubyGems con Git Flow
|
3
|
+
#
|
4
|
+
# COMPORTAMIENTO:
|
5
|
+
# - Push a develop: Publica version definida en codigo sin crear tags
|
6
|
+
# - Tags creados por Git Flow: Activan pipelines específicos según tipo de version
|
7
|
+
# - No hay duplicación de deploys (develop no crea tags automáticos)
|
3
8
|
|
4
9
|
image: ruby:3.1
|
5
10
|
|
@@ -41,20 +46,17 @@ pipelines:
|
|
41
46
|
- bundle exec rspec
|
42
47
|
- echo "Ejecutando linting..."
|
43
48
|
- bundle exec rubocop
|
44
|
-
- echo "
|
45
|
-
- bundle exec rake version:beta
|
49
|
+
- echo "Usando version definida en codigo..."
|
46
50
|
- echo "Building gem..."
|
47
51
|
- gem build jwt_auth_cognito.gemspec
|
48
52
|
- echo "Configurando credenciales RubyGems..."
|
49
53
|
- mkdir -p ~/.gem
|
50
|
-
- '
|
54
|
+
- "printf ':rubygems_api_key: %s\\n' \"$RUBYGEMS_API_KEY\" > ~/.gem/credentials"
|
51
55
|
- chmod 0600 ~/.gem/credentials
|
52
56
|
- echo "Publicando version beta a RubyGems..."
|
53
57
|
- gem push *.gem
|
54
|
-
- echo "
|
55
|
-
-
|
56
|
-
- git config user.email "pipeline@bitbucket.org"
|
57
|
-
- NEW_VERSION=$(ruby -r './lib/jwt_auth_cognito/version' -e 'puts JwtAuthCognito::VERSION') && git tag "v$NEW_VERSION" && git push origin "v$NEW_VERSION" && echo "Beta v$NEW_VERSION publicada automaticamente"
|
58
|
+
- echo "Deploy de develop completado - Version beta publicada sin tag automatico"
|
59
|
+
- echo "Los tags se crearan automaticamente en releases usando Git Flow"
|
58
60
|
|
59
61
|
main:
|
60
62
|
- step:
|
@@ -93,7 +95,7 @@ pipelines:
|
|
93
95
|
- gem build jwt_auth_cognito.gemspec
|
94
96
|
- echo "Configurando credenciales RubyGems..."
|
95
97
|
- mkdir -p ~/.gem
|
96
|
-
- '
|
98
|
+
- "printf ':rubygems_api_key: %s\\n' \"$RUBYGEMS_API_KEY\" > ~/.gem/credentials"
|
97
99
|
- chmod 0600 ~/.gem/credentials
|
98
100
|
- echo "Publicando a RubyGems con tag beta..."
|
99
101
|
- gem push *.gem
|
@@ -116,7 +118,7 @@ pipelines:
|
|
116
118
|
- gem build jwt_auth_cognito.gemspec
|
117
119
|
- echo "Configurando credenciales RubyGems..."
|
118
120
|
- mkdir -p ~/.gem
|
119
|
-
- '
|
121
|
+
- "printf ':rubygems_api_key: %s\\n' \"$RUBYGEMS_API_KEY\" > ~/.gem/credentials"
|
120
122
|
- chmod 0600 ~/.gem/credentials
|
121
123
|
- echo "Publicando a RubyGems..."
|
122
124
|
- gem push *.gem
|
@@ -151,7 +153,7 @@ pipelines:
|
|
151
153
|
- echo "🚨 DEPLOY DE PRODUCCIÓN - Versión estable"
|
152
154
|
- echo "Configurando credenciales RubyGems..."
|
153
155
|
- mkdir -p ~/.gem
|
154
|
-
- '
|
156
|
+
- "printf ':rubygems_api_key: %s\\n' \"$RUBYGEMS_API_KEY\" > ~/.gem/credentials"
|
155
157
|
- chmod 0600 ~/.gem/credentials
|
156
158
|
- echo "Publicando version ESTABLE a RubyGems..."
|
157
159
|
- gem push *.gem
|
@@ -193,7 +195,7 @@ pipelines:
|
|
193
195
|
- gem build jwt_auth_cognito.gemspec
|
194
196
|
- echo "Configurando credenciales RubyGems..."
|
195
197
|
- mkdir -p ~/.gem
|
196
|
-
- '
|
198
|
+
- "printf ':rubygems_api_key: %s\\n' \"$RUBYGEMS_API_KEY\" > ~/.gem/credentials"
|
197
199
|
- chmod 0600 ~/.gem/credentials
|
198
200
|
- echo "📤 Desplegando a RubyGems..."
|
199
201
|
- gem push *.gem
|
@@ -216,7 +218,7 @@ pipelines:
|
|
216
218
|
- gem build jwt_auth_cognito.gemspec
|
217
219
|
- echo "Configurando credenciales RubyGems..."
|
218
220
|
- mkdir -p ~/.gem
|
219
|
-
- '
|
221
|
+
- "printf ':rubygems_api_key: %s\\n' \"$RUBYGEMS_API_KEY\" > ~/.gem/credentials"
|
220
222
|
- chmod 0600 ~/.gem/credentials
|
221
223
|
- echo "📤 Desplegando a RubyGems..."
|
222
224
|
- gem push *.gem
|
@@ -244,7 +246,7 @@ pipelines:
|
|
244
246
|
- gem build jwt_auth_cognito.gemspec
|
245
247
|
- echo "Configurando credenciales RubyGems..."
|
246
248
|
- mkdir -p ~/.gem
|
247
|
-
- '
|
249
|
+
- "printf ':rubygems_api_key: %s\\n' \"$RUBYGEMS_API_KEY\" > ~/.gem/credentials"
|
248
250
|
- chmod 0600 ~/.gem/credentials
|
249
251
|
- echo "📤 Desplegando versión ESTABLE a RubyGems..."
|
250
252
|
- gem push *.gem
|
@@ -270,4 +272,4 @@ pipelines:
|
|
270
272
|
# Configuración de caches
|
271
273
|
definitions:
|
272
274
|
caches:
|
273
|
-
bundler: vendor/bundle
|
275
|
+
bundler: vendor/bundle
|
data/jwt_auth_cognito.gemspec
CHANGED
@@ -45,7 +45,6 @@ Gem::Specification.new do |spec|
|
|
45
45
|
spec.add_dependency 'aws-sdk-ssm', '~> 1.0' # For AWS Parameter Store support
|
46
46
|
spec.add_dependency 'json', '~> 2.0'
|
47
47
|
spec.add_dependency 'jwt', '~> 2.0'
|
48
|
-
spec.add_dependency 'openssl', '>= 2.1.0' # For TLS support
|
49
48
|
spec.add_dependency 'redis', '>= 4.2.5', '< 6.0' # Compatible with llegando-neo redis version
|
50
49
|
|
51
50
|
# Development dependencies
|
@@ -55,5 +54,4 @@ Gem::Specification.new do |spec|
|
|
55
54
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
56
55
|
spec.add_development_dependency 'rubocop', '~> 1.0'
|
57
56
|
spec.add_development_dependency 'webmock', '~> 3.0'
|
58
|
-
spec.metadata['rubygems_mfa_required'] = 'true'
|
59
57
|
end
|
@@ -7,7 +7,6 @@ module JwtAuthCognito
|
|
7
7
|
:redis_ssl, :redis_timeout, :redis_connect_timeout, :redis_read_timeout,
|
8
8
|
:redis_ca_cert_path, :redis_ca_cert_name, :redis_verify_mode,
|
9
9
|
:redis_tls_min_version, :redis_tls_max_version,
|
10
|
-
:redis_ca_cert_ssm_path, :redis_ca_cert_ssm_name,
|
11
10
|
:jwks_cache_ttl, :validation_mode, :environment,
|
12
11
|
:enable_api_key_validation, :enable_user_data_retrieval
|
13
12
|
|
@@ -27,14 +26,12 @@ module JwtAuthCognito
|
|
27
26
|
@redis_connect_timeout = (ENV['REDIS_CONNECT_TIMEOUT'] || 10).to_i
|
28
27
|
@redis_read_timeout = (ENV['REDIS_READ_TIMEOUT'] || 10).to_i
|
29
28
|
|
30
|
-
# TLS specific configuration
|
29
|
+
# TLS specific configuration (compatible with auth-service)
|
31
30
|
@redis_ca_cert_path = ENV.fetch('REDIS_CA_CERT_PATH', nil)
|
32
31
|
@redis_ca_cert_name = ENV.fetch('REDIS_CA_CERT_NAME', nil)
|
33
|
-
@redis_ca_cert_ssm_path = ENV.fetch('REDIS_CA_CERT_SSM_PATH', nil)
|
34
|
-
@redis_ca_cert_ssm_name = ENV.fetch('REDIS_CA_CERT_SSM_NAME', nil)
|
35
32
|
@redis_verify_mode = ENV['REDIS_VERIFY_MODE'] || 'peer'
|
36
|
-
@redis_tls_min_version = ENV['REDIS_TLS_MIN_VERSION'] || '
|
37
|
-
@redis_tls_max_version = ENV['REDIS_TLS_MAX_VERSION'] || '
|
33
|
+
@redis_tls_min_version = ENV['REDIS_TLS_MIN_VERSION'] || 'TLSv1_2'
|
34
|
+
@redis_tls_max_version = ENV['REDIS_TLS_MAX_VERSION'] || 'TLSv1_3'
|
38
35
|
|
39
36
|
@jwks_cache_ttl = (ENV['JWKS_CACHE_TTL'] || 3600).to_i # 1 hour
|
40
37
|
@environment = ENV['RAILS_ENV'] || ENV['RACK_ENV'] || ENV['NODE_ENV'] || 'development'
|
@@ -131,85 +131,6 @@ module JwtAuthCognito
|
|
131
131
|
validate(token, options.merge(api_key: api_key, enrich_user_data: true))
|
132
132
|
end
|
133
133
|
|
134
|
-
# ========== LEGACY METHODS (DEPRECATED) ==========
|
135
|
-
|
136
|
-
# @deprecated Use validate() or validate_with_api_key() instead
|
137
|
-
def validate_token_with_api_key(token, api_key = nil, options = {})
|
138
|
-
puts 'WARNING: validate_token_with_api_key is deprecated. Use validate() or validate_with_api_key() instead.'
|
139
|
-
result = validate(token, options.merge(api_key: api_key, enrich_user_data: false))
|
140
|
-
{
|
141
|
-
valid: result[:valid],
|
142
|
-
payload: result[:payload],
|
143
|
-
sub: result[:sub],
|
144
|
-
username: result[:username],
|
145
|
-
token_use: result[:token_use],
|
146
|
-
api_key: result[:api_key],
|
147
|
-
error: result[:error]
|
148
|
-
}
|
149
|
-
end
|
150
|
-
|
151
|
-
# @deprecated Use validate_with_app_access() instead
|
152
|
-
def validate_token_with_app_id(token, api_key, options = {})
|
153
|
-
puts 'WARNING: validate_token_with_app_id is deprecated. Use validate_with_app_access() instead.'
|
154
|
-
validate_with_app_access(token, api_key, options.merge(enrich_user_data: false))
|
155
|
-
end
|
156
|
-
|
157
|
-
# @deprecated Use validate() instead
|
158
|
-
def validate_token_enhanced(token, api_key = nil, options = {})
|
159
|
-
puts 'WARNING: validate_token_enhanced is deprecated. Use validate() instead.'
|
160
|
-
result = validate(token, options.merge(api_key: api_key, enrich_user_data: false))
|
161
|
-
{
|
162
|
-
valid: result[:valid],
|
163
|
-
payload: result[:payload],
|
164
|
-
sub: result[:sub],
|
165
|
-
username: result[:username],
|
166
|
-
token_use: result[:token_use],
|
167
|
-
api_key: result[:api_key],
|
168
|
-
error: result[:error]
|
169
|
-
}
|
170
|
-
end
|
171
|
-
|
172
|
-
# @deprecated Use validate_enriched() instead
|
173
|
-
def validate_token_enriched(token, api_key = nil, options = {})
|
174
|
-
puts 'WARNING: validate_token_enriched is deprecated. Use validate_enriched() instead.'
|
175
|
-
validate_enriched(token, api_key, options)
|
176
|
-
end
|
177
|
-
|
178
|
-
def old_validate_token_enriched(token, api_key = nil, options = {})
|
179
|
-
# First, perform standard token validation
|
180
|
-
basic_result = validate_token_with_api_key(token, api_key, options)
|
181
|
-
|
182
|
-
# If basic validation fails, return early
|
183
|
-
return basic_result unless basic_result[:valid] && basic_result[:payload]
|
184
|
-
|
185
|
-
# If user data retrieval is not enabled, return basic result
|
186
|
-
return basic_result unless @config.enable_user_data_retrieval && @user_data_service
|
187
|
-
|
188
|
-
# Extract user ID from the token
|
189
|
-
user_id = basic_result[:payload]['sub']
|
190
|
-
unless user_id
|
191
|
-
puts 'Token does not contain sub claim, cannot retrieve user data'
|
192
|
-
return basic_result
|
193
|
-
end
|
194
|
-
|
195
|
-
begin
|
196
|
-
# Get comprehensive user data from Redis
|
197
|
-
user_data = @user_data_service.get_comprehensive_user_data(user_id)
|
198
|
-
|
199
|
-
# Add user data to the result
|
200
|
-
enriched_result = basic_result.dup
|
201
|
-
enriched_result[:user_permissions] = user_data['permissions']
|
202
|
-
enriched_result[:user_organizations] = user_data['organizations']
|
203
|
-
enriched_result[:applications] = user_data['applications']
|
204
|
-
|
205
|
-
enriched_result
|
206
|
-
rescue StandardError => e
|
207
|
-
ErrorUtils.log_error(e, 'User data retrieval failed')
|
208
|
-
# Return basic result even if user data retrieval fails
|
209
|
-
basic_result
|
210
|
-
end
|
211
|
-
end
|
212
|
-
|
213
134
|
def validate_access_token(token)
|
214
135
|
result = validate_token(token)
|
215
136
|
|
@@ -420,6 +341,14 @@ module JwtAuthCognito
|
|
420
341
|
|
421
342
|
return { valid: true } unless app_id
|
422
343
|
|
344
|
+
# Check API key access to the application using existing logic
|
345
|
+
api_key_data_symbolized = api_key_data.transform_keys(&:to_sym)
|
346
|
+
return { valid: false, error: "API key does not have access to application #{app_id}" } unless @api_key_validator.can_access_app?(api_key_data_symbolized, app_id)
|
347
|
+
|
348
|
+
# System API keys can access any application (bypass user validation)
|
349
|
+
return { valid: true } if api_key_data['scope'] == 'system'
|
350
|
+
|
351
|
+
# For non-system API keys, verify user has access to the application
|
423
352
|
user_id = payload['sub']
|
424
353
|
return { valid: false, error: 'Token missing user ID (sub claim)' } unless user_id
|
425
354
|
|
@@ -177,18 +177,18 @@ module JwtAuthCognito
|
|
177
177
|
end
|
178
178
|
|
179
179
|
def load_ca_certificate
|
180
|
-
# Priority order for certificate loading (
|
181
|
-
# 1. SSM Parameter Store (
|
182
|
-
# 2. Local file system
|
183
|
-
# 3. Environment variable
|
180
|
+
# Priority order for certificate loading (auth-service compatibility):
|
181
|
+
# 1. SSM Parameter Store (using standard variables)
|
182
|
+
# 2. Local file system fallback
|
183
|
+
# 3. Environment variable fallback
|
184
184
|
|
185
|
-
# 1. Try SSM Parameter Store first (
|
186
|
-
if @config.
|
185
|
+
# 1. Try SSM Parameter Store first (auth-service compatibility)
|
186
|
+
if @config.redis_ca_cert_path && @config.redis_ca_cert_name
|
187
187
|
begin
|
188
188
|
puts '🔍 Loading CA certificate from SSM...'
|
189
189
|
return JwtAuthCognito::SSMService.get_ca_certificate(
|
190
|
-
@config.
|
191
|
-
@config.
|
190
|
+
@config.redis_ca_cert_path,
|
191
|
+
@config.redis_ca_cert_name
|
192
192
|
)
|
193
193
|
rescue StandardError => e
|
194
194
|
puts "⚠️ Failed to load certificate from SSM: #{e.message}"
|
@@ -196,12 +196,14 @@ module JwtAuthCognito
|
|
196
196
|
end
|
197
197
|
end
|
198
198
|
|
199
|
-
# 2.
|
199
|
+
# 2. If SSM failed, try as local file system path
|
200
200
|
if @config.redis_ca_cert_path && @config.redis_ca_cert_name
|
201
201
|
ca_cert_file = File.join(@config.redis_ca_cert_path, @config.redis_ca_cert_name)
|
202
202
|
if File.exist?(ca_cert_file)
|
203
203
|
puts "📁 Loading CA certificate from file system: #{ca_cert_file}"
|
204
204
|
return File.read(ca_cert_file)
|
205
|
+
else
|
206
|
+
puts "⚠️ Local file not found: #{ca_cert_file}"
|
205
207
|
end
|
206
208
|
end
|
207
209
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jwt_auth_cognito
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.pre.beta.
|
4
|
+
version: 1.0.0.pre.beta.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- The Optimal
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-09-
|
11
|
+
date: 2025-09-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk-ssm
|
@@ -52,20 +52,6 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '2.0'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: openssl
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - ">="
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: 2.1.0
|
62
|
-
type: :runtime
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - ">="
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: 2.1.0
|
69
55
|
- !ruby/object:Gem::Dependency
|
70
56
|
name: redis
|
71
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -224,7 +210,6 @@ metadata:
|
|
224
210
|
changelog_uri: https://github.com/theoptimal/jwt-auth-cognito/blob/main/CHANGELOG.md
|
225
211
|
documentation_uri: https://www.rubydoc.info/gems/jwt_auth_cognito
|
226
212
|
bug_tracker_uri: https://github.com/theoptimal/jwt-auth-cognito/issues
|
227
|
-
rubygems_mfa_required: 'true'
|
228
213
|
post_install_message:
|
229
214
|
rdoc_options:
|
230
215
|
- "--charset=UTF-8"
|