Class: HMAC::Signer
- Inherits:
-
Object
- Object
- HMAC::Signer
- Defined in:
- lib/hmac/signer.rb
Overview
Helper class that provides signing capabilites for the hmac strategies.
Constant Summary collapse
- DEFAULT_OPTS =
{ :auth_scheme => "HMAC", :auth_param => "auth", :auth_header => "Authorization", :auth_header_format => "%{auth_scheme} %{signature}", :query_based => false, :use_alternate_date_header => false, :extra_auth_params => {}, :ignore_params => [] }
Instance Attribute Summary collapse
-
#algorithm ⇒ Object
Returns the value of attribute algorithm.
-
#default_opts ⇒ Object
Returns the value of attribute default_opts.
-
#secret ⇒ Object
Returns the value of attribute secret.
Instance Method Summary collapse
-
#canonical_representation(params) ⇒ String
generates the canonical representation for a given request.
-
#generate_signature(params) ⇒ String
Generate the signature from a hash representation.
-
#initialize(algorithm = "sha1", default_opts = {}) ⇒ Signer
constructor
create a new HMAC instance.
-
#sign_request(url, secret, opts = {}) ⇒ Object
sign the given request.
-
#sign_url(url, secret, opts = {}) ⇒ String
convienience method to sign a url for use with query-based authentication.
-
#validate_signature(signature, params) ⇒ Bool
compares the given signature with the signature created from a hash representation.
-
#validate_url_signature(url, secret, opts = {}) ⇒ Bool
convienience method to check the signature of a url with query-based authentication.
Constructor Details
#initialize(algorithm = "sha1", default_opts = {}) ⇒ Signer
create a new HMAC instance
42 43 44 45 46 47 |
# File 'lib/hmac/signer.rb', line 42 def initialize(algorithm = "sha1", default_opts = {}) self.algorithm = algorithm default_opts[:nonce_header] ||="X-%{scheme}-Nonce" % {:scheme => (default_opts[:auth_scheme] || "HMAC")} default_opts[:alternate_date_header] ||= "X-%{scheme}-Date" % {:scheme => (default_opts[:auth_scheme] || "HMAC")} self.default_opts = DEFAULT_OPTS.merge(default_opts) end |
Instance Attribute Details
#algorithm ⇒ Object
Returns the value of attribute algorithm.
13 14 15 |
# File 'lib/hmac/signer.rb', line 13 def algorithm @algorithm end |
#default_opts ⇒ Object
Returns the value of attribute default_opts.
13 14 15 |
# File 'lib/hmac/signer.rb', line 13 def default_opts @default_opts end |
#secret ⇒ Object
Returns the value of attribute secret.
13 14 15 |
# File 'lib/hmac/signer.rb', line 13 def secret @secret end |
Instance Method Details
#canonical_representation(params) ⇒ String
generates the canonical representation for a given request
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
# File 'lib/hmac/signer.rb', line 157 def canonical_representation(params) rep = "" rep << "#{params[:method].upcase}\n" rep << "date:#{params[:date]}\n" rep << "nonce:#{params[:nonce]}\n" (params[:headers] || {}).sort.each do |pair| name,value = *pair rep << "#{name.downcase}:#{value}\n" end rep << params[:path] p = (params[:query] || {}).dup if !p.empty? query = p.sort.map do |key, value| "%{key}=%{value}" % { :key => Rack::Utils.unescape(key.to_s), :value => Rack::Utils.unescape(value.to_s) } end.join("&") rep << "?#{query}" end rep end |
#generate_signature(params) ⇒ String
Generate the signature from a hash representation
returns nil if no secret or an empty secret was given
73 74 75 76 77 78 79 80 81 82 |
# File 'lib/hmac/signer.rb', line 73 def generate_signature(params) secret = params.delete(:secret) # jruby stumbles over empty secrets, we regard them as invalid anyways, so we return an empty digest if no scret was given if '' == secret.to_s nil else OpenSSL::HMAC.hexdigest(algorithm, secret, canonical_representation(params)) end end |
#sign_request(url, secret, opts = {}) ⇒ Object
sign the given request
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 |
# File 'lib/hmac/signer.rb', line 208 def sign_request(url, secret, opts = {}) opts = default_opts.merge(opts) uri = Addressable::URI.parse(url) headers = opts[:headers] || {} date = opts[:date] || Time.now.gmtime date = date.gmtime.strftime('%a, %e %b %Y %T GMT') if date.respond_to? :strftime method = opts[:method] ? opts[:method].to_s.upcase : "GET" query_values = uri.query_values if query_values query_values.delete_if do |k,v| opts[:ignore_params].one? { |param| (k == param) || (k == param.to_s) } end end signature = generate_signature(:secret => secret, :method => method, :path => uri.path, :date => date, :nonce => opts[:nonce], :query => query_values, :headers => opts[:headers], :ignore_params => opts[:ignore_params]) if opts[:query_based] auth_params = opts[:extra_auth_params].merge({ "date" => date, "signature" => signature }) auth_params[:nonce] = opts[:nonce] unless opts[:nonce].nil? query_values = uri.query_values || {} query_values[opts[:auth_param]] = auth_params uri.query_values = query_values else headers[opts[:auth_header]] = opts[:auth_header_format] % opts.merge({:signature => signature}) headers[opts[:nonce_header]] = opts[:nonce] unless opts[:nonce].nil? if opts[:use_alternate_date_header] headers[opts[:alternate_date_header]] = date else headers["Date"] = date end end [headers, uri.to_s] end |
#sign_url(url, secret, opts = {}) ⇒ String
convienience method to sign a url for use with query-based authentication
263 264 265 266 267 268 269 |
# File 'lib/hmac/signer.rb', line 263 def sign_url(url, secret, opts = {}) opts = default_opts.merge(opts) opts[:query_based] = true headers, url = *sign_request(url, secret, opts) url end |
#validate_signature(signature, params) ⇒ Bool
compares the given signature with the signature created from a hash representation
107 108 109 |
# File 'lib/hmac/signer.rb', line 107 def validate_signature(signature, params) signature == generate_signature(params) end |
#validate_url_signature(url, secret, opts = {}) ⇒ Bool
convienience method to check the signature of a url with query-based authentication
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/hmac/signer.rb', line 120 def validate_url_signature(url, secret, opts = {}) opts = default_opts.merge(opts) opts[:query_based] = true uri = Addressable::URI.parse(url) query_values = uri.query_values return false unless query_values auth_params = query_values.delete(opts[:auth_param]) return false unless auth_params date = auth_params["date"] nonce = auth_params["nonce"] validate_signature(auth_params["signature"], :secret => secret, :method => "GET", :path => uri.path, :date => date, :nonce => nonce, :query => query_values, :headers => {}) end |