jwt_auth_cognito 0.3.0 → 1.0.0.pre.beta.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8f8b72ffb2724513f2e4080cf6d3eef3282b860267763833c3d4f3e230168c80
4
- data.tar.gz: 5f396ae6b180d33d720f59f51ef99d7cf5e42496d10d49a9a38b7a413071ee43
3
+ metadata.gz: 9296db47172be874a7d6204b54c3e5fc8de7f77a77a7e02f4b1d8d4b70bc9b8d
4
+ data.tar.gz: 55a4df3b1c9077b9803508ac925715510af9974ef79c40ed097cc0a86eb5b7a3
5
5
  SHA512:
6
- metadata.gz: 81919186799b227f0816a4087a2bd879e4eceda071f985a26cf58954d0b80e15a546b907ca0b94e1f9ad0ce4f24f74b9ef7b10cd34599b5990f1bc3bd44b550d
7
- data.tar.gz: 8aae5fbc4429541677ef8cd37437db596674d882841b1f09fe2b0130d9550945ab0293495a36be839ad4c3aee277fb97cb69e19e66fc9bb4e1845e9c8f3aedbf
6
+ metadata.gz: 19b0aa21809ac6d94c74e358d48d30b4246836610eff67121f41368552a6c385696952aec47a5bb8291c9141e6e0c1de398a028679f1fb05c8a3c71904d58446
7
+ data.tar.gz: 4cff441b707184fab34cc16f8368ae67334b8aad174f28b2c1649292a7d2b0b99ad66d60920ef9d503c95a162cd01e2ae621081e0129f38f3dc11c95f40c810c
data/CHANGELOG.md CHANGED
@@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ### Improved
11
+
12
+ - **Documentation Enhancement**: Added Redis configuration documentation to main usage patterns
13
+ - Updated README.md with complete Redis connection setup in factory method
14
+ - Enhanced CLAUDE.md with Redis configuration in the main usage pattern
15
+ - Improved clarity on how to connect Redis for token blacklisting and user data enrichment
16
+
10
17
  ## [0.3.0] - 2024-01-15
11
18
 
12
19
  ### Added
data/CLAUDE.md CHANGED
@@ -145,6 +145,50 @@ ENV['REDIS_CA_CERT'] = "-----BEGIN CERTIFICATE-----..."
145
145
  - **Backward Compatibility**: All functionality works without client secret configuration
146
146
  - **Security Integration**: Secret hash automatically included in blacklist operations when configured
147
147
 
148
+ ## 🚀 Main Usage Pattern with Redis Connection
149
+
150
+ ### ✨ Complete Setup with Redis Connection
151
+
152
+ ```ruby
153
+ # Create validator with Redis connection for blacklist and user data
154
+ validator = JwtAuthCognito.create_cognito_validator(
155
+ region: 'us-east-1',
156
+ user_pool_id: 'us-east-1_ExamplePool',
157
+ client_id: 'your-client-id',
158
+ client_secret: 'your-client-secret', # Optional
159
+ redis_config: {
160
+ # Redis configuration for token blacklisting and user data enrichment
161
+ host: ENV['REDIS_HOST'] || 'localhost',
162
+ port: ENV['REDIS_PORT']&.to_i || 6379,
163
+ password: ENV['REDIS_PASSWORD'],
164
+ db: ENV['REDIS_DB']&.to_i || 0,
165
+
166
+ # TLS configuration for secure connections
167
+ tls: ENV['REDIS_TLS'] == 'true',
168
+ ca_cert_path: ENV['REDIS_CA_CERT_PATH'],
169
+ ca_cert_name: ENV['REDIS_CA_CERT_NAME'],
170
+ verify_mode: ENV['REDIS_VERIFY_MODE'] || 'peer'
171
+ },
172
+ enable_user_data_retrieval: true
173
+ )
174
+
175
+ # Initialize Redis connection and services
176
+ validator.initialize!
177
+
178
+ # 🌟 Main validation method with complete functionality
179
+ result = validator.validate_token_enriched(token)
180
+
181
+ if result[:valid]
182
+ puts "✅ Valid token:"
183
+ puts "User: #{result[:sub]}"
184
+ puts "Permissions: #{result[:user_permissions]}"
185
+ puts "Organizations: #{result[:user_organizations]}"
186
+ puts "Applications: #{result[:applications]}"
187
+ else
188
+ puts "❌ Invalid token: #{result[:error]}"
189
+ end
190
+ ```
191
+
148
192
  ## Environment Configuration
149
193
 
150
194
  The gem supports extensive environment variable configuration for deployment flexibility:
@@ -152,7 +196,7 @@ The gem supports extensive environment variable configuration for deployment fle
152
196
  ### AWS Cognito Configuration
153
197
  ```bash
154
198
  COGNITO_REGION=us-east-1
155
- COGNITO_USER_POOL_ID=us-east-1_AbCdEfGhI
199
+ COGNITO_USER_POOL_ID=us-east-1_AbCdEfGhI
156
200
  COGNITO_CLIENT_ID=your-client-id
157
201
  COGNITO_CLIENT_SECRET=your-client-secret # Optional for enhanced security
158
202
  ```
data/README.md CHANGED
@@ -162,21 +162,41 @@ end
162
162
  ### Factory Method para Configuración Simplificada (Nuevo v0.3.0)
163
163
 
164
164
  ```ruby
165
- # Crear validador con una línea
165
+ # Crear validador con conexión Redis completa
166
166
  validator = JwtAuthCognito.create_cognito_validator(
167
167
  region: 'us-east-1',
168
168
  user_pool_id: 'us-east-1_ExamplePool',
169
169
  client_id: 'your-client-id',
170
170
  redis_config: {
171
- host: 'localhost',
172
- port: 6379,
173
- tls: true
171
+ # Configuración básica de Redis
172
+ host: ENV['REDIS_HOST'] || 'localhost',
173
+ port: ENV['REDIS_PORT']&.to_i || 6379,
174
+ password: ENV['REDIS_PASSWORD'],
175
+ db: ENV['REDIS_DB']&.to_i || 0,
176
+
177
+ # Configuración TLS para conexiones seguras
178
+ tls: ENV['REDIS_TLS'] == 'true',
179
+ ca_cert_path: ENV['REDIS_CA_CERT_PATH'],
180
+ ca_cert_name: ENV['REDIS_CA_CERT_NAME']
174
181
  },
175
182
  enable_user_data_retrieval: true
176
183
  )
177
184
 
178
- # Usar inmediatamente
185
+ # Inicializar conexiones (incluye Redis)
186
+ validator.initialize!
187
+
188
+ # Usar inmediatamente con validación enriquecida
179
189
  result = validator.validate_token_enriched(token)
190
+
191
+ if result[:valid]
192
+ puts "✅ Token válido con datos enriquecidos:"
193
+ puts "Usuario: #{result[:sub]}"
194
+ puts "Permisos: #{result[:user_permissions]}"
195
+ puts "Organizaciones: #{result[:user_organizations]}"
196
+ puts "Aplicaciones: #{result[:applications]}"
197
+ else
198
+ puts "❌ Token inválido: #{result[:error]}"
199
+ end
180
200
  ```
181
201
 
182
202
  ### Manejo Mejorado de Errores (Nuevo v0.3.0)
@@ -125,12 +125,11 @@ pipelines:
125
125
  # Tags stable (X.Y.Z)
126
126
  "v[0-9]*.[0-9]*.[0-9]*":
127
127
  - step:
128
- name: Deploy Estable a RubyGems
129
- trigger: manual # Requiere confirmación manual
128
+ name: Tests y Build para Deploy Estable
130
129
  caches:
131
130
  - bundler
132
131
  script:
133
- - echo "🚨 DEPLOY DE PRODUCCIÓN - Versión estable"
132
+ - echo "🚨 Preparando versión estable para deploy"
134
133
  - bundle install
135
134
  - echo "Tests completos y exhaustivos..."
136
135
  - bundle exec rspec
@@ -140,6 +139,16 @@ pipelines:
140
139
  - bundle audit check --update || echo "Bundle audit no disponible, continuando..."
141
140
  - echo "Building gem final..."
142
141
  - gem build jwt_auth_cognito.gemspec
142
+ - echo "Build completado - Listo para deploy manual"
143
+ artifacts:
144
+ - "*.gem"
145
+ - step:
146
+ name: Deploy Estable a RubyGems
147
+ trigger: manual # Requiere confirmación manual para el deploy
148
+ caches:
149
+ - bundler
150
+ script:
151
+ - echo "🚨 DEPLOY DE PRODUCCIÓN - Versión estable"
143
152
  - echo "Configurando credenciales RubyGems..."
144
153
  - mkdir -p ~/.gem
145
154
  - 'echo ":rubygems_api_key: $RUBYGEMS_API_KEY" > ~/.gem/credentials'
@@ -147,8 +156,6 @@ pipelines:
147
156
  - echo "Publicando version ESTABLE a RubyGems..."
148
157
  - gem push *.gem
149
158
  - echo "VERSION ESTABLE PUBLICADA EXITOSAMENTE"
150
- artifacts:
151
- - "*.gem"
152
159
 
153
160
  # Tags alpha (X.Y.Z-alpha.N) - Solo para testing
154
161
  "v*-alpha.*":
@@ -27,14 +27,24 @@ module JwtAuthCognito
27
27
  end
28
28
  end
29
29
 
30
- def validate_token(token, options = {})
31
- validate_token_with_api_key(token, nil, options)
32
- end
33
-
34
- def validate_token_with_api_key(token, api_key = nil, options = {})
30
+ # ========== 🚀 MAIN VALIDATION METHOD ==========
31
+
32
+ # Main validation method - use this for most cases
33
+ # Intelligently validates tokens with all features:
34
+ # - JWT validation (basic or secure)
35
+ # - API key validation (if provided)
36
+ # - Blacklist checking
37
+ # - Automatic appId verification
38
+ # - User data enrichment (if enabled)
39
+ def validate(token, options = {})
35
40
  @config.validate!
36
41
 
37
- # Validate API key if provided and enabled
42
+ api_key = options[:api_key]
43
+ force_secure = options[:force_secure] || false
44
+ enrich_user_data = options.fetch(:enrich_user_data, true)
45
+ require_app_access = options[:require_app_access] || false
46
+
47
+ # Step 1: Validate API key if provided
38
48
  api_key_data = nil
39
49
  if api_key && @config.enable_api_key_validation && @api_key_validator
40
50
  api_key_result = @api_key_validator.validate_api_key(api_key)
@@ -43,26 +53,129 @@ module JwtAuthCognito
43
53
  api_key_data = api_key_result[:key_data]
44
54
  end
45
55
 
46
- # Check blacklist first
56
+ # Step 2: Check blacklist first
47
57
  return { valid: false, error: 'Token has been revoked' } if @blacklist_service.is_blacklisted?(token)
48
58
 
49
- # Choose validation method based on configuration
50
- result = case @config.validation_mode
51
- when :secure
52
- validate_token_secure(token, options)
53
- when :basic
54
- validate_token_basic(token, options)
55
- else
56
- raise ConfigurationError, "Invalid validation_mode: #{@config.validation_mode}"
57
- end
59
+ # Step 3: Validate JWT token
60
+ validation_mode = force_secure ? :secure : @config.validation_mode
61
+ token_result = case validation_mode
62
+ when :secure
63
+ validate_token_secure(token, options)
64
+ when :basic
65
+ validate_token_basic(token, options)
66
+ else
67
+ raise ConfigurationError, "Invalid validation_mode: #{validation_mode}"
68
+ end
69
+
70
+ return token_result unless token_result[:valid] && token_result[:payload]
71
+
72
+ # Step 4: Verify appId access if API key has one
73
+ if api_key_data
74
+ app_validation = verify_app_access(api_key_data, token_result[:payload], require_app_access)
75
+ return app_validation unless app_validation[:valid]
76
+ end
58
77
 
59
- # Add API key data to result if validation succeeded
60
- result[:api_key] = api_key_data if result[:valid] && api_key_data
78
+ # Step 5: Enrich with user data if requested
79
+ enriched_result = token_result.dup
80
+ enriched_result[:api_key] = api_key_data if api_key_data
81
+
82
+ if enrich_user_data && @config.enable_user_data_retrieval && @user_data_service
83
+ user_id = token_result[:payload]['sub']
84
+ if user_id
85
+ begin
86
+ user_data = @user_data_service.get_comprehensive_user_data(user_id)
87
+ enriched_result[:user_permissions] = user_data['permissions']
88
+ enriched_result[:user_organizations] = user_data['organizations']
89
+ enriched_result[:applications] = user_data['applications']
90
+ rescue StandardError => e
91
+ ErrorUtils.log_error(e, 'User data retrieval failed')
92
+ # Continue with basic validation if user data service fails
93
+ end
94
+ end
95
+ end
61
96
 
62
- result
97
+ enriched_result
98
+ end
99
+
100
+ # ========== SIMPLIFIED PUBLIC API ==========
101
+
102
+ # Quick validation for simple use cases
103
+ # Just validates the JWT token (includes blacklist check)
104
+ def validate_token(token, options = {})
105
+ result = validate(token, options.merge(enrich_user_data: false))
106
+ {
107
+ valid: result[:valid],
108
+ payload: result[:payload],
109
+ sub: result[:sub],
110
+ username: result[:username],
111
+ token_use: result[:token_use],
112
+ error: result[:error]
113
+ }
114
+ end
115
+
116
+ # Validate with API key (automatic appId verification)
117
+ # Use this when you have an API key and want automatic security
118
+ def validate_with_api_key(token, api_key, options = {})
119
+ validate(token, options.merge(api_key: api_key))
120
+ end
121
+
122
+ # Validate with strict appId requirement
123
+ # Use this when you MUST ensure user has access to a specific app
124
+ def validate_with_app_access(token, api_key, options = {})
125
+ validate(token, options.merge(api_key: api_key, require_app_access: true))
126
+ end
127
+
128
+ # Get enriched validation (user data included)
129
+ # Use this when you need user permissions, organizations, apps
130
+ def validate_enriched(token, api_key = nil, options = {})
131
+ validate(token, options.merge(api_key: api_key, enrich_user_data: true))
132
+ end
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
+ }
63
149
  end
64
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
65
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 = {})
66
179
  # First, perform standard token validation
67
180
  basic_result = validate_token_with_api_key(token, api_key, options)
68
181
 
@@ -299,5 +412,41 @@ module JwtAuthCognito
299
412
 
300
413
  raise ValidationError, "Token missing required scopes: #{missing_scopes.join(', ')}"
301
414
  end
415
+
416
+ def verify_app_access(api_key_data, payload, require_app_access)
417
+ app_id = api_key_data['appId'] || api_key_data['metadata']&.[]('appId')
418
+
419
+ return { valid: false, error: 'API key is not associated with an application' } if !app_id && require_app_access
420
+
421
+ return { valid: true } unless app_id
422
+
423
+ user_id = payload['sub']
424
+ return { valid: false, error: 'Token missing user ID (sub claim)' } unless user_id
425
+
426
+ verify_user_app_access(user_id, app_id, require_app_access)
427
+ end
428
+
429
+ def verify_user_app_access(user_id, app_id, require_app_access)
430
+ if require_app_access && (!@config.enable_user_data_retrieval || !@user_data_service)
431
+ return { valid: false,
432
+ error: 'User data service not available for application access verification' }
433
+ end
434
+
435
+ return { valid: true } unless @config.enable_user_data_retrieval && @user_data_service
436
+
437
+ begin
438
+ user_applications = @user_data_service.get_user_applications(user_id)
439
+ has_access = user_applications.any? { |app| app['appId'] == app_id }
440
+
441
+ return { valid: false, error: "User does not have access to application #{app_id}" } unless has_access
442
+
443
+ { valid: true }
444
+ rescue StandardError => e
445
+ return { valid: false, error: 'Could not verify application access' } if require_app_access
446
+
447
+ ErrorUtils.log_error(e, 'User application access verification failed')
448
+ { valid: true } # Continue with basic validation if user data service fails
449
+ end
450
+ end
302
451
  end
303
452
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JwtAuthCognito
4
- VERSION = '0.3.0'
4
+ VERSION = '1.0.0-beta.2'
5
5
  end
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: 0.3.0
4
+ version: 1.0.0.pre.beta.2
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-12 00:00:00.000000000 Z
11
+ date: 2025-09-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-ssm
@@ -237,9 +237,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
237
237
  version: 2.7.0
238
238
  required_rubygems_version: !ruby/object:Gem::Requirement
239
239
  requirements:
240
- - - ">="
240
+ - - ">"
241
241
  - !ruby/object:Gem::Version
242
- version: '0'
242
+ version: 1.3.1
243
243
  requirements: []
244
244
  rubygems_version: 3.3.27
245
245
  signing_key: