Module: Verikloak::BFF::ConsistencyChecks

Defined in:
lib/verikloak/bff/consistency_checks.rb

Overview

Compares X-Auth-Request-* headers with JWT claims according to a mapping.

Class Method Summary collapse

Class Method Details

.decode_claims(token) ⇒ Hash

Decode the JWT payload without verifying the signature. Intended only for lightweight claim comparisons; full verification occurs downstream.

Parameters:

  • token (String, nil)

Returns:

  • (Hash)

    claims or empty hash on error



23
24
25
# File 'lib/verikloak/bff/consistency_checks.rb', line 23

def decode_claims(token)
  Verikloak::BFF::JwtUtils.decode_claims(token)
end

.dig_claim(claims, key) ⇒ Object?

Dig into JWT claims by a symbol/string key or an array path.

Parameters:

  • claims (Hash)
  • key (Symbol, String, Array<String,Symbol>)

Returns:

  • (Object, nil)


113
114
115
116
117
118
119
120
# File 'lib/verikloak/bff/consistency_checks.rb', line 113

def dig_claim(claims, key)
  case key
  when Symbol, String
    claims[key.to_s]
  when Array
    key.reduce(claims) { |acc, k| acc.is_a?(Hash) ? acc[k.to_s] : nil }
  end
end

.enforce!(env, token, mapping, headers_map = nil) ⇒ true, Array(:error, Symbol)

mapping: { email: :email, user: :sub, groups: :realm_roles } Enforce consistency according to the provided mapping.

Parameters:

  • env (Hash)
  • token (String, nil)
  • mapping (Hash)

    e.g., { email: :email, user: :sub, groups: :realm_roles }

  • headers_map (Hash{Symbol=>String}, nil) (defaults to: nil)

    overrides for header keys

Returns:

  • (true, Array(:error, Symbol))

    true or error tuple with failing field



35
36
37
38
39
40
# File 'lib/verikloak/bff/consistency_checks.rb', line 35

def enforce!(env, token, mapping, headers_map = nil)
  return true if mapping.nil? || mapping.empty?

  claims = decode_claims(token)
  enforce_claims(env, claims, mapping, headers_map)
end

.enforce_claims(env, claims, mapping, headers_map) ⇒ true, Array(:error, Symbol)

Shared implementation for enforce! and enforce_with_claims.

Parameters:

  • env (Hash)
  • claims (Hash)
  • mapping (Hash)
  • headers_map (Hash{Symbol=>String}, nil)

Returns:

  • (true, Array(:error, Symbol))


63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/verikloak/bff/consistency_checks.rb', line 63

def enforce_claims(env, claims, mapping, headers_map)
  mapping.each do |header_key, claim_key|
    hdr_val = extract_header_value(env, header_key, headers_map)
    next if hdr_val.nil? # no header → skip comparison

    case claim_key
    when :realm_roles
      roles = Array((claims['realm_access'] || {})['roles'] || [])
      hdr_list = split_list(hdr_val)
      return error(:groups) unless (hdr_list - roles).empty?
    else
      claim_val = dig_claim(claims, claim_key)
      return error(header_key) unless claim_val && hdr_val.to_s == claim_val.to_s
    end
  end
  true
end

.enforce_with_claims(env, claims, mapping, headers_map = nil) ⇒ true, Array(:error, Symbol)

Enforce consistency using pre-decoded claims (avoids redundant JWT parsing).

Parameters:

  • env (Hash)
  • claims (Hash)

    pre-decoded JWT claims

  • mapping (Hash)
  • headers_map (Hash{Symbol=>String}, nil) (defaults to: nil)

Returns:

  • (true, Array(:error, Symbol))


49
50
51
52
53
54
# File 'lib/verikloak/bff/consistency_checks.rb', line 49

def enforce_with_claims(env, claims, mapping, headers_map = nil)
  return true if mapping.nil? || mapping.empty?

  claims = {} unless claims.is_a?(Hash)
  enforce_claims(env, claims, mapping, headers_map)
end

.error(field) ⇒ Array(:error, Symbol)

Build an error tuple for a failed field.

Parameters:

  • field (Symbol)

Returns:

  • (Array(:error, Symbol))


126
127
128
# File 'lib/verikloak/bff/consistency_checks.rb', line 126

def error(field)
  [:error, field]
end

.extract_header_value(env, key, headers_map = nil) ⇒ String?

Extract an X-Auth-Request-* header value mapped from a symbolic key.

Parameters:

  • env (Hash)
  • key (Symbol)
  • headers_map (Hash{Symbol=>String}, nil) (defaults to: nil)

Returns:

  • (String, nil)


87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/verikloak/bff/consistency_checks.rb', line 87

def extract_header_value(env, key, headers_map = nil)
  return env[headers_map[key]] if headers_map && headers_map[key]

  case key
  when :email
    env['HTTP_X_AUTH_REQUEST_EMAIL']
  when :user
    env['HTTP_X_AUTH_REQUEST_USER']
  when :groups
    env['HTTP_X_AUTH_REQUEST_GROUPS']
  end
end

.split_list(val) ⇒ Array<String>

Split a comma-separated list into an array.

Parameters:

  • val (String)

Returns:

  • (Array<String>)


104
105
106
# File 'lib/verikloak/bff/consistency_checks.rb', line 104

def split_list(val)
  Array(val.to_s.split(',').map(&:strip).reject(&:empty?))
end