@@ -29,9 +29,10 @@ def initialize(user_management:, client_id:, session_data:, cookie_password:)
2929 end
3030
3131 # Authenticates the user based on the session data
32+ # @param include_expired [Boolean] If true, returns decoded token data even when expired (default: false)
3233 # @return [Hash] A hash containing the authentication response and a reason if the authentication failed
33- # rubocop:disable Metrics/AbcSize
34- def authenticate
34+ # rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity
35+ def authenticate ( include_expired : false )
3536 return { authenticated : false , reason : 'NO_SESSION_COOKIE_PROVIDED' } if @session_data . nil?
3637
3738 begin
@@ -41,23 +42,41 @@ def authenticate
4142 end
4243
4344 return { authenticated : false , reason : 'INVALID_SESSION_COOKIE' } unless session [ :access_token ]
44- return { authenticated : false , reason : 'INVALID_JWT' } unless is_valid_jwt ( session [ :access_token ] )
45-
46- decoded = JWT . decode ( session [ :access_token ] , nil , true , algorithms : @jwks_algorithms , jwks : @jwks ) . first
47-
48- {
49- authenticated : true ,
50- session_id : decoded [ 'sid' ] ,
51- organization_id : decoded [ 'org_id' ] ,
52- role : decoded [ 'role' ] ,
53- roles : decoded [ 'roles' ] ,
54- permissions : decoded [ 'permissions' ] ,
55- entitlements : decoded [ 'entitlements' ] ,
56- feature_flags : decoded [ 'feature_flags' ] ,
57- user : session [ :user ] ,
58- impersonator : session [ :impersonator ] ,
59- reason : nil ,
60- }
45+
46+ begin
47+ decoded = JWT . decode (
48+ session [ :access_token ] ,
49+ nil ,
50+ true ,
51+ algorithms : @jwks_algorithms ,
52+ jwks : @jwks ,
53+ verify_expiration : false ,
54+ ) . first
55+
56+ expired = decoded [ 'exp' ] && decoded [ 'exp' ] < Time . now . to_i
57+
58+ # Early return for expired tokens when not including expired data (backward compatible)
59+ return { authenticated : false , reason : 'INVALID_JWT' } if expired && !include_expired
60+
61+ # Return full data for valid tokens or when include_expired is true
62+ {
63+ authenticated : !expired ,
64+ session_id : decoded [ 'sid' ] ,
65+ organization_id : decoded [ 'org_id' ] ,
66+ role : decoded [ 'role' ] ,
67+ roles : decoded [ 'roles' ] ,
68+ permissions : decoded [ 'permissions' ] ,
69+ entitlements : decoded [ 'entitlements' ] ,
70+ feature_flags : decoded [ 'feature_flags' ] ,
71+ user : session [ :user ] ,
72+ impersonator : session [ :impersonator ] ,
73+ reason : expired ? 'INVALID_JWT' : nil ,
74+ }
75+ rescue JWT ::DecodeError
76+ { authenticated : false , reason : 'INVALID_JWT' }
77+ rescue StandardError => e
78+ { authenticated : false , reason : e . message }
79+ end
6180 end
6281
6382 # Refreshes the session data using the refresh token stored in the session data
@@ -66,7 +85,6 @@ def authenticate
6685 # @option options [String] :organization_id The organization ID to use for refreshing the session
6786 # @return [Hash] A hash containing a new sealed session, the authentication response,
6887 # and a reason if the refresh failed
69- # rubocop:disable Metrics/PerceivedComplexity
7088 def refresh ( options = nil )
7189 cookie_password = options . nil? || options [ :cookie_password ] . nil? ? @cookie_password : options [ :cookie_password ]
7290
@@ -168,17 +186,5 @@ def create_remote_jwk_set(uri)
168186
169187 jwks
170188 end
171-
172- # Validates a JWT token using the JWKS set
173- # @param token [String] The JWT token to validate
174- # @return [Boolean] True if the token is valid, false otherwise
175- # rubocop:disable Naming/PredicateName
176- def is_valid_jwt ( token )
177- JWT . decode ( token , nil , true , algorithms : @jwks_algorithms , jwks : @jwks )
178- true
179- rescue StandardError
180- false
181- end
182- # rubocop:enable Naming/PredicateName
183189 end
184190end
0 commit comments