module Roda::RodaPlugins::HmacPaths::InstanceMethods
def hmac_path(path, opts=OPTS)
:seconds :: Make the given path valid for the given integer number of seconds.
the top level of the routing tree.
to the empty string, which will returns paths valid for r.hmac_path at
the already matched path of the routing tree using r.hmac_path. Defaults
:root :: Should be an empty string or string starting with +/+. This will be
limits the returned path to only be valid for that exact query string.
:params :: Includes parameters in the query string of the returned path, and
namespace when there is a default namespace, pass a nil value.
provided, the default namespace is used. To explicitly not use a
:namespace :: Make the HMAC value depend on the given namespace. If this is not
:method :: Limits the returned path to only be valid for the given request method.
valid paths. The given path should be a string starting with +/+. Options:
(directly or indirectly). This can prevent users of a site from enumerating
users can only request paths that they have been provided by the application
Return a path with an HMAC. Designed to be used with r.hmac_path, to make sure
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
def hmac_path_default_namespace
def hmac_path_default_namespace if (key = opts[:hmac_paths_namespace_session_key]) && (value = session[key]) value.to_s end end
def hmac_path_hmac(root, path, opts=OPTS)
def hmac_path_hmac(root, path, opts=OPTS) OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA256.new, hmac_path_hmac_secret(root, opts), path) end
def hmac_path_hmac_secret(root, opts=OPTS)
using the secret given in the plugin, for the given root and options.
The secret used to calculate the HMAC in hmac_path. This is itself an HMAC, created
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
def hmac_path_namespace(opts=OPTS)
provided, and a :namespace_session_key option was provided, this will
The namespace to use for the hmac path. If a :namespace option is not
def hmac_path_namespace(opts=OPTS) opts.fetch(:namespace){hmac_path_default_namespace} end