Class: Verikloak::Middleware

Inherits:
Object
  • Object
show all
Includes:
MiddlewareAudienceResolution, MiddlewareConfiguration, MiddlewareDecoderCache, MiddlewareErrorMapping, MiddlewareTokenVerification, SkipPathMatcher
Defined in:
lib/verikloak/middleware.rb

Overview

Rack middleware that verifies incoming JWT access tokens (Keycloak) using OpenID Connect discovery and JWKs. On success, it populates:

  • env` — the raw JWT string

  • env` — the decoded JWT claims Hash

Failures are converted to JSON error responses with appropriate status codes.

Constant Summary collapse

DEFAULT_REALM =
'verikloak'
DEFAULT_TOKEN_ENV_KEY =
'verikloak.token'
DEFAULT_USER_ENV_KEY =
'verikloak.user'
DEFAULT_DECODER_CACHE_LIMIT =

rubocop:disable Metrics/ParameterLists

128

Constants included from MiddlewareErrorMapping

Verikloak::MiddlewareErrorMapping::AUTH_ERROR_CODES, Verikloak::MiddlewareErrorMapping::INFRA_ERROR_CODES

Instance Method Summary collapse

Constructor Details

#initialize(app, discovery_url:, audience:, skip_paths: [], discovery: nil, jwks_cache: nil, connection: nil, leeway: Verikloak::TokenDecoder::DEFAULT_LEEWAY, token_verify_options: {}, decoder_cache_limit: DEFAULT_DECODER_CACHE_LIMIT, token_env_key: DEFAULT_TOKEN_ENV_KEY, user_env_key: DEFAULT_USER_ENV_KEY, realm: DEFAULT_REALM, logger: nil) ⇒ Middleware

Returns a new instance of Middleware.



648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
# File 'lib/verikloak/middleware.rb', line 648

def initialize(app,
               discovery_url:,
               audience:,
               skip_paths: [],
               discovery: nil,
               jwks_cache: nil,
               connection: nil,
               leeway: Verikloak::TokenDecoder::DEFAULT_LEEWAY,
               token_verify_options: {},
               decoder_cache_limit: DEFAULT_DECODER_CACHE_LIMIT,
               token_env_key: DEFAULT_TOKEN_ENV_KEY,
               user_env_key: DEFAULT_USER_ENV_KEY,
               realm: DEFAULT_REALM,
               logger: nil)
  @app             = app
  @connection      = connection || Verikloak::HTTP.default_connection
  @audience_source = audience
  @discovery       = discovery || Discovery.new(discovery_url: discovery_url, connection: @connection)
  @jwks_cache      = jwks_cache
  @leeway = leeway
  @token_verify_options = token_verify_options || {}
  @decoder_cache_limit = normalize_decoder_cache_limit(decoder_cache_limit)
  @issuer        = nil
  @mutex         = Mutex.new
  @decoder_cache = {}
  @decoder_cache_order = []
  @last_cached_keys_id = nil
  @token_env_key = normalize_env_key(token_env_key, 'token_env_key')
  @user_env_key  = normalize_env_key(user_env_key, 'user_env_key')
  @realm         = normalize_realm(realm)
  @logger        = logger

  compile_skip_paths(skip_paths)
end

Instance Method Details

#call(env) ⇒ Array(Integer, Hash, Array<String>)

Rack entrypoint.

Parameters:

  • env (Hash)

    Rack environment

Returns:

  • (Array(Integer, Hash, Array<String>))

    standard Rack response triple



688
689
690
691
692
693
694
695
696
697
698
699
700
# File 'lib/verikloak/middleware.rb', line 688

def call(env)
  path = env['PATH_INFO']
  return @app.call(env) if skip?(path)

  token = extract_token(env)
  handle_request(env, token)
rescue Verikloak::Error => e
  code, status = map_error(e)
  error_response(code, e.message, status)
rescue StandardError => e
  log_internal_error(e)
  error_response('internal_server_error', 'An unexpected error occurred', 500)
end