class Bezel::Plug::CSRF
include Bezel::Plug
Protects a browser pipeline against cross-site request forgery (after
Plug::Session):
- Each session gets a secret token (in the session,
_csrf_token). Pages carry it masked (a fresh one-time pad per request, so that it never repeats in a compressed response):Conn#csrf_token, whichBezel.html(conn)puts in forms and non-GET links. - A POST, PUT, PATCH or DELETE must send it back, in the form field
_csrf_tokenor the headerX-CSRF-Token, elseInvalidCSRFToken(403). - As a second check, such a request whose Origin is another origin
than the request's (its scheme and Host header, default ports aside),
or whose
Sec-Fetch-Siteiscross-site, is refused even with a token. Behind a proxy, the proxy must pass the Host the browser used (and X-Forwarded-Proto from a trusted proxy gives the scheme).
GET, HEAD and OPTIONS are not checked: they must not change anything.
Constants
KEY: String
The session key of the token.
UNSAFE: Array[String]
The methods that need a token.
Class methods
def self.new -> Bezel::Plug::CSRF
The plug.
def self.new_secret -> String
A new secret: 32 random bytes, URL-safe Base64 (what the session keeps).
def self.mask(secret: Bytes) -> String
secret masked with a fresh pad: the pad and the secret XORed with
it, in URL-safe Base64.
def self.valid?(secret: Bytes, given: String) -> Bool
Whether given, a masked token, unmasks to secret.
Methods
def call(conn: Bezel::Conn) -> Bezel::Conn
The connection changed by this plug.
from Bezel::Plug