Open In App

CSRF Protection in Flask

Last Updated : 24 Mar, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

Cross-Site Request Forgery (CSRF) is a security vulnerability where an attacker tricks a user into unknowingly submitting a request to a web application in which they are authenticated. This can lead to unauthorized actions being performed on behalf of the user, such as changing account settings or making transactions.

How to Prevent CSRF Attacks?

One of the most effective ways to prevent CSRF attacks is by using CSRF tokens. These tokens are unique, dynamically generated values included in forms and verified by the server when a request is made. Since attackers cannot predict these tokens, they are unable to forge valid requests.

CSRF Prevention

Implementing CSRF Protection in Flask

Step 1: Install Dependencies

To implement CSRF protection in Flask, install the required packages using:

pip install flask flask-wtf

Step 2: Set Up Flask Application

In Flask, CSRF protection can be enabled using Flask-WTF, which provides automatic CSRF protection for forms. Below is a basic example:

Python
from flask import Flask, render_template, request, flash
from flask_wtf import FlaskForm, CSRFProtect
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired

app = Flask(__name__)
app.secret_key = 'your_secret_key'  # Required for CSRF protection
csrf = CSRFProtect(app)  # Enable CSRF Protection

# Creating a FlaskForm to manage CSRF properly
class NameForm(FlaskForm):
    name = StringField('Name', validators=[DataRequired()])
    submit = SubmitField('Submit')

@app.route("/", methods=['GET', 'POST'])
def index():
    form = NameForm()

    if request.method == 'POST':
        if form.validate_on_submit():
            name = form.name.data
            flash(f'Hello {name} from Protected Form!', 'success')
            return render_template('index.html', form=form)
        else:
            flash('CSRF Token Missing or Invalid!', 'danger')

    return render_template('index.html', form=form)

@app.route("/unprotected_form", methods=['POST'])
def unprotected_form():
    name = request.form.get('Name', '').strip()
    if not name:
        return "Error: Name is required!", 400
    return f'Hello {name} from Unprotected Form!'

if __name__ == '__main__':
    app.run(debug=True)

Step 3: Create a Secure HTML Form

A simple HTML page with CSRF-protected and unprotected forms:

Python
<!DOCTYPE html>
<html>
<head>
    <title>CSRF Protection Demo</title>
</head>
<body>

    <h2>Protected Form (CSRF Token Required)</h2>
    <form action="{{ url_for('index') }}" method="POST">
        {{ form.hidden_tag() }}  <!-- This automatically includes CSRF token -->
        <label for="Name">Your Name Please?</label>
        {{ form.name() }}  <!-- Flask-WTF handles input -->
        {{ form.submit() }}  <!-- Submit button -->
    </form>

    <h2>Unprotected Form (No CSRF Token)</h2>
    <form action="{{ url_for('unprotected_form') }}" method="POST">
        <label for="Name">Your Name Please?</label>
        <input type="text" name="Name" required>
        <button type="submit">Submit</button>
    </form>

    <!-- Flash Messages -->
    {% with messages = get_flashed_messages(with_categories=True) %}
        {% if messages %}
            {% for category, message in messages %}
                <p style="color: {{ 'red' if category == 'danger' else 'green' }}">{{ message }}</p>
            {% endfor %}
        {% endif %}
    {% endwith %}

</body>
</html>

Step 4: Run the Flask Application

Run the app in development mode using command-

python app.py

Step 5: Testing the CSRF Protection

  1. Open http://127.0.0.1:5000/protected_form in your browser.
  2. Try submitting both forms:
    1. Unprotected Form: Submits without any token, making it vulnerable to CSRF attacks.
    2. Protected Form: Requires a valid CSRF token to submit successfully.
  3. If you try submitting the protected form without the CSRF token, an error will occur, preventing unauthorized requests.
c1
Value into unprotected form
c2
Successful submission
c3
Value into Protected form
c4
CSRF token missing error on submission

Note: To submit forms that require CSRF tokens, use hidden_tag() method of Flask-WTF, it automatically generates hidden fields including CSRD token inside a form.


Next Article

Similar Reads