Class: ApiKeys::Services::Authenticator

Inherits:
Object
  • Object
show all
Extended by:
Logging
Defined in:
lib/api_keys/services/authenticator.rb

Overview

Authenticates an incoming request by extracting and verifying an API key.

Defined Under Namespace

Classes: Result

Class Method Summary collapse

Class Method Details

.call(request) ⇒ ApiKeys::Services::Authenticator::Result

Authenticates the request.

Parameters:

  • request (ActionDispatch::Request)

    The incoming request object.

Returns:



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/api_keys/services/authenticator.rb', line 31

def self.call(request)
  log_debug "[ApiKeys Auth] Authenticator.call started for request: #{request.uuid}"
  config = ApiKeys.configuration
  config.before_authentication&.call(request)

  # === HTTPS Check (Production Only) ===
  if defined?(Rails.env) && Rails.env.production? && config.https_only_production
    if request.protocol == "http://"
      warning_message = "[ApiKeys Security] API key authentication attempted over insecure HTTP connection in production."
      log_warn warning_message
      if config.https_strict_mode
        log_warn "[ApiKeys Security] Strict mode enabled: Aborting authentication."
        result = Result.failure(error_code: :insecure_connection, message: "API requests must be made over HTTPS in production.")
        config.after_authentication&.call(result)
        return result # Halt execution due to strict mode
      end
    end
  end
  # === End HTTPS Check ===

  token = extract_token(request, config)

  unless token
    log_debug "[ApiKeys Auth] Token extraction failed."
    result = Result.failure(error_code: :missing_token, message: "API token is missing")
    config.after_authentication&.call(result)
    return result
  end

  log_debug "[ApiKeys Auth] Token extracted successfully. Verifying..."
  # Pass the original token AND config to find_and_verify_key
  api_key = find_and_verify_key(token, config)

  result = if api_key&.active?
             log_debug "[ApiKeys Auth] Verification successful. Key ID: #{api_key.id}"
             # TODO: Optionally update last_used_at and requests_count
             Result.success(api_key)
           elsif api_key&.revoked?
             log_debug "[ApiKeys Auth] Verification failed: Key revoked. Key ID: #{api_key.id}"
             Result.failure(error_code: :revoked_key, message: "API key has been revoked")
           elsif api_key&.expired?
             log_debug "[ApiKeys Auth] Verification failed: Key expired. Key ID: #{api_key.id}"
             Result.failure(error_code: :expired_key, message: "API key has expired")
           else # Not found, mismatch, or inactive
             log_debug "[ApiKeys Auth] Verification failed: Token invalid or key not found."
             Result.failure(error_code: :invalid_token, message: "API token is invalid")
           end

  log_debug "[ApiKeys Auth] Authenticator.call finished. Result: #{result.inspect}"
  config.after_authentication&.call(result)
  result
end