Mojolicious::Plugin::CSRFProtectBuiltin - CSRF protection plugin using Mojolicious built-in CSRF support
# Mojolicious
$self->plugin('TagHelpers');
$self->plugin('CSRFProtectBuiltin');
# Mojolicious::Lite
plugin 'TagHelpers';
plugin 'CSRFProtectBuiltin';
# Existing block-style form_for forms automatically receive a CSRF field
%= form_for '/login' => (method => 'POST') => begin
%= text_field 'Username'
%= password_field 'Password'
%= submit_button 'Sign in'
% end
# Optional jQuery AJAX support
<%= jquery_ajax_csrf_protection %>
# Custom error handling
$self->plugin('CSRFProtectBuiltin' => {
on_error => sub {
my $c = shift;
$c->render(template => 'error_403', status => 403);
}
});
Mojolicious::Plugin::CSRFProtectBuiltin adds CSRF protection to applications that already make heavy use of form_for, while relying on Mojolicious built-in CSRF helpers and validation.
It does the following:
Wraps the form_for helper so block-style forms automatically get a csrf_field inserted at the start of the form body.
Provides a jquery_ajax_csrf_protection helper that emits a meta tag with the current CSRF token and JavaScript to attach that token as an X-CSRF-Token header on jQuery AJAX requests.
Rejects non GET, HEAD, and OPTIONS requests when csrf_protect validation fails.
This plugin uses Mojolicious built-in csrf_token, csrf_field, and csrf_protect support rather than implementing its own token generation and comparison logic.
Optional callback used when CSRF validation fails.
If omitted, the plugin returns a simple 403 Forbidden! response.
Example:
$self->plugin('CSRFProtectBuiltin' => {
on_error => sub {
my $c = shift;
$c->render(template => 'error_403', status => 403);
}
});
This plugin replaces the existing form_for helper and prepends csrf_field to block-style forms.
So this:
%= form_for '/save' => (method => 'POST') => begin
%= text_field 'name'
%= submit_button 'Save'
% end
behaves as if you had written:
%= form_for '/save' => (method => 'POST') => begin
%= csrf_field
%= text_field 'name'
%= submit_button 'Save'
% end
Returns the current Mojolicious CSRF token.
In templates:
<%= csrftoken %>
In controllers:
my $token = $self->csrftoken;
This is a compatibility helper for older code that expects a helper called csrftoken.
Checks whether the current request contains a valid CSRF token.
Returns 1 for valid and 0 for invalid.
Example:
return $c->render(status => 403, text => 'Forbidden')
unless $c->is_valid_csrftoken;
This is primarily a compatibility helper for code that previously used the older plugin API.
Emits a meta tag containing the current CSRF token and a jQuery ajaxSend handler that adds the token as an X-CSRF-Token header to AJAX requests.
Add it in the page head or layout:
<%= jquery_ajax_csrf_protection %>
This helper is intended for jQuery-based AJAX only. If your application uses fetch, Axios, or raw XMLHttpRequest, you will need an equivalent custom JavaScript snippet.
For non GET, HEAD, and OPTIONS requests, the plugin calls:
$c->validation->csrf_protect
If validation fails, Mojolicious records an error on csrf_token, and the plugin invokes the configured on_error callback.
This plugin does not automatically protect ordinary GET requests.
That is intentional, because navigation links and menu entries are normally GET, while CSRF protection is generally intended for state-changing requests such as POST, PUT, PATCH, and DELETE.
If you have a state-changing GET route, you should strongly consider changing it to POST. If that is not possible, protect it manually.
Only block-style form_for ... begin ... end usage is automatically augmented with csrf_field.
Raw literal <form> tags are not modified.
The AJAX helper supports jQuery only.
Mojolicious, Mojolicious::Plugin::TagHelpers, Mojolicious::Plugin::DefaultHelpers, Mojolicious::Validator::Validation, Mojolicious::Plugin::CSRFProtect, Mojolicious::Plugin::CSRFDefender
Adapted for Mojolicious built-in CSRF support.
Same terms as Perl itself.