Class: Rack::Contrib::Sign::Middleware
- Inherits:
-
Object
- Object
- Rack::Contrib::Sign::Middleware
- Defined in:
- lib/rack/contrib/sign/middleware.rb
Instance Method Summary collapse
-
#build_receipt(env, credentials) ⇒ Object
Extract environmental data into a Receipt.
- #call(env) ⇒ Object
-
#extract_body(env) ⇒ Object
Extract the body from the environment, ensuring to rewind the input back to zero, so future access gets the arguments.
-
#extract_credentials(auth_header) ⇒ Object
Pass in the Authorization header, and get back the key and signature.
-
#extract_headers(env) ⇒ Object
Extract all the headers with our Prefix from the ENV and return the hash.
- #get_secret(api_key) ⇒ Object
-
#initialize(app, opts) ⇒ Middleware
constructor
A new instance of Middleware.
Constructor Details
#initialize(app, opts) ⇒ Middleware
Returns a new instance of Middleware.
6 7 8 9 10 11 12 13 |
# 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 |
Instance Method Details
#build_receipt(env, credentials) ⇒ Object
Extract environmental data into a Receipt
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# 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) ⇒ Object
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# 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) ⇒ Object
Extract the body from the environment, ensuring to rewind the input back to zero, so future access gets the arguments.
75 76 77 78 79 |
# 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) ⇒ Object
Pass in the Authorization header, and get back the key and signature.
97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# 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) ⇒ Object
Extract all the headers with our Prefix from the ENV and return the hash
83 84 85 86 87 88 89 90 91 92 93 |
# 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) ⇒ Object
112 113 114 115 116 |
# 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 |