Module: Roda::RodaPlugins::RouteCsrf::InstanceMethods

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

Instance Method Summary collapse

Instance Method Details

#check_csrf!(opts = OPTS, &block) ⇒ Object

Check that the submitted CSRF token is valid, if the request requires a CSRF token. If the CSRF token is valid or the request does not require a CSRF token, return nil. Otherwise, if a block is given, treat it as a routing block and yield to it, and if a block is not given, use the :csrf_failure option to determine how to handle it.



220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
# File 'lib/roda/plugins/route_csrf.rb', line 220

def check_csrf!(opts=OPTS, &block)
  if msg = csrf_invalid_message(opts)
    if block
      @_request.on(&block)
    end
    
    case failure_action = opts.fetch(:csrf_failure, csrf_options[:csrf_failure])
    when :raise
      raise InvalidToken, msg
    when :empty_403
      @_response.status = 403
      headers = @_response.headers
      headers.clear
      headers[RodaResponseHeaders::CONTENT_TYPE] = 'text/html'
      headers[RodaResponseHeaders::CONTENT_LENGTH] ='0'
      throw :halt, @_response.finish_with_body([])
    when :clear_session
      RodaPlugins.warn "Passing :clear_session as the :csrf_failure option to check_csrf! is deprecated"
      session.clear
    when :csrf_failure_method
      @_request.on{_roda_route_csrf_failure(@_request)}
    when Proc
      RodaPlugins.warn "Passing a Proc as the :csrf_failure option value to check_csrf! is deprecated"
      @_request.on{instance_exec(@_request, &failure_action)} # Deprecated
    else
      raise RodaError, "Unsupported :csrf_failure option: #{failure_action.inspect}"
    end
  end
end

#csrf_fieldObject

The name of the hidden input tag containing the CSRF token. Also used as the name for the meta tag.



252
253
254
# File 'lib/roda/plugins/route_csrf.rb', line 252

def csrf_field
  csrf_options[:field]
end

#csrf_formaction_tag(path, *args) ⇒ Object

An HTML hidden input tag string containing the CSRF token, used for inputs with formaction, so the same form can be used to submit to multiple endpoints depending on which button was clicked. See csrf_token for arguments, but the path argument is required.



290
291
292
# File 'lib/roda/plugins/route_csrf.rb', line 290

def csrf_formaction_tag(path, *args)
  "<input type=\"hidden\" name=\"#{csrf_options[:formaction_field]}[#{Rack::Utils.escape_html(path)}]\" value=\"#{csrf_token(path, *args)}\" \/>"
end

#csrf_headerObject

The HTTP header name to use when submitting CSRF tokens in an HTTP header, if such support is enabled (it is not by default).



258
259
260
# File 'lib/roda/plugins/route_csrf.rb', line 258

def csrf_header
  csrf_options[:header]
end

#csrf_metatagObject

An HTML meta tag string containing a CSRF token that is not request-specific. It is not recommended to use this, as it doesn't support request-specific tokens.



264
265
266
# File 'lib/roda/plugins/route_csrf.rb', line 264

def csrf_metatag
  "<meta name=\"#{csrf_field}\" content=\"#{csrf_token}\" \/>"
end

#csrf_path(action) ⇒ Object

Given a form action, return the appropriate path to use for the CSRF token. This makes it easier to generate request-specific tokens without having to worry about the different types of form actions (relative paths, absolute paths, URLs, empty paths).



272
273
274
275
276
277
278
279
280
281
282
283
284
# File 'lib/roda/plugins/route_csrf.rb', line 272

def csrf_path(action)
  case action
  when nil, '', /\A[#?]/
    # use current path
    request.path
  when /\A(?:https?:\/)?\//
    # Either full URI or absolute path, extract just the path
    URI.parse(action).path
  else
    # relative path, join to current path
    URI.join(request.url, action).path
  end
end

#csrf_tag(*args) ⇒ Object

An HTML hidden input tag string containing the CSRF token. See csrf_token for arguments.



296
297
298
# File 'lib/roda/plugins/route_csrf.rb', line 296

def csrf_tag(*args)
  "<input type=\"hidden\" name=\"#{csrf_field}\" value=\"#{csrf_token(*args)}\" \/>"
end

#csrf_token(path = nil, method = ('POST' if path)) ⇒ Object

The value of the csrf token. For a path specific token, provide a path argument. By default, it a path is provided, the POST request method will be assumed. To generate a token for a non-POST request method, pass the method as the second argument.



304
305
306
307
308
# File 'lib/roda/plugins/route_csrf.rb', line 304

def csrf_token(path=nil, method=('POST' if path))
  token = SecureRandom.random_bytes(31)
  token << csrf_hmac(token, method, path)
  [token].pack("m0")
end

#use_request_specific_csrf_tokens?Boolean

Whether request-specific CSRF tokens should be used by default.

Returns:

  • (Boolean)


311
312
313
# File 'lib/roda/plugins/route_csrf.rb', line 311

def use_request_specific_csrf_tokens?
  csrf_options[:require_request_specific_tokens]
end

#valid_csrf?(opts = OPTS) ⇒ Boolean

Whether the submitted CSRF token is valid for the request. True if the request does not require a CSRF token.

Returns:

  • (Boolean)


317
318
319
# File 'lib/roda/plugins/route_csrf.rb', line 317

def valid_csrf?(opts=OPTS)
  csrf_invalid_message(opts).nil?
end