Mojolicious-Plugin-Fondation-CSRF

 view release on metacpan or  search on metacpan

README.md  view on Meta::CPAN

    # With exemptions:
    'Fondation::CSRF' => {
        auto_protect => 1,
        exemptions   => [qr{^/webhook/}, qr{^/api/public/}],
    },

# DESCRIPTION

`Mojolicious::Plugin::Fondation::CSRF` provides Cross-Site Request Forgery
protection for Fondation applications. It uses Mojolicious' built-in CSRF
token mechanism (stored in session, validated via ["csrf\_protect" in Validation](https://metacpan.org/pod/Validation#csrf_protect)).

Three protection layers, all using the same underlying Mojo validation:

- 1. Route condition `fondation.csrf` — explicit opt-in on any route
- 2. OpenAPI auto-protection — POST/PUT/PATCH/DELETE routes generated
by [Fondation::OpenAPI](https://metacpan.org/pod/Fondation%3A%3AOpenAPI) automatically get `requires('fondation.csrf')`
- 3. `around_dispatch` blanket protection — all mutating requests
(POST/PUT/PATCH/DELETE) are checked unless the path matches an exemption

Token transmission works two ways, both handled automatically by Mojo:

README.md  view on Meta::CPAN


- 1. Layout-Bootstrap injects `<meta name="csrf-token">` in `<head>`.
- 2. `csrf.js` (loaded via AssetPack bundle or `<script src>`) patches
`fetch` and `XMLHttpRequest` to inject `X-CSRF-Token` on all mutating AJAX calls.
- 3. HTML forms (login, etc.) include `<%= csrf_field %>` to embed
the token as a hidden field.
- 4. OpenAPI routes (POST/PUT/PATCH/DELETE) automatically get
`requires('fondation.csrf')` via the `openapi_routes_added` hook.
- 5. HTML POST routes are protected by `around_dispatch` when
`auto_protect` is enabled (default), or by explicit `requires('fondation.csrf')`.
- 6. Mojo's `csrf_protect` validates the token from form field or
`X-CSRF-Token` header against the session token.

# HOW TOKEN VALIDATION WORKS

The route condition and `around_dispatch` both delegate to Mojo's
`csrf_protect` validation:

- 1. Mojo generates a unique token on first session access
- 2. Token is stored in `$c->session->{csrf_token}`
- 3. Client sends the token back (form field or `X-CSRF-Token` header)

lib/Mojolicious/Plugin/Fondation/CSRF.pm  view on Meta::CPAN

    $app->routes->add_condition('fondation.csrf' => sub {
        my ($route, $c, $captures) = @_;

        # GET, HEAD, OPTIONS are safe — no CSRF needed
        return 1 if $c->req->method =~ /^(GET|HEAD|OPTIONS)$/;

        # Bearer token auth bypasses CSRF — no session cookie, no CSRF risk
        my $auth = $c->req->headers->authorization;
        return 1 if $auth && $auth =~ /^Bearer\s+/i;

        # Delegate to Mojo's built-in csrf_protect (validates csrf_token
        # from form field or X-CSRF-Token header against session token)
        $c->validation->csrf_protect;

        unless ($c->validation->has_error('csrf_token')) {
            return 1;
        }

        $c->res->code(403);
        $c->stash('fondation.denied' => { status => 403, title => 'CSRF token missing or invalid' })
            unless $c->stash('fondation.denied');

lib/Mojolicious/Plugin/Fondation/CSRF.pm  view on Meta::CPAN

    # With exemptions:
    'Fondation::CSRF' => {
        auto_protect => 1,
        exemptions   => [qr{^/webhook/}, qr{^/api/public/}],
    },

=head1 DESCRIPTION

C<Mojolicious::Plugin::Fondation::CSRF> provides Cross-Site Request Forgery
protection for Fondation applications. It uses Mojolicious' built-in CSRF
token mechanism (stored in session, validated via L<Validation/csrf_protect>).

Three protection layers, all using the same underlying Mojo validation:

=over 4

=item 1. Route condition C<fondation.csrf> — explicit opt-in on any route

=item 2. OpenAPI auto-protection — POST/PUT/PATCH/DELETE routes generated
by L<Fondation::OpenAPI> automatically get C<requires('fondation.csrf')>

lib/Mojolicious/Plugin/Fondation/CSRF.pm  view on Meta::CPAN


=item 3. HTML forms (login, etc.) include C<< <%= csrf_field %> >> to embed
the token as a hidden field.

=item 4. OpenAPI routes (POST/PUT/PATCH/DELETE) automatically get
C<requires('fondation.csrf')> via the C<openapi_routes_added> hook.

=item 5. HTML POST routes are protected by C<around_dispatch> when
C<auto_protect> is enabled (default), or by explicit C<requires('fondation.csrf')>.

=item 6. Mojo's C<csrf_protect> validates the token from form field or
C<X-CSRF-Token> header against the session token.

=back

=head1 HOW TOKEN VALIDATION WORKS

The route condition and C<around_dispatch> both delegate to Mojo's
C<csrf_protect> validation:

=over 4



( run in 1.051 second using v1.01-cache-2.11-cpan-ad19def0cd9 )