Module: Verikloak::Audience::Checker

Defined in:
lib/verikloak/audience/checker.rb

Overview

Audience profile checker functions.

This module provides predicate helpers used by the middleware to decide whether a given set of claims satisfies the configured profile.

Constant Summary collapse

VALID_PROFILES =

Kept for backward compatibility; the canonical definition lives in Verikloak::Audience::Configuration::VALID_PROFILES.

Verikloak::Audience::Configuration::VALID_PROFILES

Class Method Summary collapse

Class Method Details

.allow_account?(claims, required) ⇒ Boolean

Validate aud allowing "account" as an extra value.

Parameters:

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

Returns:

  • (Boolean)


59
60
61
62
63
64
65
66
67
68
# File 'lib/verikloak/audience/checker.rb', line 59

def allow_account?(claims, required)
  aud = normalized_audiences(claims)
  required = normalized_required(required)
  return false if required.empty?

  # Permit 'account' extra
  extras = aud - required
  extras.delete('account')
  extras.empty? && (required - aud).empty?
end

.any_match?(claims, required) ⇒ Boolean

Validate that at least one required audience is present in the token. More permissive than :strict_single; useful when multiple clients share audiences.

Parameters:

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

Returns:

  • (Boolean)


76
77
78
79
80
81
82
83
# File 'lib/verikloak/audience/checker.rb', line 76

def any_match?(claims, required)
  aud = normalized_audiences(claims)
  required = normalized_required(required)
  return false if required.empty?

  # At least one of the required audiences must be present
  aud.intersect?(required)
end

.observed_audiences(claims) ⇒ Array<String>

Audience values observed in the claims, normalized exactly like the profile checks normalize them (useful for consistent logging).

Parameters:

  • claims (Object)

    raw claims value (Hash or #to_hash)

Returns:

  • (Array<String>)


125
126
127
# File 'lib/verikloak/audience/checker.rb', line 125

def observed_audiences(claims)
  normalized_audiences(normalize_claims(claims))
end

.ok?(claims, cfg) ⇒ Boolean

Returns whether the given claims satisfy the configured profile.

Parameters:

Returns:

  • (Boolean)

Raises:



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/verikloak/audience/checker.rb', line 24

def ok?(claims, cfg)
  claims = normalize_claims(claims)
  profile = cfg.validated_profile

  case profile
  when :strict_single
    strict_single?(claims, cfg.required_aud_list)
  when :allow_account
    allow_account?(claims, cfg.required_aud_list)
  when :any_match
    any_match?(claims, cfg.required_aud_list)
  when :resource_or_aud
    resource_or_aud?(claims, cfg.resource_client.to_s, cfg.required_aud_list)
  end
end

.resource_or_aud?(claims, client, required) ⇒ Boolean

Permit when resource roles exist for the client; otherwise fallback to #allow_account?.

Parameters:

  • claims (Hash)
  • client (String)
  • required (Array<String,Symbol>, String, Symbol)

Returns:

  • (Boolean)


92
93
94
95
96
97
98
# File 'lib/verikloak/audience/checker.rb', line 92

def resource_or_aud?(claims, client, required)
  roles = Array(claims.dig('resource_access', client, 'roles')).compact.reject { |r| r.to_s.empty? }
  return true unless roles.empty? # if meaningful roles for client exist, pass

  # otherwise enforce allow_account semantics by default
  allow_account?(claims, required)
end

.strict_single?(claims, required) ⇒ Boolean

Validate that aud matches required exactly (order-insensitive).

Parameters:

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

Returns:

  • (Boolean)


45
46
47
48
49
50
51
52
# File 'lib/verikloak/audience/checker.rb', line 45

def strict_single?(claims, required)
  aud = normalized_audiences(claims)
  required = normalized_required(required)
  return false if required.empty?

  # Must contain all required and have no unexpected extra (order-insensitive)
  aud.sort == required.sort
end

.suggest(claims, cfg, fallback: :strict_single) ⇒ :strict_single, ...

Suggest which profile might fit better, for migration aid.

Parameters:

  • claims (Hash)
  • cfg (Verikloak::Audience::Configuration)
  • fallback (Symbol, nil) (defaults to: :strict_single)

    value returned when no profile accepts the claims (defaults to :strict_single, preserving the 1.0 contract)

Returns:

  • (:strict_single, :allow_account, :any_match, :resource_or_aud, nil)

    the most fitting profile, or the fallback when none accepts



108
109
110
111
112
113
114
115
116
117
118
# File 'lib/verikloak/audience/checker.rb', line 108

def suggest(claims, cfg, fallback: :strict_single)
  claims = normalize_claims(claims)

  required = cfg.required_aud_list
  return :strict_single if strict_single?(claims, required)
  return :allow_account if allow_account?(claims, required)
  return :any_match if any_match?(claims, required)
  return :resource_or_aud if resource_or_aud?(claims, cfg.resource_client.to_s, required)

  fallback
end