Class: Rack::Protection::AuthenticityToken
- Defined in:
- lib/rack/protection/authenticity_token.rb
Overview
- Prevented attack
-
CSRF
- Supported browsers
-
all
- More infos
This middleware only accepts requests other than GET
, HEAD
, OPTIONS
, TRACE
if their given access token matches the token included in the session.
It checks the X-CSRF-Token
header and the POST
form data.
It is not OOTB-compatible with the rack-csrf gem. For that, the following patch needs to be applied:
Rack::Protection::AuthenticityToken.(key: "csrf.token", authenticity_param: "_csrf")
Options
:authenticity_param
-
the name of the param that should contain the token on a request. Default value:
"authenticity_token"
:key
-
the name of the param that should contain
the token in the session. Default value: <tt>:csrf</tt>
:allow_if
-
a proc for custom allow/deny logic. Default value:
<tt>nil</tt>
Example: Forms application
To show what the AuthenticityToken does, this section includes a sample program which shows two forms. One with, and one without a CSRF token The one without CSRF token field will get a 403 Forbidden response.
Install the gem, then run the program:
gem install 'rack-protection'
puma server.ru
Here is server.ru
:
require 'rack/protection'
require 'rack/session'
app = Rack::Builder.app do
use Rack::Session::Cookie, secret: 'CHANGEMEaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
use Rack::Protection::AuthenticityToken
run -> (env) do
[200, {}, [
<<~EOS
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>rack-protection minimal example</title>
</head>
<body>
<h1>Without Authenticity Token</h1>
<p>This takes you to <tt>Forbidden</tt></p>
<form action="" method="post">
<input type="text" name="foo" />
<input type="submit" />
</form>
<h1>With Authenticity Token</h1>
<p>This successfully takes you to back to this form.</p>
<form action="" method="post">
<input type="hidden" name="authenticity_token" value="#{Rack::Protection::AuthenticityToken.token(env['rack.session'])}" />
<input type="text" name="foo" />
<input type="submit" />
</form>
</body>
</html>
EOS
]]
end
end
run app
Example: Customize which POST parameter holds the token
To customize the authenticity parameter for form data, use the :authenticity_param
option:
use Rack::Protection::AuthenticityToken, authenticity_param: 'your_token_param_name'
Direct Known Subclasses
Constant Summary collapse
- TOKEN_LENGTH =
32
Constants inherited from Base
Instance Attribute Summary
Attributes inherited from Base
Class Method Summary collapse
Instance Method Summary collapse
Methods inherited from Base
#call, #debug, #default_options, default_options, default_reaction, #deny, #drop_session, #encrypt, #html?, #initialize, #instrument, #origin, #random_string, #react, #referrer, #report, #safe?, #secure_compare, #session, #session?, #warn
Constructor Details
This class inherits a constructor from Rack::Protection::Base
Class Method Details
.random_token ⇒ Object
109 110 111 |
# File 'lib/rack/protection/authenticity_token.rb', line 109 def self.random_token SecureRandom.urlsafe_base64(TOKEN_LENGTH, padding: false) end |
.token(session, path: nil, method: :post) ⇒ Object
105 106 107 |
# File 'lib/rack/protection/authenticity_token.rb', line 105 def self.token(session, path: nil, method: :post) new(nil).mask_authenticity_token(session, path: path, method: method) end |
Instance Method Details
#accepts?(env) ⇒ Boolean
113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/rack/protection/authenticity_token.rb', line 113 def accepts?(env) session = session(env) set_token(session) safe?(env) || valid_token?(env, env['HTTP_X_CSRF_TOKEN']) || valid_token?(env, Request.new(env).params[[:authenticity_param]]) || [:allow_if]&.call(env) rescue StandardError false end |
#mask_authenticity_token(session, path: nil, method: :post) ⇒ Object
125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/rack/protection/authenticity_token.rb', line 125 def mask_authenticity_token(session, path: nil, method: :post) set_token(session) token = if path && method per_form_token(session, path, method) else global_token(session) end mask_token(token) end |