or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

csrf-protection.mdfile-upload.mdform-handling.mdindex.mdrecaptcha.md

csrf-protection.mddocs/

0

# CSRF Protection

1

2

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.

3

4

## Capabilities

5

6

### CSRFProtect Class

7

8

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.

9

10

```python { .api }

11

class CSRFProtect:

12

def __init__(self, app: Flask = None):

13

"""

14

Initialize CSRF protection.

15

16

Args:

17

app: Flask application instance (optional for factory pattern)

18

"""

19

20

def init_app(self, app: Flask):

21

"""

22

Initialize CSRF protection with Flask app (factory pattern).

23

24

Args:

25

app: Flask application instance

26

"""

27

28

def exempt(self, view):

29

"""

30

Mark a view function or blueprint exempt from CSRF protection.

31

32

Args:

33

view: View function, blueprint, or string view name

34

35

Returns:

36

The view function or blueprint (for use as decorator)

37

"""

38

39

def protect(self):

40

"""

41

Manually protect the current request with CSRF validation.

42

Raises CSRFError if validation fails.

43

"""

44

```

45

46

### Token Generation

47

48

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

49

50

```python { .api }

51

def generate_csrf(secret_key: str = None, token_key: str = None) -> str:

52

"""

53

Generate a CSRF token for the current request.

54

55

Args:

56

secret_key: Secret key for signing (defaults to WTF_CSRF_SECRET_KEY or app.secret_key)

57

token_key: Session key for token storage (defaults to WTF_CSRF_FIELD_NAME)

58

59

Returns:

60

Signed CSRF token string

61

"""

62

```

63

64

### Token Validation

65

66

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

67

68

```python { .api }

69

def validate_csrf(

70

data: str,

71

secret_key: str = None,

72

time_limit: int = None,

73

token_key: str = None

74

):

75

"""

76

Validate a CSRF token against the session token.

77

78

Args:

79

data: The signed CSRF token to validate

80

secret_key: Secret key for verification (defaults to WTF_CSRF_SECRET_KEY)

81

time_limit: Token expiration time in seconds (defaults to WTF_CSRF_TIME_LIMIT)

82

token_key: Session key for stored token (defaults to WTF_CSRF_FIELD_NAME)

83

84

Raises:

85

ValidationError: If token is missing, expired, invalid, or doesn't match

86

"""

87

```

88

89

### CSRF Error Exception

90

91

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

92

93

```python { .api }

94

class CSRFError(BadRequest):

95

"""

96

CSRF validation failed error.

97

98

Generates 400 Bad Request response by default.

99

Customize response by registering error handler with Flask.

100

"""

101

description: str = "CSRF validation failed."

102

```

103

104

## Usage Examples

105

106

### Basic Global Protection

107

108

```python

109

from flask import Flask

110

from flask_wtf import CSRFProtect

111

112

app = Flask(__name__)

113

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

114

115

# Enable CSRF protection for all views

116

csrf = CSRFProtect(app)

117

118

# Or using factory pattern

119

csrf = CSRFProtect()

120

csrf.init_app(app)

121

```

122

123

### Exempting Views

124

125

```python

126

# Exempt a single view

127

@app.route('/api/public', methods=['POST'])

128

@csrf.exempt

129

def public_api():

130

return {'status': 'ok'}

131

132

# Exempt an entire blueprint

133

from flask import Blueprint

134

api = Blueprint('api', __name__)

135

csrf.exempt(api)

136

137

# Exempt by string name

138

csrf.exempt('main.upload_file')

139

```

140

141

### Manual Token Handling

142

143

```python

144

from flask import render_template

145

from flask_wtf.csrf import generate_csrf, validate_csrf

146

147

@app.route('/custom-form')

148

def custom_form():

149

token = generate_csrf()

150

return render_template('custom.html', csrf_token=token)

151

152

@app.route('/validate-token', methods=['POST'])

153

def validate_token():

154

token = request.form.get('csrf_token')

155

try:

156

validate_csrf(token)

157

return 'Valid token'

158

except ValidationError as e:

159

return f'Invalid token: {e}', 400

160

```

161

162

### Template Integration

163

164

CSRF tokens are automatically available in Jinja2 templates:

165

166

```html

167

<!-- Automatic token function -->

168

<form method="POST">

169

<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>

170

<!-- form fields -->

171

</form>

172

173

<!-- Via context processor -->

174

<form method="POST">

175

<input type="hidden" name="csrf_token" value="{{ csrf_token }}"/>

176

<!-- form fields -->

177

</form>

178

```

179

180

## Configuration

181

182

### Required Configuration

183

184

```python

185

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

186

```

187

188

### Optional CSRF Configuration

189

190

```python

191

# CSRF protection settings

192

app.config['WTF_CSRF_ENABLED'] = True # Enable/disable protection

193

app.config['WTF_CSRF_SECRET_KEY'] = 'csrf-specific-key' # Separate CSRF key

194

app.config['WTF_CSRF_FIELD_NAME'] = 'csrf_token' # Token field name

195

app.config['WTF_CSRF_TIME_LIMIT'] = 3600 # Token expiration (seconds)

196

197

# HTTP method protection

198

app.config['WTF_CSRF_METHODS'] = ['POST', 'PUT', 'PATCH', 'DELETE']

199

200

# Token sources (form data and headers)

201

app.config['WTF_CSRF_HEADERS'] = ['X-CSRFToken', 'X-CSRF-Token']

202

203

# Request processing settings

204

app.config['WTF_CSRF_CHECK_DEFAULT'] = True # Auto-check requests

205

app.config['WTF_CSRF_SSL_STRICT'] = True # Enforce referrer on HTTPS

206

```

207

208

## Error Handling

209

210

### Custom Error Handler

211

212

```python

213

@app.errorhandler(CSRFError)

214

def handle_csrf_error(e):

215

return render_template('csrf_error.html'), 400

216

```

217

218

### AJAX Integration

219

220

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

221

222

```javascript

223

// Get token from meta tag

224

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

225

226

// Include in AJAX requests

227

fetch('/api/endpoint', {

228

method: 'POST',

229

headers: {

230

'X-CSRFToken': token,

231

'Content-Type': 'application/json'

232

},

233

body: JSON.stringify(data)

234

});

235

```

236

237

Template meta tag:

238

239

```html

240

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

241

```