module Roda::RodaPlugins::HmacPaths::InstanceMethods
Public Instance Methods
Source
# File lib/roda/plugins/hmac_paths.rb, line 252 def hmac_path(path, opts=OPTS) unless path.is_a?(String) && path.getbyte(0) == 47 raise RodaError, "path must be a string starting with /" end root = opts[:root] || '' unless root.is_a?(String) && ((root_byte = root.getbyte(0)) == 47 || root_byte == nil) raise RodaError, "root must be empty string or string starting with /" end if valid_until = opts[:until] valid_until = valid_until.to_i elsif seconds = opts[:seconds] valid_until = Time.now.to_i + seconds end flags = String.new path = path.dup if method = opts[:method] flags << 'm' end if params = opts[:params] flags << 'p' path << '?' << Rack::Utils.build_query(params) end if hmac_path_namespace(opts) flags << 'n' end if valid_until flags << 't' path = "/#{valid_until}#{path}" end flags << '0' if flags.empty? hmac_path = if method "#{method.to_s.upcase}:/#{flags}#{path}" else "/#{flags}#{path}" end "#{root}/#{hmac_path_hmac(root, hmac_path, opts)}/#{flags}#{path}" end
Return a path with an HMAC. Designed to be used with r.hmac_path, to make sure users can only request paths that they have been provided by the application (directly or indirectly). This can prevent users of a site from enumerating valid paths. The given path should be a string starting with /
. Options:
- :method
-
Limits the returned path to only be valid for the given request method.
- :namespace
-
Make the HMAC value depend on the given namespace. If this is not provided, the default namespace is used. To explicitly not use a namespace when there is a default namespace, pass a nil value.
- :params
-
Includes parameters in the query string of the returned path, and limits the returned path to only be valid for that exact query string.
- :root
-
Should be an empty string or string starting with
/
. This will be the already matched path of the routing tree using r.hmac_path. Defaults to the empty string, which will returns paths valid for r.hmac_path at the top level of the routing tree. - :seconds
-
Make the given path valid for the given integer number of seconds.
- :until
-
Make the given path valid until the given Time.
Source
# File lib/roda/plugins/hmac_paths.rb, line 301 def hmac_path_hmac(root, path, opts=OPTS) OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA256.new, hmac_path_hmac_secret(root, opts), path) end
The HMAC to use in hmac_path
, for the given root, path, and options.
Source
# File lib/roda/plugins/hmac_paths.rb, line 308 def hmac_path_namespace(opts=OPTS) opts.fetch(:namespace){hmac_path_default_namespace} end
The namespace to use for the hmac path. If a :namespace option is not provided, and a :namespace_session_key option was provided, this will use the value of the related session key, if present.
Private Instance Methods
Source
# File lib/roda/plugins/hmac_paths.rb, line 328 def hmac_path_default_namespace if (key = opts[:hmac_paths_namespace_session_key]) && (value = session[key]) value.to_s end end
The default namespace to use for hmac_path
, if a :namespace option is not provided.
Source
# File lib/roda/plugins/hmac_paths.rb, line 317 def hmac_path_hmac_secret(root, opts=OPTS) secret = opts[:secret] || self.opts[:hmac_paths_secret] if namespace = hmac_path_namespace(opts) secret = OpenSSL::HMAC.digest(OpenSSL::Digest::SHA256.new, secret, namespace) end OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA256.new, secret, root) end
The secret used to calculate the HMAC in hmac_path. This is itself an HMAC, created using the secret given in the plugin, for the given root and options. This always returns a hexidecimal string.