1

I'm trying to neatly compartmentalize my code by separating flask app, service component and a decoupled key/value pair store.

My web app looks like this:

import flask
import os
import service_component as service

app = flask.Flask(__name__)

@app.route("/", methods=["POST"])
def event():
    service.dostuff()
    return "ok", 200

if __name__ == "__main__":
    app.run(port=5000, debug=True)
    # for test purposes
    app.secret_key = os.urandom(24)

My service_component is:

import key_value_store

def dostuff():
    val_i_want = key_value_store.provider["key"]

...and key_value_store looks like:

from flask import session

class SessionProvider:
    def __getitem__(self, key):
            return session.get(key)

    def __setitem__(self, key, value):
            session[key] = value

provider = SessionProvider()

The problem is that when I run the program, I get the error:

RuntimeError: The session is unavailable because no secret key was set. Set the secret_key on the application to something unique and secret.

Is there some requirement to keep the usage of "session" in my web app file? Are there recommended ways around this that still let me maintain loose coupling of components/abstraction of the key/value pair store?

Colin
  • 4,025
  • 21
  • 40

1 Answers1

2

Don't set the secret key here:

if __name__ == "__main__":
    app.secret_key = os.urandom(24)
    app.run(port=5000, debug=True)
        return "ok", 200 # Also this does nothing here

The above will only apply when running with python app.py not with flask run or a WSGI server.

Also this would change the secret key on each launch, which you want to avoid. You should really be loading a pre-defined key in via your config, so user cookies aren't invalidated on each app restart. This sounds like it could lead to some weird session persistance behaviour.

If you don't have a config loader (yet), you can just hard-code the value right after you define the app:

app = Flask(__name__)
app.config['SECRET_KEY'] = 'super_secure'

Of course set that key to something sensible. If you want to generate this with Python, use the secrets module rather than os.urandom. However, again, you should passing the key as an actual string, rather than generating it dynamically on each app launch, for the reason mentioned above.

v25
  • 7,096
  • 2
  • 20
  • 36
  • You're right about all that, though my return statement was just a copy/paste flub. However, that's doesn't seem to get at the heart of my question, which is: why is session erroring in the separate module? – Colin Aug 18 '20 at 20:13
  • 1
    Disregard: you were actually right in the main diagnosis; I was debugging in an environment where the key wasn't getting set in dunder main. Thank you!!! – Colin Aug 18 '20 at 20:19