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
41 42 43 44 45 46 |
# File 'lib/hmac/signer.rb', line 41 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.
12 13 14 |
# File 'lib/hmac/signer.rb', line 12 def algorithm @algorithm end |
#default_opts ⇒ Object
Returns the value of attribute default_opts.
12 13 14 |
# File 'lib/hmac/signer.rb', line 12 def default_opts @default_opts end |
#secret ⇒ Object
Returns the value of attribute secret.
12 13 14 |
# File 'lib/hmac/signer.rb', line 12 def secret @secret end |
Instance Method Details
#canonical_representation(params) ⇒ String
generates the canonical representation for a given request
156 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 |
# File 'lib/hmac/signer.rb', line 156 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
72 73 74 75 76 77 78 79 80 81 |
# File 'lib/hmac/signer.rb', line 72 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
207 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 |
# File 'lib/hmac/signer.rb', line 207 def sign_request(url, secret, opts = {}) opts = default_opts.merge(opts) uri = parse_url(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 = Rack::Utils.parse_nested_query(uri.query) 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 ||= {} query_values[opts[:auth_param]] = auth_params uri.query = Rack::Utils.build_nested_query(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
262 263 264 265 266 267 268 |
# File 'lib/hmac/signer.rb', line 262 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
106 107 108 |
# File 'lib/hmac/signer.rb', line 106 def validate_signature(signature, params) compare_hashes(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
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/hmac/signer.rb', line 119 def validate_url_signature(url, secret, opts = {}) opts = default_opts.merge(opts) opts[:query_based] = true uri = parse_url(url) query_values = Rack::Utils.parse_nested_query(uri.query) 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 |