I don't know a lot about CSRF but I'd like to know if it is correctly implemented.
I have a simple signin form using the following code:
The CSRF protection is activated:
from flask_wtf.csrf import CSRFProtect
csrf = CSRFProtect()
csrf.init_app(app)
In forms.py:
from flask_wtf import FlaskForm
from wtforms import RadioField,SubmitField, StringField,PasswordField, BooleanField
from wtforms.validators import Length, Email, DataRequired
class SignInForm(FlaskForm):
email = StringField('Email', validators=[DataRequired(), Length(1,50),Email()])
password = PasswordField('Password', validators=[DataRequired()])
remember_me = BooleanField('Keep me signed in')
submit = SubmitField('Sign in' )
In the html page:
<form action="" method="post" style="text-align:left">
{{wtf.quick_form(form)}}
</form>
However, once the app is running, it works well but I find the CSRF token like this in the inspection mode:
<form action="" method="post" style="text-align:left">
<input id="csrf_token" name="csrf_token" type="hidden" value="very_complex_key">
...
</form>
Shouldn't the csrf token very_complex_key be totally hidden? Or is it a CSRF token per session that Flask manages internally?
CodePudding user response:
The anti-CSRF token must be sent to the frontend user, so that when they submit the form, it will be sent back to the server. This IS the prevention for CSRF, so that an attacker can not send an API request without having the anti-CSRF token (which they can't get, since they can't read the HTML.
The reason why type="hidden"
is often added is because there is no UI reason for the user to see the token. It should be sent with the form, when it is submitted.
For this reason, the CSRF token should get to the frontend application, then it should be sent back in any API requests or forms. Therefore, it is correctly implemented to add the input
anti-CSRF tag into the form.