csrf
CSRF protection
Cross-site request forgery protection checks that an unsafe request carries a
token that was issued to the current session. Enable it on a controller with
protect-from-forgery:
class ApplicationController is MVC::Keayl::Controller { }
ApplicationController.protect-from-forgery;It also has an is protect-from-forgery trait form for the class header:
class ApplicationController is MVC::Keayl::Controller is protect-from-forgery { }This registers a before-action that verifies the token on every unsafe verb
(POST, PUT, PATCH, DELETE). Safe verbs (GET, HEAD, OPTIONS,
TRACE) are not checked.
The token
csrf-token returns a token for a form. The session holds one real token; each
call masks it with a fresh one-time pad, so the value differs every render while
still validating against the same real token. Put it in a form with the
csrf-token option:
form-with(model => $post, url => '/posts', csrf-token => self.csrf-token, content => -> $f {
$f.text-field('title')
});A request may also supply the token in the X-CSRF-Token header, which suits
JavaScript clients. Verification accepts a masked or an unmasked token and
compares in constant time.
Strategies
protect-from-forgery takes a with strategy for a failed check:
ApplicationController.protect-from-forgery(with => 'exception'); # default
ApplicationController.protect-from-forgery(with => 'reset-session');
ApplicationController.protect-from-forgery(with => 'null-session');exceptionraisesX::MVC::Keayl::InvalidAuthenticityToken, which the base controller turns into a422response.reset-sessionandnull-sessionclear the session and let the request proceed without the prior identity.
Skipping protection
API and webhook endpoints that authenticate another way can opt out with
skip-forgery-protection, using the same only/except filters as the
callbacks:
ApiController.skip-forgery-protection(only => ['create', 'update']);