Class: AuthHMAC
- Inherits:
-
Object
- Object
- AuthHMAC
- Includes:
- Headers
- Defined in:
- lib/auth-hmac.rb,
lib/auth-hmac/version.rb
Overview
This module provides a HMAC Authentication method for HTTP requests. It should work with net/http request classes and CGIRequest classes and hence Rails.
It is loosely based on the Amazon Web Services Authentication mechanism but generalized to be useful to any application that requires HMAC based authentication. As a result of the generalization, it won’t work with AWS because it doesn’t support the Amazon extension headers.
References
- Cryptographic Hash functions
- SHA-1 Hash function
- HMAC algorithm
- RFC 2104
Defined Under Namespace
Modules: Headers, VERSION Classes: CanonicalString, Rails
Constant Summary collapse
- @@default_signature_class =
CanonicalString
Class Method Summary collapse
-
.authenticated?(request, access_key_id, secret, options) ⇒ Boolean
Authenticates a request using HMAC.
-
.canonical_string(request, options = nil) ⇒ Object
Generates canonical signing string for given request.
-
.sign!(request, access_key_id, secret, options = nil) ⇒ Object
Signs a request using a given access key id and secret.
-
.signature(request, secret, options = nil) ⇒ Object
Generates signature string for a given secret.
Instance Method Summary collapse
-
#authenticated?(request) ⇒ Boolean
Authenticates a request using HMAC.
- #authorization(request, access_key_id, secret) ⇒ Object
- #authorization_header(request) ⇒ Object
- #canonical_string(request) ⇒ Object
-
#initialize(credential_store, options = nil) ⇒ AuthHMAC
constructor
Create an AuthHMAC instance using the given credential store.
-
#sign!(request, access_key_id) ⇒ Object
Signs a request using the access_key_id and the secret associated with that id in the credential store.
- #signature(request, secret) ⇒ Object
Methods included from Headers
Constructor Details
#initialize(credential_store, options = nil) ⇒ AuthHMAC
Create an AuthHMAC instance using the given credential store
Credential Store:
-
Credential store must respond to the [] method and return a secret for access key id
Options: Override default options
-
:service_id
- Service ID used in the AUTHORIZATION header string. Default is AuthHMAC. -
:signature_method
- Proc object that takes request and produces the signature stringused for authentication. Default is CanonicalString.
Examples:
my_hmac = AuthHMAC.new('access_id1' => 'secret1', 'access_id2' => 'secret2')
cred_store = { 'access_id1' => 'secret1', 'access_id2' => 'secret2' }
= { :service_id => 'MyApp', :signature_method => lambda { |r| MyRequestString.new(r) } }
my_hmac = AuthHMAC.new(cred_store, )
139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/auth-hmac.rb', line 139 def initialize(credential_store, = nil) @credential_store = credential_store # Defaults @service_id = self.class.name @signature_class = @@default_signature_class unless .nil? @service_id = [:service_id] if .key?(:service_id) @signature_class = [:signature] if .key?(:signature) && [:signature].is_a?(Class) end @signature_method = lambda { |r| @signature_class.send(:new, r) } end |
Class Method Details
.authenticated?(request, access_key_id, secret, options) ⇒ Boolean
Authenticates a request using HMAC
Supports same options as AuthHMAC.initialize for overriding service_id and signature method.
187 188 189 190 |
# File 'lib/auth-hmac.rb', line 187 def AuthHMAC.authenticated?(request, access_key_id, secret, ) credentials = { access_key_id => secret } self.new(credentials, ).authenticated?(request) end |
.canonical_string(request, options = nil) ⇒ Object
Generates canonical signing string for given request
Supports same options as AuthHMAC.initialize for overriding service_id and signature method.
159 160 161 |
# File 'lib/auth-hmac.rb', line 159 def AuthHMAC.canonical_string(request, = nil) self.new(nil, ).canonical_string(request) end |
.sign!(request, access_key_id, secret, options = nil) ⇒ Object
Signs a request using a given access key id and secret.
Supports same options as AuthHMAC.initialize for overriding service_id and signature method.
177 178 179 180 |
# File 'lib/auth-hmac.rb', line 177 def AuthHMAC.sign!(request, access_key_id, secret, = nil) credentials = { access_key_id => secret } self.new(credentials, ).sign!(request, access_key_id) end |
.signature(request, secret, options = nil) ⇒ Object
Generates signature string for a given secret
Supports same options as AuthHMAC.initialize for overriding service_id and signature method.
168 169 170 |
# File 'lib/auth-hmac.rb', line 168 def AuthHMAC.signature(request, secret, = nil) self.new(nil, ).signature(request, secret) end |
Instance Method Details
#authenticated?(request) ⇒ Boolean
Authenticates a request using HMAC
Returns true if the request has an AuthHMAC Authorization header and the access id and HMAC match an id and HMAC produced for the secret in the credential store. Otherwise returns false.
213 214 215 216 217 218 219 220 221 222 223 |
# File 'lib/auth-hmac.rb', line 213 def authenticated?(request) rx = Regexp.new("#{@service_id} ([^:]+):(.+)$") if md = rx.match((request)) access_key_id = md[1] hmac = md[2] secret = @credential_store[access_key_id] !secret.nil? && hmac == signature(request, secret) else false end end |
#authorization(request, access_key_id, secret) ⇒ Object
238 239 240 |
# File 'lib/auth-hmac.rb', line 238 def (request, access_key_id, secret) "#{@service_id} #{access_key_id}:#{signature(request, secret)}" end |
#authorization_header(request) ⇒ Object
234 235 236 |
# File 'lib/auth-hmac.rb', line 234 def (request) find_header(%w(Authorization HTTP_AUTHORIZATION), headers(request)) end |
#canonical_string(request) ⇒ Object
230 231 232 |
# File 'lib/auth-hmac.rb', line 230 def canonical_string(request) @signature_method.call(request) end |
#sign!(request, access_key_id) ⇒ Object
Signs a request using the access_key_id and the secret associated with that id in the credential store.
Signing a requests adds an Authorization header to the request in the format:
<service_id> <access_key_id>:<signature>
where <signature> is the Base64 encoded HMAC-SHA1 of the CanonicalString and the secret.
201 202 203 204 205 |
# File 'lib/auth-hmac.rb', line 201 def sign!(request, access_key_id) secret = @credential_store[access_key_id] raise ArgumentError, "No secret found for key id '#{access_key_id}'" if secret.nil? request['Authorization'] = (request, access_key_id, secret) end |
#signature(request, secret) ⇒ Object
225 226 227 228 |
# File 'lib/auth-hmac.rb', line 225 def signature(request, secret) digest = OpenSSL::Digest::Digest.new('sha1') Base64.encode64(OpenSSL::HMAC.digest(digest, secret, canonical_string(request))).strip end |