I am working on a Vue.js application with a Flask backend. I am using Flask-WTF for CSRF protection. When I make a POST request to the /user_login endpoint, I encounter a 400 Bad Request error stating that the CSRF token is missing, despite including it in the request headers.
Here are the details:
Flask backend:
@app.route("/get_csrf_token", methods=["GET"])
def get_csrf_token():
csrf_token = generate_csrf()
response = jsonify(csrf_token=csrf_token)
response.headers.set("X-CSRFToken", csrf_token)
return response
@app.route('/user_login', methods=["POST"])
def user_login():
print("called")
data = request.get_json()
print('Received data:', data)
print('Session:', session)
try:
if not data or 'username' not in data or 'password' not in data:
raise ValueError('Invalid request data')
username = data.get('username')
password = data.get('password')
print('Received login request for username:', username)
user = User.query.filter_by(username=username).first()
print("Crossed db check")
if user and user.role == "user":
print("logging in")
login_user(user)
print("logged in")
return jsonify(message='Login successful', user_id=user.id), 200
else:
return jsonify(message='Invalid username or password'), 401
except Exception as e:
print('Error during login:', e)
return jsonify(message='An error occurred during login'), 500
Vue –
Axios:
import axios from 'axios';
// Create an Axios instance with common settings
const axiosInstance = axios.create({
baseURL: 'http://127.0.0.1:5000',
withCredentials: true, // This allows cookies to be sent
});
// Function to get CSRF token
async function getCsrfToken() {
try {
const response = await axiosInstance.get('/get_csrf_token');
const csrfToken = response.data.csrf_token;
axiosInstance.defaults.headers.common['X-CSRFToken'] = csrfToken;
console.log('CSRF token set:', csrfToken);
return csrfToken;
} catch (error) {
console.error('Error fetching CSRF token:', error);
}
}
// Call getCsrfToken immediately to set the CSRF token on app load
getCsrfToken();
// Function to login a user
async function loginUser(username, password) {
try {
const response = await axiosInstance.post('/user_login', {
username,
password,
});
return response.data;
} catch (error) {
console.error('Error during login:', error);
throw error; // Propagate error to the caller
}
}
export { getCsrfToken, loginUser };
What could be causing Flask to not recognize the CSRF token, and how can I resolve this issue?
Things I have tried:
Ensuring withCredentials is set to true in Axios.
Printing the CSRF token to the console to verify it’s being fetched and set correctly.
Checking network requests to confirm the CSRF token is included in the headers.
Rishit Pant is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.