<commit_before>require_relative 'hmac_signature'

# A Rack app to verify requests based on a computed signature passed within the
# HTTP Header: X-Auth-Sig.
#
# This app will rebuild the signature and then compare its own computed HMAC
# against the one sent from the client to verify authenticity.
#
module Rack
  module Signature
    class Verify
      attr_reader :options

      # Initializes the Rack Middleware
      #
      # ==== Attributes
      #
      # * +app+     - A Rack app
      # * +options+ - A hash of options
      #
      def initialize(app, options)
        @app, @options = app, options
      end

      def call(env)
        if signature_is_valid?(env)
          @app.call(env)
        else
          invalid_signature
        end
      end

      private

      # if the signature is invalid we send back this Rack app
      def invalid_signature
        [401, {'CONTENT_TYPE' => 'application/json'}, 'Access Denied']
      end

      # compares the received Signature against what the Signature should be
      # (computed signature)
      def signature_is_valid?(env)
        return true if html_request?(env)

        # grab and compute the X-AUTH-SIG
        signature_sent    = env["X_AUTH_SIG"]
        actual_signature  = compute_signature(env)

        # are they the same?
        signature_sent.to_s == actual_signature.to_s
      end

      # builds the request message and tells HmacSignature to sign the message
      def compute_signature(env)
        message = BuildMessage.new(env).build!
        HmacSignature.new(shared_key(env), message).sign
      end

      # FIXME: This is here for now for a quick implementation within another
      # app. This will eventually need to be a rack app itself
      def shared_key(env)
        token = (env[options[:token]] || "")
        return '' if token.nil? || token == ''

        shared_token = options[:klass].send(options[:method].to_s, token)
        shared_token.to_s
      end

      # we only want to use this if the request is an api request
      def html_request?(env)
        debug(env) if options[:debug]
        (env['CONTENT_TYPE'] || "").to_s !~ /json/i
      end

      def debug(env)
        builder = BuildMessage.new(env)
        log "SHARED_KEY from Rails:     #{shared_key(env).inspect}"
        log "CONTENT_TYPE of request:   #{env['CONTENT_TYPE'].inspect}"
        log "QUERY SENT:                #{builder.query.inspect}"
        log "MESSAGE built by rails:    #{builder.build!.inspect}"
        log "HMAC built by rails:       #{HmacSignature.new(shared_key(env), builder.build!).sign.inspect}"
        log "HMAC received from client  #{env['X_AUTH_SIG'].inspect}"
      end

      def log(msg)
        STDOUT.puts(msg)
      end

    end
  end
end<commit_msg>one more thing to debug<commit_after>require_relative 'hmac_signature'

# A Rack app to verify requests based on a computed signature passed within the
# HTTP Header: X-Auth-Sig.
#
# This app will rebuild the signature and then compare its own computed HMAC
# against the one sent from the client to verify authenticity.
#
module Rack
  module Signature
    class Verify
      attr_reader :options

      # Initializes the Rack Middleware
      #
      # ==== Attributes
      #
      # * +app+     - A Rack app
      # * +options+ - A hash of options
      #
      def initialize(app, options)
        @app, @options = app, options
      end

      def call(env)
        if signature_is_valid?(env)
          @app.call(env)
        else
          invalid_signature
        end
      end

      private

      # if the signature is invalid we send back this Rack app
      def invalid_signature
        [401, {'CONTENT_TYPE' => 'application/json'}, 'Access Denied']
      end

      # compares the received Signature against what the Signature should be
      # (computed signature)
      def signature_is_valid?(env)
        return true if html_request?(env)

        # grab and compute the X-AUTH-SIG
        signature_sent    = env["X_AUTH_SIG"]
        actual_signature  = compute_signature(env)

        # are they the same?
        signature_sent.to_s == actual_signature.to_s
      end

      # builds the request message and tells HmacSignature to sign the message
      def compute_signature(env)
        message = BuildMessage.new(env).build!
        HmacSignature.new(shared_key(env), message).sign
      end

      # FIXME: This is here for now for a quick implementation within another
      # app. This will eventually need to be a rack app itself
      def shared_key(env)
        token = (env[options[:header_token]] || "")
        return '' if token.nil? || token == ''

        shared_token = options[:klass].send(options[:method].to_s, token)
        shared_token.to_s
      end

      # we only want to use this if the request is an api request
      def html_request?(env)
        debug(env) if options[:debug]
        (env['CONTENT_TYPE'] || "").to_s !~ /json/i
      end

      def debug(env)
        builder = BuildMessage.new(env)
        log "CALL RAILS MODEL:          #{options[:klass].send(options[:method].to_s, (env[options[:header_token]]))}"
        log "SHARED_KEY from Rails:     #{shared_key(env).inspect}"
        log "CONTENT_TYPE of request:   #{env['CONTENT_TYPE'].inspect}"
        log "QUERY SENT:                #{builder.query.inspect}"
        log "MESSAGE built by rails:    #{builder.build!.inspect}"
        log "HMAC built by rails:       #{HmacSignature.new(shared_key(env), builder.build!).sign.inspect}"
        log "HMAC received from client  #{env['X_AUTH_SIG'].inspect}"
      end

      def log(msg)
        STDOUT.puts(msg)
      end

    end
  end
end
{'fraction_non_alphanumeric': 0.09257303766279479, 'fraction_numerical': 0.0010559662090813093, 'mean_word_length': 2.3156359393232204, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5189231', 'n_tokens_mistral': 1660, 'n_tokens_neox': 1628, 'n_words': 521}