CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-flask-wtf

Form rendering, validation, and CSRF protection for Flask with WTForms.

72

0.91x
Overview
Eval results
Files

csrf-protection.mddocs/

CSRF Protection

Cross-Site Request Forgery (CSRF) protection for Flask applications with automatic token generation, validation, and request processing. Flask-WTF provides both global application-level protection and manual token handling for custom scenarios.

Capabilities

CSRFProtect Class

Main CSRF protection extension that integrates with Flask's request processing cycle. Provides automatic protection for specified HTTP methods and allows exemption of specific views or blueprints.

class CSRFProtect:
    def __init__(self, app: Flask = None):
        """
        Initialize CSRF protection.
        
        Args:
            app: Flask application instance (optional for factory pattern)
        """
    
    def init_app(self, app: Flask):
        """
        Initialize CSRF protection with Flask app (factory pattern).
        
        Args:
            app: Flask application instance
        """
    
    def exempt(self, view):
        """
        Mark a view function or blueprint exempt from CSRF protection.
        
        Args:
            view: View function, blueprint, or string view name
            
        Returns:
            The view function or blueprint (for use as decorator)
        """
    
    def protect(self):
        """
        Manually protect the current request with CSRF validation.
        Raises CSRFError if validation fails.
        """

Token Generation

Generate CSRF tokens for use in templates and views. Tokens are cached per request and stored in the session for validation.

def generate_csrf(secret_key: str = None, token_key: str = None) -> str:
    """
    Generate a CSRF token for the current request.
    
    Args:
        secret_key: Secret key for signing (defaults to WTF_CSRF_SECRET_KEY or app.secret_key)
        token_key: Session key for token storage (defaults to WTF_CSRF_FIELD_NAME)
        
    Returns:
        Signed CSRF token string
    """

Token Validation

Manually validate CSRF tokens in custom scenarios where automatic protection is not sufficient.

def validate_csrf(
    data: str, 
    secret_key: str = None, 
    time_limit: int = None, 
    token_key: str = None
):
    """
    Validate a CSRF token against the session token.
    
    Args:
        data: The signed CSRF token to validate
        secret_key: Secret key for verification (defaults to WTF_CSRF_SECRET_KEY)
        time_limit: Token expiration time in seconds (defaults to WTF_CSRF_TIME_LIMIT)
        token_key: Session key for stored token (defaults to WTF_CSRF_FIELD_NAME)
        
    Raises:
        ValidationError: If token is missing, expired, invalid, or doesn't match
    """

CSRF Error Exception

Exception raised when CSRF validation fails. Inherits from Werkzeug's BadRequest for proper HTTP error handling.

class CSRFError(BadRequest):
    """
    CSRF validation failed error.
    
    Generates 400 Bad Request response by default.
    Customize response by registering error handler with Flask.
    """
    description: str = "CSRF validation failed."

Usage Examples

Basic Global Protection

from flask import Flask
from flask_wtf import CSRFProtect

app = Flask(__name__)
app.config['SECRET_KEY'] = 'your-secret-key'

# Enable CSRF protection for all views
csrf = CSRFProtect(app)

# Or using factory pattern
csrf = CSRFProtect()
csrf.init_app(app)

Exempting Views

# Exempt a single view
@app.route('/api/public', methods=['POST'])
@csrf.exempt
def public_api():
    return {'status': 'ok'}

# Exempt an entire blueprint
from flask import Blueprint
api = Blueprint('api', __name__)
csrf.exempt(api)

# Exempt by string name
csrf.exempt('main.upload_file')

Manual Token Handling

from flask import render_template
from flask_wtf.csrf import generate_csrf, validate_csrf

@app.route('/custom-form')
def custom_form():
    token = generate_csrf()
    return render_template('custom.html', csrf_token=token)

@app.route('/validate-token', methods=['POST'])
def validate_token():
    token = request.form.get('csrf_token')
    try:
        validate_csrf(token)
        return 'Valid token'
    except ValidationError as e:
        return f'Invalid token: {e}', 400

Template Integration

CSRF tokens are automatically available in Jinja2 templates:

<!-- Automatic token function -->
<form method="POST">
    <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
    <!-- form fields -->
</form>

<!-- Via context processor -->
<form method="POST">
    <input type="hidden" name="csrf_token" value="{{ csrf_token }}"/>
    <!-- form fields -->
</form>

Configuration

Required Configuration

app.config['SECRET_KEY'] = 'your-secret-key-here'

Optional CSRF Configuration

# CSRF protection settings
app.config['WTF_CSRF_ENABLED'] = True  # Enable/disable protection
app.config['WTF_CSRF_SECRET_KEY'] = 'csrf-specific-key'  # Separate CSRF key
app.config['WTF_CSRF_FIELD_NAME'] = 'csrf_token'  # Token field name
app.config['WTF_CSRF_TIME_LIMIT'] = 3600  # Token expiration (seconds)

# HTTP method protection
app.config['WTF_CSRF_METHODS'] = ['POST', 'PUT', 'PATCH', 'DELETE']

# Token sources (form data and headers)
app.config['WTF_CSRF_HEADERS'] = ['X-CSRFToken', 'X-CSRF-Token']

# Request processing settings
app.config['WTF_CSRF_CHECK_DEFAULT'] = True  # Auto-check requests
app.config['WTF_CSRF_SSL_STRICT'] = True  # Enforce referrer on HTTPS

Error Handling

Custom Error Handler

@app.errorhandler(CSRFError)
def handle_csrf_error(e):
    return render_template('csrf_error.html'), 400

AJAX Integration

For JavaScript/AJAX requests, include CSRF token in headers:

// Get token from meta tag
const token = document.querySelector('meta[name=csrf-token]').getAttribute('content');

// Include in AJAX requests
fetch('/api/endpoint', {
    method: 'POST',
    headers: {
        'X-CSRFToken': token,
        'Content-Type': 'application/json'
    },
    body: JSON.stringify(data)
});

Template meta tag:

<meta name="csrf-token" content="{{ csrf_token() }}">

Install with Tessl CLI

npx tessl i tessl/pypi-flask-wtf

docs

csrf-protection.md

file-upload.md

form-handling.md

index.md

recaptcha.md

tile.json