Module: EY::ApiHMAC

Defined in:
lib/ey_api_hmac.rb,
lib/ey_api_hmac/sso.rb,
lib/ey_api_hmac/version.rb,
lib/ey_api_hmac/api_auth.rb,
lib/ey_api_hmac/base_connection.rb,
lib/ey_api_hmac/authed_connection.rb

Defined Under Namespace

Modules: ApiAuth, SSO Classes: AuthedConnection, BaseConnection, HmacAuthFail

Constant Summary collapse

VERSION =
"0.4.12"

Class Method Summary collapse

Class Method Details

.auth_string(key_id, signature) ⇒ Object



33
34
35
# File 'lib/ey_api_hmac.rb', line 33

def self.auth_string(key_id, signature)
  "AuthHMAC #{key_id}:#{signature}"
end

.authenticate!(env, &lookup) ⇒ Object



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/ey_api_hmac.rb', line 52

def self.authenticate!(env, &lookup)
  rx = Regexp.new("AuthHMAC ([^:]+):(.+)$")
  if md = rx.match(env["HTTP_AUTHORIZATION"])
    access_key_id = md[1]
    hmac = md[2]
    secret = lookup.call(access_key_id)
    unless secret
      raise HmacAuthFail, "couldn't find auth for #{access_key_id}"
    end
    unless hmac == signature(env, secret) || hmac == signature_legacy(env, secret)
      raise HmacAuthFail, "signature mismatch. Calculated canonical_string: #{canonical_string(env).inspect}"
    end
  else
    raise HmacAuthFail, "no authorization header"
  end
end

.authenticated?(env, &lookup) ⇒ Boolean

Returns:

  • (Boolean)


69
70
71
72
73
74
75
76
# File 'lib/ey_api_hmac.rb', line 69

def self.authenticated?(env, &lookup)
  begin
    authenticate!(env, &lookup)
    true
  rescue HmacAuthFail => e
    false
  end
end

.base64digest(data, secret) ⇒ Object



45
46
47
48
# File 'lib/ey_api_hmac.rb', line 45

def self.base64digest(data,secret)
  digest = OpenSSL::Digest.new('sha1')
  [OpenSSL::HMAC.digest(digest, secret, data)].pack('m').strip
end

.canonical_string(env, legacy = false) ⇒ Object



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/ey_api_hmac.rb', line 13

def self.canonical_string(env, legacy = false)
  parts = []
  expect = Proc.new do |var|
    unless env[var]
      raise HmacAuthFail, "'#{var}' header missing and required in #{env.inspect}"
    end
    env[var]
  end
  parts << expect["REQUEST_METHOD"]
  parts << env["CONTENT_TYPE"]
  parts << generated_md5(env, legacy)
  parts << expect["HTTP_DATE"]
  if env["REQUEST_URI"]
    parts << URI.parse(env["REQUEST_URI"]).path
  else
    parts << (env["SCRIPT_NAME"] + expect["PATH_INFO"])
  end
  parts.join("\n")
end

.sign!(env, key_id, secret) ⇒ Object



9
10
11
# File 'lib/ey_api_hmac.rb', line 9

def self.sign!(env, key_id, secret)
  env["HTTP_AUTHORIZATION"] = auth_string(key_id, signature(env, secret))
end

.signature(env, secret) ⇒ Object



37
38
39
# File 'lib/ey_api_hmac.rb', line 37

def self.signature(env, secret)
  base64digest(canonical_string(env), secret)
end

.signature_legacy(env, secret) ⇒ Object



41
42
43
# File 'lib/ey_api_hmac.rb', line 41

def self.signature_legacy(env, secret)
  base64digest(canonical_string(env, true), secret)
end