Module: Roda::RodaPlugins::HmacPaths::InstanceMethods

Defined in:
lib/roda/plugins/hmac_paths.rb

Instance Method Summary collapse

Instance Method Details

#hmac_path(path, opts = OPTS) ⇒ Object

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.



235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
# File 'lib/roda/plugins/hmac_paths.rb', line 235

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

  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

  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

#hmac_path_hmac(root, path, opts = OPTS) ⇒ Object

The HMAC to use in hmac_path, for the given root, path, and options.



273
274
275
# File 'lib/roda/plugins/hmac_paths.rb', line 273

def hmac_path_hmac(root, path, opts=OPTS)
  OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA256.new, hmac_path_hmac_secret(root, opts), path)
end

#hmac_path_namespace(opts = OPTS) ⇒ Object

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.



280
281
282
# File 'lib/roda/plugins/hmac_paths.rb', line 280

def hmac_path_namespace(opts=OPTS)
  opts.fetch(:namespace){hmac_path_default_namespace}
end