class Rack::Contrib::Sign::Middleware
Public Class Methods
new(app, opts)
click to toggle source
# File lib/rack/contrib/sign/middleware.rb, line 6 def initialize app, opts @app = app @logger = opts[:logger] @realm = opts[:realm] @credentials = opts[:credentials] || {} @header_prefix = (opts[:prefix] || "").gsub(/-/, '_').downcase end
Public Instance Methods
build_receipt(env, credentials)
click to toggle source
Extract environmental data into a Receipt
# File lib/rack/contrib/sign/middleware.rb, line 48 def build_receipt env, credentials req = Rack::Request.new(env) receipt = Rack::Contrib::Sign::Receipt.new port = '' unless ( (req.scheme == 'http' && req.port.to_s == '80') || (req.scheme == 'https' && req.port.to_s == '443')) port = ':' + req.port.to_s end receipt.host = req.scheme + '://' + req.host + port receipt.uri = env['REQUEST_URI'] receipt.request_method = env['REQUEST_METHOD'] receipt.body = extract_body env receipt.content_type = env['HTTP_CONTENT_TYPE'] || '' extract_headers(env).each { |h,v| receipt.headers[h] = v } receipt.api_key = credentials[:key] receipt.api_secret = get_secret(credentials[:key]) receipt end
call(env)
click to toggle source
# File lib/rack/contrib/sign/middleware.rb, line 15 def call env creds = extract_credentials env['HTTP_AUTHORIZATION'] unless creds @logger.info "Denied: Authorization header not present or invalid." return [401, {}, []] end receipt = build_receipt env, creds unless receipt.api_secret @logger.info "Denied: API key not recognized." return [401, {}, []] end sign = receipt.to_s digest = OpenSSL::Digest::Digest.new('sha1') validation = OpenSSL::HMAC.hexdigest(digest, receipt.api_secret, sign) unless validation == creds[:signature] @logger.error "Denied: Authorization signature does not match" @logger.info "Denied: EXPECTED: %s GOT: %s" % [ validation, creds[:signature] ] @logger.debug "Generated signing data:" @logger.debug sign return [401, {}, []] end @app.call env end
extract_body(env)
click to toggle source
Extract the body from the environment, ensuring to rewind the input back to zero, so future access gets the arguments.
# File lib/rack/contrib/sign/middleware.rb, line 75 def extract_body env env['rack.input'].read ensure env['rack.input'].rewind end
extract_credentials(auth_header)
click to toggle source
Pass in the Authorization header, and get back the key and signature.
# File lib/rack/contrib/sign/middleware.rb, line 97 def extract_credentials auth_header return false if auth_header.nil? pattern = /^(?<realm>.*) (?<api_key>.*):(?<signature>.*)$/ matches = auth_header.match(pattern) return false if matches.nil? return false unless matches[:realm] == @realm { key: matches[:api_key], signature: matches[:signature] } end
extract_headers(env)
click to toggle source
Extract all the headers with our Prefix from the ENV and return the hash
# File lib/rack/contrib/sign/middleware.rb, line 83 def extract_headers env headers = {} env.sort_by { |k,v| k.to_s.downcase }.each do |key,val| next unless key =~ /^http_#{@header_prefix}/i header = key.sub(/^http_/i, '').gsub(/_/, '-') headers[header] = val end headers end
get_secret(api_key)
click to toggle source
# File lib/rack/contrib/sign/middleware.rb, line 112 def get_secret api_key return false unless @credentials.has_key? api_key return @credentials.fetch(api_key) end