← Back to all snippets
PYTHON

Implement CSRF Protection with Secure Tokens in Flask

Protect your Flask web applications from Cross-Site Request Forgery (CSRF) attacks by generating and validating secure, unique tokens for each user session.

from flask import Flask, request, session, redirect, url_for, render_template_string
import os
import secrets

app = Flask(__name__)
app.secret_key = os.urandom(24) # A strong secret key is crucial for session security

HTML_FORM = """
<!doctype html>
<html>
<head><title>CSRF Demo</title></head>
<body>
        <h1>Transfer Money</h1>
        <form method="POST" action="/transfer">
            <input type="hidden" name="csrf_token" value="{{ csrf_token }}">
            <label for="amount">Amount:</label>
            <input type="text" id="amount" name="amount"><br><br>
            <input type="submit" value="Transfer">
        </form>
</body>
</html>
"""

@app.before_request
def csrf_protect():
    if request.method == "POST":
        token = session.pop('_csrf_token', None)
        if not token or token != request.form.get('csrf_token'):
            # In a real app, log this and return a 403 Forbidden
            return "CSRF token missing or invalid!", 403

def generate_csrf_token():
    if '_csrf_token' not in session:
        session['_csrf_token'] = secrets.token_urlsafe(16)
    return session['_csrf_token']

app.jinja_env.globals['csrf_token'] = generate_csrf_token

@app.route('/')
def index():
    return render_template_string(HTML_FORM)

@app.route('/transfer', methods=['POST'])
def transfer():
    amount = request.form.get('amount')
    # In a real application, perform the transfer securely here
    return f"Transfer of {amount} processed securely!"

if __name__ == '__main__':
    app.run(debug=True)
How it works: This Flask snippet demonstrates a basic implementation of CSRF (Cross-Site Request Forgery) protection. A unique, unpredictable token is generated and stored in the user's session (`generate_csrf_token`). This token is then embedded as a hidden field in forms. On `POST` requests, the `before_request` hook validates that the submitted token matches the one in the session. If they don't match or the token is missing, the request is rejected, preventing attackers from tricking users into making unauthorized requests. The session secret key is critical and must be genuinely random and kept confidential.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs