Internal Server Error when using Flask session

52,086

Solution 1

According to Flask sessions documentation:

... What this means is that the user could look at the contents of your cookie but not modify it, unless they know the secret key used for signing.

In order to use sessions you have to set a secret key.

Set secret key. And you should return string, not int.

#!/usr/bin/env python

from flask import Flask, session

app = Flask(__name__)

@app.route('/')
def run():
    session['tmp'] = 43
    return '43'

if __name__ == '__main__':
    app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'
    app.run()

Solution 2

As @falsetru mentioned, you have to set a secret key.

Before sending the session cookie to the user's browser, Flask signs the cookies cryptographically, and that doesn't mean that you cannot decode the cookie. I presume that Flask keeps track of the signed cookies, so it can perform it's own 'magic', in order to determine if the cookie that was sent along with the request (request headers), is a valid cookie or not.

Some methods that you may use, all related with Flask class instance, generally defined as app:

  • defining the secret_key variable for app object

    app.secret_key = b'6hc/_gsh,./;2ZZx3c6_s,1//'
    
  • using the config() method

    app.config['SECRET_KEY'] = b'6hc/_gsh,./;2ZZx3c6_s,1//'
    
  • using an external configuration file for the entire Flask application

    $ grep pyfile app.py
    app.config.from_pyfile('flask_settings.cfg')
    
    $ cat flask_settings.py
    SECRET_KEY = b'6hc/_gsh,./;2ZZx3c6_s,1//'
    

Here's an example (an adaptation from this article), focused on providing a more clearer picture of Flask session cookie, considering the participation of both Client and Server sides:

from flask import Flask, request, session                                       
import os                                                                       

app = Flask(__name__)                                                           

@app.route('/')                                                                 
def f_index():                                                               
    # Request Headers, sent on every request                                    
    print("\n\n\n[Client-side]\n", request.headers)                             
    if 'visits' in session:                                                     
        # getting value from session dict (Server-side) and incrementing by 1   
        session['visits'] = session.get('visits') + 1                           
    else:                                                                       
        # first visit, generates the key/value pair {"visits":1}                
        session['visits'] = 1                                                   
        # 'session' cookie tracked from every request sent                          
        print("[Server-side]\n", session)                                           
    return "Total visits:{0}".format(session.get('visits'))                     


if __name__ == "__main__":                                                      
    app.secret_key = os.urandom(24)                                             
    app.run()

Here's the output:

$ python3 sessions.py 
* Serving Flask app "sessions" (lazy loading)
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

[Client-side]
Upgrade-Insecure-Requests: 1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Connection: keep-alive
Host: 127.0.0.1:5000
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.5

[Server-side]
<SecureCookieSession {'visits': 1}>
127.0.0.1 - - [12/Oct/2018 14:27:05] "GET / HTTP/1.1" 200 -


[Client-side]
Upgrade-Insecure-Requests: 1
Cookie: session=eyJ2aXNpdHMiOjF9.DqKHCQ.MSZ7J-Zicehb6rr8qw43dCVXVNA  # <--- session cookie
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Connection: keep-alive
Host: 127.0.0.1:5000
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.5

[Server-side]
<SecureCookieSession {'visits': 2}>
127.0.0.1 - - [12/Oct/2018 14:27:14] "GET / HTTP/1.1" 200 -

You may have noticed that in the example above, I'm using the os lib and the urandom() function, in order to generate Flask's secret key, right?

From the official doc:

How to generate good secret keys

A secret key should be as random as possible. Your operating system has ways to generate pretty random data based on a cryptographic random generator. Use the following command to quickly generate a value for Flask.secret_key (or SECRET_KEY):

$ python -c 'import os; print(os.urandom(16))'

b'_5#y2L"F4Q8z\n\xec]/'


PLUS NOTE

As you can see, the creators of Flask support the practice of using os.urandom() for building the Flask secret key, from older versions of the tool to its latest version. So: why @joshlsullivan's answer received downvotes (deserves an upvote) and why @MikhailKashkin writes that, using os.urandom() is terrible idea, are mysteries.

Share:
52,086
sedavidw
Author by

sedavidw

Updated on October 16, 2020

Comments

  • sedavidw
    sedavidw over 3 years

    I want to save an ID between requests, using Flask session cookie, but I'm getting an Internal Server Error as result, when I perform a request.

    I prototyped a simple Flask app for demonstrating my problem:

    #!/usr/bin/env python
    
    from flask import Flask, session
    
    app = Flask(__name__)
    
    @app.route('/')
    def run():
        session['tmp'] = 43
        return '43'
    
    if __name__ == '__main__':
        app.run()
    

    Why I can't store the session cookie with the following value when I perform the request?