or run

tessl search
Log in

Version

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
mavenpkg:maven/io.quarkus/quarkus-resteasy-reactive@3.15.x

docs

index.md
tile.json

tessl/maven-io-quarkus--quarkus-resteasy-reactive

tessl install tessl/maven-io-quarkus--quarkus-resteasy-reactive@3.15.0

A Jakarta REST implementation utilizing build time processing and Vert.x for high-performance REST endpoints with reactive capabilities in cloud-native environments.

csrf-protection.mddocs/reference/

CSRF Protection

Quarkus REST provides built-in Cross-Site Request Forgery (CSRF) protection for REST endpoints. The CSRF filter validates tokens on state-changing requests (POST, PUT, DELETE, PATCH) to prevent unauthorized cross-site requests.

Import

import io.quarkus.csrf.reactive.runtime.RestCsrfConfig;

Capabilities

RestCsrfConfig

Runtime configuration for REST CSRF protection.

/**
 * CSRF protection configuration for REST endpoints
 * Configured via quarkus.rest-csrf.* properties (implied prefix)
 */
public class RestCsrfConfig {
    /**
     * Form field name containing the CSRF token
     * Default: "csrf-token"
     */
    String formFieldName = "csrf-token";

    /**
     * HTTP header name for CSRF token
     * Default: "X-CSRF-TOKEN"
     */
    String tokenHeaderName = "X-CSRF-TOKEN";

    /**
     * Cookie name for CSRF token
     * Default: "csrf-token"
     */
    String cookieName = "csrf-token";

    /**
     * CSRF cookie maximum age
     * Default: 2H (2 hours)
     */
    Duration cookieMaxAge = Duration.ofHours(2);

    /**
     * CSRF cookie path
     * Default: "/"
     */
    String cookiePath = "/";

    /**
     * CSRF cookie domain
     * Optional: If not set, uses request domain
     */
    Optional<String> cookieDomain;

    /**
     * Force secure flag on CSRF cookie (HTTPS only)
     * Default: false
     */
    boolean cookieForceSecure = false;

    /**
     * Set HttpOnly flag on CSRF cookie
     * Default: true
     */
    boolean cookieHttpOnly = true;

    /**
     * Paths that trigger CSRF token creation (GET requests)
     * Optional: If not set, token is created on any GET request
     */
    Optional<Set<String>> createTokenPath;

    /**
     * Size of random CSRF token in bytes
     * Default: 16 bytes
     */
    int tokenSize = 16;

    /**
     * HMAC signature key for token signing (min 32 characters)
     * Optional: If not set, tokens are not signed
     */
    Optional<String> tokenSignatureKey;

    /**
     * Enable CSRF token verification
     * Default: true
     */
    boolean verifyToken = true;

    /**
     * Require application/x-www-form-urlencoded content type for form submissions
     * Default: true
     */
    boolean requireFormUrlEncoded = true;
}

Configuration

Configure CSRF protection via application.properties. The prefix quarkus.rest-csrf.* is implied for these properties:

# Form field name
quarkus.rest-csrf.form-field-name=csrf-token

# Token header name
quarkus.rest-csrf.token-header-name=X-CSRF-TOKEN

# Cookie configuration
quarkus.rest-csrf.cookie-name=csrf-token
quarkus.rest-csrf.cookie-max-age=2h
quarkus.rest-csrf.cookie-path=/
quarkus.rest-csrf.cookie-domain=example.com
quarkus.rest-csrf.cookie-force-secure=false
quarkus.rest-csrf.cookie-http-only=true

# Token creation paths (comma-separated)
quarkus.rest-csrf.create-token-path=/form,/login

# Token configuration
quarkus.rest-csrf.token-size=16
quarkus.rest-csrf.token-signature-key=your-secret-key-minimum-32-characters-long

# Verification settings
quarkus.rest-csrf.verify-token=true
quarkus.rest-csrf.require-form-url-encoded=true

Usage Examples

Basic CSRF Protection

Enable CSRF protection by adding the extension and configuring it:

<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-rest-csrf</artifactId>
</dependency>

Configuration:

# Enable CSRF protection with default settings
quarkus.rest-csrf.verify-token=true

HTML Form with CSRF Token

import io.quarkus.qute.Template;
import io.quarkus.qute.TemplateInstance;
import jakarta.inject.Inject;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.*;

@Path("/form")
public class FormResource {

    @Inject
    Template form;

    @GET
    @Produces(MediaType.TEXT_HTML)
    public TemplateInstance showForm(@CookieParam("csrf-token") String csrfToken) {
        // CSRF token is automatically created and set in cookie
        return form.data("csrfToken", csrfToken);
    }

    @POST
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    public Response submitForm(
        @FormParam("name") String name,
        @FormParam("csrf-token") String csrfToken
    ) {
        // CSRF token is automatically validated
        return Response.ok("Form submitted successfully").build();
    }
}

HTML template (form.html):

<!DOCTYPE html>
<html>
<body>
    <form method="POST" action="/form">
        <input type="hidden" name="csrf-token" value="{csrfToken}">
        <input type="text" name="name" placeholder="Your name">
        <button type="submit">Submit</button>
    </form>
</body>
</html>

REST API with CSRF Header

@Path("/api")
public class ApiResource {

    @POST
    @Path("/action")
    public Response performAction(ActionRequest request) {
        // Client must send CSRF token in X-CSRF-TOKEN header
        return Response.ok("Action completed").build();
    }
}

JavaScript client:

// Get CSRF token from cookie
const csrfToken = document.cookie
    .split('; ')
    .find(row => row.startsWith('csrf-token='))
    ?.split('=')[1];

// Send token in header
fetch('/api/action', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'X-CSRF-TOKEN': csrfToken
    },
    body: JSON.stringify({ action: 'delete' })
});

Signed CSRF Tokens

For enhanced security, use HMAC-signed tokens:

# Set signature key (minimum 32 characters)
quarkus.rest-csrf.token-signature-key=your-very-long-secret-key-at-least-32-characters-or-more

Signed tokens prevent token tampering and forgery.

Custom Token Creation Paths

Create CSRF tokens only on specific pages:

# Only create tokens on these GET endpoints
quarkus.rest-csrf.create-token-path=/login,/dashboard,/forms

This limits token creation to reduce overhead for public read-only endpoints.

Secure Production Configuration

# Force HTTPS-only cookies in production
%prod.quarkus.rest-csrf.cookie-force-secure=true

# Set specific cookie domain
%prod.quarkus.rest-csrf.cookie-domain=example.com

# Use signed tokens
%prod.quarkus.rest-csrf.token-signature-key=${CSRF_SECRET_KEY}

# Shorter max age
%prod.quarkus.rest-csrf.cookie-max-age=30m

Development Configuration

# Disable CSRF in development (use with caution)
%dev.quarkus.rest-csrf.verify-token=false

# Or use relaxed settings
%dev.quarkus.rest-csrf.cookie-force-secure=false
%dev.quarkus.rest-csrf.cookie-http-only=false

Custom Cookie Path

For multi-application deployments:

# Scope CSRF cookie to specific application path
quarkus.rest-csrf.cookie-path=/app

Custom Header Name

For compatibility with frontend frameworks:

# Use framework-specific header name
quarkus.rest-csrf.token-header-name=X-XSRF-TOKEN
quarkus.rest-csrf.cookie-name=XSRF-TOKEN

This is compatible with Angular's built-in CSRF support.

Larger Token Size

For high-security requirements:

# Increase token entropy (32 bytes = 256 bits)
quarkus.rest-csrf.token-size=32

Multipart Form Submissions

CSRF protection works with multipart forms:

@POST
@Path("/upload")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response upload(
    @RestForm("file") FileUpload file,
    @RestForm("csrf-token") String csrfToken
) {
    // CSRF token is automatically validated
    return Response.ok("File uploaded").build();
}

HTML form:

<form method="POST" action="/upload" enctype="multipart/form-data">
    <input type="hidden" name="csrf-token" value="{csrfToken}">
    <input type="file" name="file">
    <button type="submit">Upload</button>
</form>

Conditional CSRF Verification

# Disable CSRF for specific profiles
%test.quarkus.rest-csrf.verify-token=false

# Enable only in production
%prod.quarkus.rest-csrf.verify-token=true

Exempting Specific Endpoints

For endpoints that should not require CSRF tokens (like public APIs), use path-based exclusion via HTTP firewall configuration or custom filters.

Best Practices

Always Use HTTPS in Production

%prod.quarkus.rest-csrf.cookie-force-secure=true

CSRF tokens in cookies should only be transmitted over HTTPS to prevent interception.

Use Signed Tokens

quarkus.rest-csrf.token-signature-key=${CSRF_SECRET_KEY}

Store the signature key in environment variables or secret management systems, never in source code.

Set Appropriate Cookie Max Age

# Short-lived sessions
quarkus.rest-csrf.cookie-max-age=30m

# Long-lived sessions
quarkus.rest-csrf.cookie-max-age=24h

Balance security and user experience based on your application's session duration.

Scope Cookies Appropriately

# Application-specific path
quarkus.rest-csrf.cookie-path=/app

# Subdomain scope
quarkus.rest-csrf.cookie-domain=.example.com

Prevent cookie leakage to unrelated applications on the same domain.

Use HttpOnly Cookies

quarkus.rest-csrf.cookie-http-only=true

This prevents JavaScript access to CSRF tokens, reducing XSS risk (though CSRF tokens should still be accessible to your application's JavaScript for AJAX requests).

Test CSRF Protection

Always test CSRF protection in staging environments before deploying to production:

@QuarkusTest
public class CsrfTest {

    @Test
    public void testCsrfProtection() {
        // Request without CSRF token should fail
        given()
            .contentType(ContentType.URLENC)
            .formParam("data", "value")
        .when()
            .post("/form")
        .then()
            .statusCode(403);

        // Request with valid token should succeed
        String token = given()
            .get("/form")
            .cookie("csrf-token");

        given()
            .contentType(ContentType.URLENC)
            .formParam("data", "value")
            .formParam("csrf-token", token)
            .cookie("csrf-token", token)
        .when()
            .post("/form")
        .then()
            .statusCode(200);
    }
}

Integration with Single Page Applications (SPA)

Double Submit Cookie Pattern

The default configuration uses the double-submit cookie pattern:

  1. Server sets CSRF token in cookie (GET request)
  2. Client reads token from cookie
  3. Client sends token in header (POST/PUT/DELETE/PATCH)
  4. Server validates that cookie matches header
// React/Vue/Angular example
async function makeSecureRequest(url, data) {
    const csrfToken = getCookie('csrf-token');

    const response = await fetch(url, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'X-CSRF-TOKEN': csrfToken
        },
        credentials: 'include', // Include cookies
        body: JSON.stringify(data)
    });

    return response.json();
}

function getCookie(name) {
    const value = `; ${document.cookie}`;
    const parts = value.split(`; ${name}=`);
    if (parts.length === 2) return parts.pop().split(';').shift();
}

Framework-Specific Integration

Angular:

// Angular automatically handles XSRF tokens
// Configure to match Quarkus settings:
// quarkus.rest-csrf.token-header-name=X-XSRF-TOKEN
// quarkus.rest-csrf.cookie-name=XSRF-TOKEN

import { HttpClientModule, HttpClientXsrfModule } from '@angular/common/http';

@NgModule({
  imports: [
    HttpClientModule,
    HttpClientXsrfModule.withOptions({
      cookieName: 'XSRF-TOKEN',
      headerName: 'X-XSRF-TOKEN'
    })
  ]
})
export class AppModule { }

Security Considerations

  • CSRF tokens protect against cross-site attacks but not against XSS attacks
  • Always validate input even with CSRF protection enabled
  • Use HTTPS to prevent token interception
  • Rotate tokens by setting appropriate cookie-max-age
  • Don't disable CSRF protection in production without careful consideration
  • Token size of 16 bytes provides 128 bits of entropy (cryptographically secure)
  • Signed tokens provide additional protection against token forgery

Troubleshooting

CSRF Token Validation Fails

Check that:

  1. Cookie domain and path match the request
  2. Token is sent in both cookie and header/form field
  3. Cookie is not being blocked by browser settings
  4. HTTPS is used if cookie-force-secure=true

Token Not Created

Ensure:

  1. verify-token=true (enables CSRF filter)
  2. GET request is made first to create token
  3. create-token-path includes the endpoint (if configured)

Token Expired

Adjust cookie-max-age based on session duration:

# Longer session duration
quarkus.rest-csrf.cookie-max-age=8h