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.

:seconds

Make the given path valid for the given integer number of seconds.

:until

Make the given path valid until the given Time.



252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
# 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

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

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



301
302
303
# 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

#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.



308
309
310
# File 'lib/roda/plugins/hmac_paths.rb', line 308

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