verikloak-audience 0.2.5 → 0.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +19 -0
- data/README.md +10 -2
- data/lib/generators/verikloak/audience/install/install_generator.rb +26 -0
- data/lib/generators/verikloak/audience/install/templates/initializer.rb.erb +7 -0
- data/lib/verikloak/audience/checker.rb +16 -9
- data/lib/verikloak/audience/configuration.rb +9 -12
- data/lib/verikloak/audience/middleware.rb +9 -13
- data/lib/verikloak/audience/railtie.rb +178 -12
- data/lib/verikloak/audience/version.rb +1 -1
- metadata +4 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 59d9195c0dfe4835b91a16bf8f08a58369f398890b5aff664979421a388a91d1
         | 
| 4 | 
            +
              data.tar.gz: 8bd59e610df30f6eb1238b06f12a2778ddb0287264a967424751db38acae2f81
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 0d5d65f4ff5ca863d1f638b7e19a71edb256aa905bcc21b1ac49802b4c8db53697ed50d6f45bd67730a147a215972ddadbc78a403155e5d3b6ea1cf5b341dc69
         | 
| 7 | 
            +
              data.tar.gz: c149176b446b3021204c039d2a07f9297676b57db52ae63f40812029b7f899c7398a425ba1a1542f058303e5a0615d51ebd793b5610d1c9feeb98bd7009c1c88
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -7,6 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 | |
| 7 7 |  | 
| 8 8 | 
             
            ---
         | 
| 9 9 |  | 
| 10 | 
            +
            ## [0.2.7] - 2025-09-27
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            ### Changed
         | 
| 13 | 
            +
            - Rails Railtie now syncs `env_claims_key`, `required_aud`, and `resource_client` defaults with verikloak-rails configuration after boot.
         | 
| 14 | 
            +
            - Generator template converted to ERB and bundled with the gem so `rails g verikloak:audience:install` produces the initializer without relying on Rails internals.
         | 
| 15 | 
            +
            - Middleware option validation tightened to fail fast on unknown overrides with clearer error messages.
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            ### Documentation
         | 
| 18 | 
            +
            - Added RubyDoc comments across the Railtie to clarify initializer responsibilities and helper methods.
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            ## [0.2.6] - 2025-09-23
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            ### Added
         | 
| 23 | 
            +
            - Rails generator `verikloak:audience:install` to create an initializer that inserts the audience middleware once the core Verikloak middleware is available.
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            ### Changed
         | 
| 26 | 
            +
            - Improved warning message when core Verikloak middleware is not present in the Rails middleware stack.
         | 
| 27 | 
            +
            - Enhanced middleware insertion logic to provide clearer guidance on setup requirements.
         | 
| 28 | 
            +
             | 
| 10 29 | 
             
            ## [0.2.5] - 2025-09-23
         | 
| 11 30 |  | 
| 12 31 | 
             
            ### Changed
         | 
    
        data/README.md
    CHANGED
    
    | @@ -30,9 +30,17 @@ For the full error behaviour (response shapes, exception classes, logging hints) | |
| 30 30 | 
             
            bundle add verikloak-audience
         | 
| 31 31 | 
             
            ```
         | 
| 32 32 |  | 
| 33 | 
            -
             | 
| 33 | 
            +
            In Rails applications, generate the initializer that automatically inserts the middleware:
         | 
| 34 34 |  | 
| 35 | 
            -
             | 
| 35 | 
            +
            ```bash
         | 
| 36 | 
            +
            rails g verikloak:audience:install
         | 
| 37 | 
            +
            ```
         | 
| 38 | 
            +
             | 
| 39 | 
            +
            This creates `config/initializers/verikloak_audience.rb` that will insert the audience middleware after the core Verikloak middleware once it's available.
         | 
| 40 | 
            +
             | 
| 41 | 
            +
            ## Manual Rack / Rails setup
         | 
| 42 | 
            +
             | 
| 43 | 
            +
            Alternatively, you can manually insert **after** `Verikloak::Middleware`:
         | 
| 36 44 |  | 
| 37 45 | 
             
            ```ruby
         | 
| 38 46 | 
             
            # config/application.rb
         | 
| @@ -0,0 +1,26 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            begin
         | 
| 4 | 
            +
              require 'rails/generators'
         | 
| 5 | 
            +
              require 'rails/generators/base'
         | 
| 6 | 
            +
            rescue LoadError
         | 
| 7 | 
            +
              raise unless defined?(Rails::Generators::Base)
         | 
| 8 | 
            +
            end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            module Verikloak
         | 
| 11 | 
            +
              module Audience
         | 
| 12 | 
            +
                module Generators
         | 
| 13 | 
            +
                  # Installs the verikloak audience middleware configuration into a Rails
         | 
| 14 | 
            +
                  # application. This generator creates an initializer that inserts the
         | 
| 15 | 
            +
                  # audience middleware after the core Verikloak middleware once it is
         | 
| 16 | 
            +
                  # available.
         | 
| 17 | 
            +
                  class InstallGenerator < Rails::Generators::Base
         | 
| 18 | 
            +
                    source_root File.expand_path('templates', __dir__)
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                    def create_initializer
         | 
| 21 | 
            +
                      template 'initializer.rb.erb', 'config/initializers/verikloak_audience.rb'
         | 
| 22 | 
            +
                    end
         | 
| 23 | 
            +
                  end
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
              end
         | 
| 26 | 
            +
            end
         | 
| @@ -0,0 +1,7 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # Insert the audience middleware after the core Verikloak middleware once it
         | 
| 4 | 
            +
            # has been loaded into the application.
         | 
| 5 | 
            +
            if defined?(Rails) && Rails.respond_to?(:application)
         | 
| 6 | 
            +
              Verikloak::Audience::Railtie.insert_middleware(Rails.application)
         | 
| 7 | 
            +
            end
         | 
| @@ -44,7 +44,7 @@ module Verikloak | |
| 44 44 | 
             
                  # @param required [Array<String>]
         | 
| 45 45 | 
             
                  # @return [Boolean]
         | 
| 46 46 | 
             
                  def strict_single?(claims, required)
         | 
| 47 | 
            -
                    aud =  | 
| 47 | 
            +
                    aud = normalized_audiences(claims)
         | 
| 48 48 | 
             
                    return false if required.empty?
         | 
| 49 49 |  | 
| 50 50 | 
             
                    # Must contain all required and have no unexpected extra (order-insensitive)
         | 
| @@ -57,7 +57,7 @@ module Verikloak | |
| 57 57 | 
             
                  # @param required [Array<String>]
         | 
| 58 58 | 
             
                  # @return [Boolean]
         | 
| 59 59 | 
             
                  def allow_account?(claims, required)
         | 
| 60 | 
            -
                    aud =  | 
| 60 | 
            +
                    aud = normalized_audiences(claims)
         | 
| 61 61 | 
             
                    return false if required.empty?
         | 
| 62 62 |  | 
| 63 63 | 
             
                    # Permit 'account' extra
         | 
| @@ -89,13 +89,10 @@ module Verikloak | |
| 89 89 | 
             
                  def suggest(claims, cfg)
         | 
| 90 90 | 
             
                    claims = normalize_claims(claims)
         | 
| 91 91 |  | 
| 92 | 
            -
                     | 
| 93 | 
            -
                     | 
| 94 | 
            -
                     | 
| 95 | 
            -
             | 
| 96 | 
            -
                    return :strict_single if aud.sort == req.sort
         | 
| 97 | 
            -
                    return :allow_account if (aud - req) == ['account'] && (req - aud).empty?
         | 
| 98 | 
            -
                    return :resource_or_aud if has_roles
         | 
| 92 | 
            +
                    required = cfg.required_aud_list
         | 
| 93 | 
            +
                    return :strict_single if strict_single?(claims, required)
         | 
| 94 | 
            +
                    return :allow_account if allow_account?(claims, required)
         | 
| 95 | 
            +
                    return :resource_or_aud if resource_or_aud?(claims, cfg.resource_client.to_s, required)
         | 
| 99 96 |  | 
| 100 97 | 
             
                    :strict_single
         | 
| 101 98 | 
             
                  end
         | 
| @@ -120,6 +117,16 @@ module Verikloak | |
| 120 117 | 
             
                  end
         | 
| 121 118 | 
             
                  module_function :normalize_claims
         | 
| 122 119 | 
             
                  private_class_method :normalize_claims
         | 
| 120 | 
            +
             | 
| 121 | 
            +
                  # Normalize audience claims into a predictable array of strings.
         | 
| 122 | 
            +
                  #
         | 
| 123 | 
            +
                  # @param claims [Hash]
         | 
| 124 | 
            +
                  # @return [Array<String>]
         | 
| 125 | 
            +
                  def normalized_audiences(claims)
         | 
| 126 | 
            +
                    Array(claims['aud']).map(&:to_s)
         | 
| 127 | 
            +
                  end
         | 
| 128 | 
            +
                  module_function :normalized_audiences
         | 
| 129 | 
            +
                  private_class_method :normalized_audiences
         | 
| 123 130 | 
             
                end
         | 
| 124 131 | 
             
              end
         | 
| 125 132 | 
             
            end
         | 
| @@ -23,6 +23,7 @@ module Verikloak | |
| 23 23 | 
             
                #   @return [Boolean]
         | 
| 24 24 | 
             
                class Configuration
         | 
| 25 25 | 
             
                  DEFAULT_RESOURCE_CLIENT = 'rails-api'
         | 
| 26 | 
            +
                  DEFAULT_ENV_CLAIMS_KEY = 'verikloak.user'
         | 
| 26 27 |  | 
| 27 28 | 
             
                  attr_accessor :profile, :required_aud, :resource_client,
         | 
| 28 29 | 
             
                                :suggest_in_logs
         | 
| @@ -35,7 +36,7 @@ module Verikloak | |
| 35 36 | 
             
                    @profile         = :strict_single
         | 
| 36 37 | 
             
                    @required_aud    = []
         | 
| 37 38 | 
             
                    @resource_client = DEFAULT_RESOURCE_CLIENT
         | 
| 38 | 
            -
                    self.env_claims_key =  | 
| 39 | 
            +
                    self.env_claims_key = DEFAULT_ENV_CLAIMS_KEY
         | 
| 39 40 | 
             
                    @suggest_in_logs = true
         | 
| 40 41 | 
             
                  end
         | 
| 41 42 |  | 
| @@ -121,23 +122,19 @@ module Verikloak | |
| 121 122 | 
             
                  # @return [void]
         | 
| 122 123 | 
             
                  def ensure_resource_client!(audiences)
         | 
| 123 124 | 
             
                    client = resource_client.to_s
         | 
| 125 | 
            +
                    error_msg = 'resource_client must match one of required_aud when using :resource_or_aud profile'
         | 
| 124 126 |  | 
| 125 | 
            -
                     | 
| 127 | 
            +
                    if needs_resource_client_inference?(client, audiences)
         | 
| 128 | 
            +
                      raise Verikloak::Audience::ConfigurationError, error_msg unless audiences.one?
         | 
| 129 | 
            +
             | 
| 130 | 
            +
                      self.resource_client = audiences.first
         | 
| 131 | 
            +
                      client = resource_client.to_s
         | 
| 126 132 |  | 
| 127 | 
            -
                    if needs_inference
         | 
| 128 | 
            -
                      if audiences.one?
         | 
| 129 | 
            -
                        self.resource_client = audiences.first
         | 
| 130 | 
            -
                        client = resource_client.to_s
         | 
| 131 | 
            -
                      else
         | 
| 132 | 
            -
                        raise Verikloak::Audience::ConfigurationError,
         | 
| 133 | 
            -
                              'resource_client must match one of required_aud when using :resource_or_aud profile'
         | 
| 134 | 
            -
                      end
         | 
| 135 133 | 
             
                    end
         | 
| 136 134 |  | 
| 137 135 | 
             
                    return if audiences.include?(client)
         | 
| 138 136 |  | 
| 139 | 
            -
                    raise Verikloak::Audience::ConfigurationError,
         | 
| 140 | 
            -
                          'resource_client must match one of required_aud when using :resource_or_aud profile'
         | 
| 137 | 
            +
                    raise Verikloak::Audience::ConfigurationError, error_msg
         | 
| 141 138 | 
             
                  end
         | 
| 142 139 |  | 
| 143 140 | 
             
                  # Decide whether the resource client should be inferred from the
         | 
| @@ -57,16 +57,14 @@ module Verikloak | |
| 57 57 | 
             
                  # @return [void]
         | 
| 58 58 | 
             
                  def apply_overrides!(opts)
         | 
| 59 59 | 
             
                    cfg = @config
         | 
| 60 | 
            -
                    opts. | 
| 60 | 
            +
                    opts.each do |key, value|
         | 
| 61 61 | 
             
                      writer = "#{key}="
         | 
| 62 | 
            -
                       | 
| 62 | 
            +
                      unless cfg.respond_to?(writer)
         | 
| 63 | 
            +
                        raise Verikloak::Audience::ConfigurationError,
         | 
| 64 | 
            +
                              "unknown middleware option :#{key}"
         | 
| 65 | 
            +
                      end
         | 
| 63 66 |  | 
| 64 | 
            -
                       | 
| 65 | 
            -
                            "unknown middleware option :#{key}"
         | 
| 66 | 
            -
                    end
         | 
| 67 | 
            -
             | 
| 68 | 
            -
                    opts.each do |k, v|
         | 
| 69 | 
            -
                      cfg.public_send("#{k}=", v)
         | 
| 67 | 
            +
                      cfg.public_send(writer, value)
         | 
| 70 68 | 
             
                    end
         | 
| 71 69 | 
             
                  end
         | 
| 72 70 |  | 
| @@ -90,11 +88,9 @@ module Verikloak | |
| 90 88 | 
             
                  # @return [void]
         | 
| 91 89 | 
             
                  def log_warning(env, message)
         | 
| 92 90 | 
             
                    logger = env['verikloak.logger'] || env['rack.logger'] || env['action_dispatch.logger']
         | 
| 93 | 
            -
                    if logger.respond_to?(:warn)
         | 
| 94 | 
            -
             | 
| 95 | 
            -
                     | 
| 96 | 
            -
                      warn(message)
         | 
| 97 | 
            -
                    end
         | 
| 91 | 
            +
                    return logger.warn(message) if logger.respond_to?(:warn)
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                    Kernel.warn(message)
         | 
| 98 94 | 
             
                  end
         | 
| 99 95 | 
             
                end
         | 
| 100 96 | 
             
              end
         | 
| @@ -35,6 +35,7 @@ module Verikloak | |
| 35 35 |  | 
| 36 36 | 
             
                  initializer 'verikloak_audience.configuration' do
         | 
| 37 37 | 
             
                    config.after_initialize do
         | 
| 38 | 
            +
                      self.class.apply_verikloak_rails_configuration
         | 
| 38 39 | 
             
                      next if Verikloak::Audience::Railtie.skip_configuration_validation?
         | 
| 39 40 |  | 
| 40 41 | 
             
                      Verikloak::Audience.config.validate!
         | 
| @@ -42,15 +43,61 @@ module Verikloak | |
| 42 43 | 
             
                  end
         | 
| 43 44 |  | 
| 44 45 | 
             
                  # Performs the insertion into the middleware stack when the core
         | 
| 45 | 
            -
                  # Verikloak middleware is available. Extracted for | 
| 46 | 
            -
                  # requiring a full Rails boot process.
         | 
| 46 | 
            +
                  # Verikloak middleware is available and already present. Extracted for
         | 
| 47 | 
            +
                  # testability without requiring a full Rails boot process.
         | 
| 48 | 
            +
                  #
         | 
| 49 | 
            +
                  # Insert the audience middleware after the base Verikloak middleware when
         | 
| 50 | 
            +
                  # both are available on the stack.
         | 
| 47 51 | 
             
                  #
         | 
| 48 52 | 
             
                  # @param app [#middleware] An object exposing a Rack middleware stack via `#middleware`.
         | 
| 49 53 | 
             
                  # @return [void]
         | 
| 50 54 | 
             
                  def self.insert_middleware(app)
         | 
| 51 55 | 
             
                    return unless defined?(::Verikloak::Middleware)
         | 
| 52 56 |  | 
| 53 | 
            -
                    app.middleware | 
| 57 | 
            +
                    middleware_stack = app.middleware
         | 
| 58 | 
            +
                    return unless middleware_stack.respond_to?(:include?)
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                    return if middleware_stack.include?(::Verikloak::Audience::Middleware)
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                    unless middleware_stack.include?(::Verikloak::Middleware)
         | 
| 63 | 
            +
                      warn_missing_core_middleware
         | 
| 64 | 
            +
                      return
         | 
| 65 | 
            +
                    end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                    middleware_stack.insert_after ::Verikloak::Middleware, ::Verikloak::Audience::Middleware
         | 
| 68 | 
            +
                  end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                  WARNING_MESSAGE = <<~MSG
         | 
| 71 | 
            +
                    [verikloak-audience] Skipping automatic middleware insertion because ::Verikloak::Middleware
         | 
| 72 | 
            +
                    is not present in the Rails middleware stack.
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                    To enable verikloak-audience, first ensure that the core Verikloak middleware (`Verikloak::Middleware`)
         | 
| 75 | 
            +
                    is added to your Rails middleware stack. Once the core middleware is present, you can run
         | 
| 76 | 
            +
                    `rails g verikloak:audience:install` to generate the initializer for the audience middleware,
         | 
| 77 | 
            +
                    or manually add:
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                      config.middleware.insert_after Verikloak::Middleware, Verikloak::Audience::Middleware
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                    This warning will disappear once the core middleware is properly configured and the audience
         | 
| 82 | 
            +
                    middleware is inserted.
         | 
| 83 | 
            +
                  MSG
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                  # Logs a warning message when the core Verikloak middleware is missing
         | 
| 86 | 
            +
                  # from the Rails middleware stack. Uses the Rails logger if available,
         | 
| 87 | 
            +
                  # otherwise falls back to Kernel.warn for output.
         | 
| 88 | 
            +
                  #
         | 
| 89 | 
            +
                  # This method is called when automatic middleware insertion is skipped
         | 
| 90 | 
            +
                  # due to the absence of the required core middleware.
         | 
| 91 | 
            +
                  #
         | 
| 92 | 
            +
                  # @return [void]
         | 
| 93 | 
            +
                  def self.warn_missing_core_middleware
         | 
| 94 | 
            +
                    logger = (::Rails.logger if defined?(::Rails) && ::Rails.respond_to?(:logger))
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                    if logger
         | 
| 97 | 
            +
                      logger.warn(WARNING_MESSAGE)
         | 
| 98 | 
            +
                    else
         | 
| 99 | 
            +
                      Kernel.warn(WARNING_MESSAGE)
         | 
| 100 | 
            +
                    end
         | 
| 54 101 | 
             
                  end
         | 
| 55 102 |  | 
| 56 103 | 
             
                  # Rails short commands (`g`, `d`) are stripped from ARGV fairly early in
         | 
| @@ -64,25 +111,32 @@ module Verikloak | |
| 64 111 | 
             
                  #
         | 
| 65 112 | 
             
                  # @return [Boolean]
         | 
| 66 113 | 
             
                  def self.skip_configuration_validation?
         | 
| 67 | 
            -
                     | 
| 68 | 
            -
                    return false  | 
| 114 | 
            +
                    tokens = first_cli_tokens
         | 
| 115 | 
            +
                    return false if tokens.empty?
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                    command = tokens.first
         | 
| 118 | 
            +
                    return true if COMMANDS_SKIPPING_VALIDATION.include?(command)
         | 
| 69 119 |  | 
| 70 | 
            -
                     | 
| 120 | 
            +
                    tokens.any? { |token| verikloak_install_generator?(token) }
         | 
| 71 121 | 
             
                  end
         | 
| 72 122 |  | 
| 73 | 
            -
                  # Capture the first non-option  | 
| 74 | 
            -
                  # ignoring wrapper tokens such as "rails".
         | 
| 123 | 
            +
                  # Capture the first non-option arguments passed to the Rails CLI,
         | 
| 124 | 
            +
                  # ignoring wrapper tokens such as "rails". Only the first two tokens are
         | 
| 125 | 
            +
                  # relevant for generator detection, so we keep the return list short.
         | 
| 75 126 | 
             
                  #
         | 
| 76 | 
            -
                  # @return [String | 
| 77 | 
            -
                  def self. | 
| 127 | 
            +
                  # @return [Array<String>] ordered CLI tokens that may signal a generator
         | 
| 128 | 
            +
                  def self.first_cli_tokens
         | 
| 129 | 
            +
                    tokens = []
         | 
| 130 | 
            +
             | 
| 78 131 | 
             
                    ARGV.each do |arg|
         | 
| 79 132 | 
             
                      next if arg.start_with?('-')
         | 
| 80 133 | 
             
                      next if arg == 'rails'
         | 
| 81 134 |  | 
| 82 | 
            -
                       | 
| 135 | 
            +
                      tokens << arg
         | 
| 136 | 
            +
                      break if tokens.size >= 2
         | 
| 83 137 | 
             
                    end
         | 
| 84 138 |  | 
| 85 | 
            -
                     | 
| 139 | 
            +
                    tokens
         | 
| 86 140 | 
             
                  end
         | 
| 87 141 |  | 
| 88 142 | 
             
                  # Detect whether the provided CLI token refers to a Verikloak install
         | 
| @@ -95,6 +149,118 @@ module Verikloak | |
| 95 149 |  | 
| 96 150 | 
             
                    command.start_with?('verikloak:') && command.end_with?(':install')
         | 
| 97 151 | 
             
                  end
         | 
| 152 | 
            +
             | 
| 153 | 
            +
                  class << self
         | 
| 154 | 
            +
                    # Synchronize configuration with verikloak-rails when it is present.
         | 
| 155 | 
            +
                    # Aligns env_claims_key, required_aud, and resource_client defaults so
         | 
| 156 | 
            +
                    # that both gems operate on the same Rack env payload and audience list.
         | 
| 157 | 
            +
                    #
         | 
| 158 | 
            +
                    # @return [void]
         | 
| 159 | 
            +
                    def apply_verikloak_rails_configuration
         | 
| 160 | 
            +
                      rails_config = verikloak_rails_config
         | 
| 161 | 
            +
                      return unless rails_config
         | 
| 162 | 
            +
             | 
| 163 | 
            +
                      Verikloak::Audience.configure do |cfg|
         | 
| 164 | 
            +
                        sync_env_claims_key(cfg, rails_config)
         | 
| 165 | 
            +
                        sync_required_aud(cfg, rails_config)
         | 
| 166 | 
            +
                        sync_resource_client(cfg, rails_config)
         | 
| 167 | 
            +
                      end
         | 
| 168 | 
            +
                    end
         | 
| 169 | 
            +
             | 
| 170 | 
            +
                    private
         | 
| 171 | 
            +
             | 
| 172 | 
            +
                    # Resolve the verikloak-rails configuration object if the gem is loaded.
         | 
| 173 | 
            +
                    #
         | 
| 174 | 
            +
                    # @return [Verikloak::Rails::Configuration, nil]
         | 
| 175 | 
            +
                    def verikloak_rails_config
         | 
| 176 | 
            +
                      return unless defined?(::Verikloak::Rails)
         | 
| 177 | 
            +
                      return unless ::Verikloak::Rails.respond_to?(:config)
         | 
| 178 | 
            +
             | 
| 179 | 
            +
                      ::Verikloak::Rails.config
         | 
| 180 | 
            +
                    rescue StandardError
         | 
| 181 | 
            +
                      nil
         | 
| 182 | 
            +
                    end
         | 
| 183 | 
            +
             | 
| 184 | 
            +
                    # Align the environment claims key with the one configured in verikloak-rails.
         | 
| 185 | 
            +
                    #
         | 
| 186 | 
            +
                    # @param cfg [Verikloak::Audience::Configuration]
         | 
| 187 | 
            +
                    # @param rails_config [Verikloak::Rails::Configuration]
         | 
| 188 | 
            +
                    # @return [void]
         | 
| 189 | 
            +
                    def sync_env_claims_key(cfg, rails_config)
         | 
| 190 | 
            +
                      return unless rails_config.respond_to?(:user_env_key)
         | 
| 191 | 
            +
             | 
| 192 | 
            +
                      user_key = rails_config.user_env_key
         | 
| 193 | 
            +
                      return if blank?(user_key)
         | 
| 194 | 
            +
             | 
| 195 | 
            +
                      current = cfg.env_claims_key
         | 
| 196 | 
            +
                      return unless current.nil? || current == Verikloak::Audience::Configuration::DEFAULT_ENV_CLAIMS_KEY
         | 
| 197 | 
            +
             | 
| 198 | 
            +
                      cfg.env_claims_key = user_key
         | 
| 199 | 
            +
                    end
         | 
| 200 | 
            +
             | 
| 201 | 
            +
                    # Populate required audiences from the verikloak-rails configuration when absent.
         | 
| 202 | 
            +
                    #
         | 
| 203 | 
            +
                    # @param cfg [Verikloak::Audience::Configuration]
         | 
| 204 | 
            +
                    # @param rails_config [Verikloak::Rails::Configuration]
         | 
| 205 | 
            +
                    # @return [void]
         | 
| 206 | 
            +
                    def sync_required_aud(cfg, rails_config)
         | 
| 207 | 
            +
                      return unless cfg_required_aud_blank?(cfg)
         | 
| 208 | 
            +
                      return unless rails_config.respond_to?(:audience)
         | 
| 209 | 
            +
             | 
| 210 | 
            +
                      audiences = normalized_audiences(rails_config.audience)
         | 
| 211 | 
            +
                      return if audiences.empty?
         | 
| 212 | 
            +
             | 
| 213 | 
            +
                      cfg.required_aud = audiences.size == 1 ? audiences.first : audiences
         | 
| 214 | 
            +
                    end
         | 
| 215 | 
            +
             | 
| 216 | 
            +
                    # Infer the resource client based on the configured audience when possible.
         | 
| 217 | 
            +
                    #
         | 
| 218 | 
            +
                    # @param cfg [Verikloak::Audience::Configuration]
         | 
| 219 | 
            +
                    # @param rails_config [Verikloak::Rails::Configuration]
         | 
| 220 | 
            +
                    # @return [void]
         | 
| 221 | 
            +
                    def sync_resource_client(cfg, rails_config)
         | 
| 222 | 
            +
                      return unless rails_config.respond_to?(:audience)
         | 
| 223 | 
            +
             | 
| 224 | 
            +
                      audiences = normalized_audiences(rails_config.audience)
         | 
| 225 | 
            +
                      return unless audiences.size == 1
         | 
| 226 | 
            +
             | 
| 227 | 
            +
                      current_client = cfg.resource_client
         | 
| 228 | 
            +
                      unless blank?(current_client) || current_client == Verikloak::Audience::Configuration::DEFAULT_RESOURCE_CLIENT
         | 
| 229 | 
            +
                        return
         | 
| 230 | 
            +
                      end
         | 
| 231 | 
            +
             | 
| 232 | 
            +
                      cfg.resource_client = audiences.first
         | 
| 233 | 
            +
                    end
         | 
| 234 | 
            +
             | 
| 235 | 
            +
                    # Determine whether the audience configuration is effectively empty.
         | 
| 236 | 
            +
                    #
         | 
| 237 | 
            +
                    # @param cfg [Verikloak::Audience::Configuration]
         | 
| 238 | 
            +
                    # @return [Boolean]
         | 
| 239 | 
            +
                    def cfg_required_aud_blank?(cfg)
         | 
| 240 | 
            +
                      value_blank?(cfg.required_aud)
         | 
| 241 | 
            +
                    end
         | 
| 242 | 
            +
             | 
| 243 | 
            +
                    # Generic blank? helper that tolerates nil, empty, or blank-ish values.
         | 
| 244 | 
            +
                    #
         | 
| 245 | 
            +
                    # @param value [Object]
         | 
| 246 | 
            +
                    # @return [Boolean]
         | 
| 247 | 
            +
                    def value_blank?(value)
         | 
| 248 | 
            +
                      return true if value.nil?
         | 
| 249 | 
            +
                      return true if value.respond_to?(:empty?) && value.empty?
         | 
| 250 | 
            +
             | 
| 251 | 
            +
                      value.to_s.empty?
         | 
| 252 | 
            +
                    end
         | 
| 253 | 
            +
             | 
| 254 | 
            +
                    alias blank? value_blank?
         | 
| 255 | 
            +
             | 
| 256 | 
            +
                    # Coerce the given source into an array of non-empty string audiences.
         | 
| 257 | 
            +
                    #
         | 
| 258 | 
            +
                    # @param source [Object]
         | 
| 259 | 
            +
                    # @return [Array<String>]
         | 
| 260 | 
            +
                    def normalized_audiences(source)
         | 
| 261 | 
            +
                      Array(source).compact.map(&:to_s).reject(&:empty?)
         | 
| 262 | 
            +
                    end
         | 
| 263 | 
            +
                  end
         | 
| 98 264 | 
             
                end
         | 
| 99 265 | 
             
              end
         | 
| 100 266 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: verikloak-audience
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.2. | 
| 4 | 
            +
              version: 0.2.7
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - taiyaky
         | 
| @@ -59,6 +59,8 @@ files: | |
| 59 59 | 
             
            - CHANGELOG.md
         | 
| 60 60 | 
             
            - LICENSE
         | 
| 61 61 | 
             
            - README.md
         | 
| 62 | 
            +
            - lib/generators/verikloak/audience/install/install_generator.rb
         | 
| 63 | 
            +
            - lib/generators/verikloak/audience/install/templates/initializer.rb.erb
         | 
| 62 64 | 
             
            - lib/verikloak-audience.rb
         | 
| 63 65 | 
             
            - lib/verikloak/audience.rb
         | 
| 64 66 | 
             
            - lib/verikloak/audience/checker.rb
         | 
| @@ -74,7 +76,7 @@ metadata: | |
| 74 76 | 
             
              source_code_uri: https://github.com/taiyaky/verikloak-audience
         | 
| 75 77 | 
             
              changelog_uri: https://github.com/taiyaky/verikloak-audience/blob/main/CHANGELOG.md
         | 
| 76 78 | 
             
              bug_tracker_uri: https://github.com/taiyaky/verikloak-audience/issues
         | 
| 77 | 
            -
              documentation_uri: https://rubydoc.info/gems/verikloak-audience/0.2. | 
| 79 | 
            +
              documentation_uri: https://rubydoc.info/gems/verikloak-audience/0.2.7
         | 
| 78 80 | 
             
              rubygems_mfa_required: 'true'
         | 
| 79 81 | 
             
            rdoc_options: []
         | 
| 80 82 | 
             
            require_paths:
         |