Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flask Session() object not permanent

In my Flask API, I'm trying to get sessions to stay permanent, so that it will still be there even after browser closes. My front-end is written in React, and uses the Fetch API to make requests. However, after testing out what I have so far, it doesn't seem to work. My code (left out some irrelevant database stuff that works):

@bp.route('/login', methods=('POST',))
def login():
    ...

    error=None
    res = {}

    db = get_db()
    cursor = db.cursor(dictionary=True)
    ...
    user = cursor.fetchone()

    ...

    if error is None:
        session.clear()
        session.permanent = True
        session['userID'] = user['id']
        current_app.logger.debug(session['userID'])

        res['actionSuccess']= True
    else:
        res['actionSuccess'] = False
        res['error'] = error

    return jsonify(res)

So far, I can tell that sessions is indeed storing the userID value. I then write another route to tell me if an userID value is stored in session, like so:

@bp.route('/init', methods=('GET',))
def init():
    userID = session.get('userID') 
    if userID is None:
        res = {"signedIn": False}
    else:
        res = {"signedIn": True, "username": userID}
    return jsonify(res)

However, everytime I make the call to '/init', it returns False even though I previously signed in. I don't know why session isn't permanent here. Is it because I'm running the client locally on my machine? Do I need to allow cookies somewhere on my Chrome browser? I used Chrome to look into the cookies stored for the client, and no "sessions" was stored there. Do I have to something extra on the front-end to store the cookies/session, or do they store automatically? Am I misunderstanding the usage of Flask sessions?

like image 203
albert Avatar asked Oct 20 '25 10:10

albert


1 Answers

Found out why sessions wasn't working after a lot of research! Flask sessions are essentially cookies, and I was using the Fetch API to perform CORS operations. Fetch() by default does not allow cookies to be received or sent, and must be configured in order to use Flask sessions.

On my React.js client, I did this by setting 'include' for 'credentials':

        fetch(url, {
            method: 'POST',
            mode: 'cors',
            body: JSON.stringify(loginObj),
            credentials: 'include',
            headers: {
                'Content-Type': 'application/json'
            }
        })
        .then(res => res.json())
        ...

Because of this configuration, the request isn't considered a "simple request", and the client will actually "preflight" the POST request with an OPTIONS request. This means that before my POST request is sent, a OPTIONS request testing to see if the server has the correct access will be sent to my Flask server first.

The preflight OPTIONS request will test to see if the response from the server has the correct headers containing "Access-Control-Allow-Origin", 'Access-Control-Allow-Credentials', and 'Access-Control-Allow-Headers'. If the test sent by the OPTIONS request fails, the actual POST request will not be sent and you'll get a Fetch error.

I then set the headers accordingly on my Flask server like so:

@bp.route('/login', methods=('POST','OPTIONS'))
def login():
    if request.method == 'OPTIONS':
        resp = Response()
        resp.headers['Access-Control-Allow-Origin'] = clientUrl
        resp.headers['Access-Control-Allow-Credentials'] = 'true'
        resp.headers['Access-Control-Allow-Headers'] = "Content-Type"

        return resp
    else:

        '''
        use session for something  
        '''  

        res['actionSuccess'] = False
        js = json.dumps(res)

        resp = Response(js, status=200, mimetype='application/json')        
        resp.headers['Access-Control-Allow-Origin'] = clientUrl
        resp.headers['Access-Control-Allow-Credentials'] = 'true'
        resp.headers['Access-Control-Allow-Headers'] = "Content-Type"

        return resp

Take note that 'Access-Control-Allow-Credentials' was set to 'true' as opposed to the Python boolean True, as the client will not recognize the Python boolean.

And with that, a Flask Session object should be stored in your cookies.

like image 118
albert Avatar answered Oct 22 '25 05:10

albert