I am working with a Flask project with React as front-end. I just completed the authentication work. When i tried to access the user_id which i stored in session as 'user_data' from another route via an 'axios' request, I wasn't able to access it as it said 'No data found in session'. I have encountered some like these before which will resolve if I add 'withCredentials: true' along my 'axios' request. I tried it too but nothing worked. So i even made a custom flask route that just gets the session and if there is no data it prints something like 'No_data'. As i expected it printed 'No_data'. Now I tried to print the session data in the login route itself right after creating it and it works there but it won't in other route. So the session is being created and stored but not shared across routes... I will also share my required code.
from flask import Flask, request, jsonify, session
from datetime import datetime, timedelta
from flask_cors import CORS
import threading
import uuid
import firebase_admin
from firebase_admin import credentials, firestore
app = Flask(__name__)
app.secret_key = "HelloWorld"
app.config["SESSION_PERMANENT"] = True
app.config["PERMANENT_SESSION_LIFETIMT"] = timedelta(days = 1)
CORS(app,supports_credentials=True, resources={r"/*": {"origins":"http://localhost:5173"}})
@app.after_request
def apply_cors_headers(response):
response.headers["Access-Control-Allow-Origin"] = "http://localhost:5173" # Allow your React app's origin
response.headers["Access-Control-Allow-Credentials"] = "true" # Allow cookies (sessions)
response.headers["Access-Control-Allow-Headers"] = "Content-Type" # Allow content-type headers
response.headers["Access-Control-Allow-Methods"] = "POST, GET, OPTIONS" # Allow specific methods
return response
#Route for axios
@app.route('/login', methods=['POST'])
def login():
data = request.get_json()
usermail = data.get("usermail")
password = data.get("password")
email_query = user_collection.where("usermail", "==", usermail).stream()
user_doc = next(email_query, None)
if user_doc is None:
return jsonify({"message": "User not registered"}), 404
user_data = user_doc.to_dict()
if user_data.get("password") != password:
return jsonify({"message": "Invalid credentials"}), 401
telegram_id = user_data.get("telegramID", "")
first_login = telegram_id.strip() == ""
# Store user data in session
session.permanent = True
session["user_data"] = user_data
session.modified = True
print(session["user_data"]) #This prints the session as it is
return jsonify({
"message": "Login successful",
"first_login": first_login
}), 200
@app.route('/addTelegramID', methods=['POST'])
def add_telegram_id():
if 'user_data' not in session: #This gets executes showing it clearly session is not accessible
print("Error")
data = request.get_json()
user_data = session.get('user_data')
print(user_data)
if user_data:
user_id = user_data["user_id"]
if not user_data:
print("NO data")
return jsonify({"message": "Unauthorized"}), 401
telegram_id = data.get("telegramID")
if not telegram_id:
return jsonify({"message": "Telegram ID is required"}), 400
user_query = user_collection.where("user_id", "==", user_id).stream()
user_doc = next(user_query, None)
if user_doc is None:
return jsonify({"message": "User not found"}), 404
user_collection.document(user_doc.id).update({"telegramID": telegram_id})
return jsonify({"message": "Telegram ID added successfully"}), 200
#Testing route
@app.route('/test')
def test():
user_data = session.get('user_data')
if user_data:
return user_data
else:
return jsonify({"message":"No data"}) #Again this gets executed showing there is no data accessible
if __name__ == '__main__':
from scheduler import start_scheduler
threading.Thread(target=start_scheduler, args=(reminders,), daemon=True).start()
app.run(debug=True)
Is there anything I am missing ??
You should familiarize yourself with the Same Site Policy. This is likely responsible for rejecting session data in the backend. You can either use a proxy in the background or use third-party cookies.
You define a proxy in the package.json
file when using "Create React App". This forwards requests to the frontend server to the backend server. Both CORS and cookie issues are thus obsolete, as they are the same site.
"proxy": "http://localhost:5000"
If you use Vite, you can configure the proxy in the vite.config.js
file. A description can be found here.
However, if you later, during deployment, do not want to run your frontend and backend behind the same proxy server, you can use third-party cookies. The following configuration is required for this.
app.config["SESSION_COOKIE_SAMESITE"]="None"
app.config["SESSION_COOKIE_SECURE"]=True