I am trying to build an authentication application for the first time using flask and flask session for the backend and Nextjs for the frontend. Upon research I came across this article on medium link, which I followed carefully.
config.py
# Import the `load_dotenv` function from the `dotenv` library.
# This is used to load environment variables from a `.env` file.
from dotenv import load_dotenv
# Import the built-in `os` module, which provides functions to interact with the operating system.
# It is used here to access environment variables.
import os
# Import the `redis` library, which is a Python client for Redis.
# Redis is commonly used for caching, real-time analytics, and message queuing in web applications.
import redis
load_dotenv()
secret_key = os.getenv('DATABASE_SECRET_KEY')
class ApplicationConfig:
SECRET_KEY = os.getenv('SECRET_KEY')
SQLALCHEMY_TRACK_MODIFICATIONS = False
SQLALCHEMY_ECHO = True
SQLALCHEMY_DATABASE_URI = f'mysql+pymysql://root:{secret_key}@localhost:3306/user_register'
# Here we use Redis for server-side sessions to keep the authenticated session alive.
# Enable session configuration and set it to use Redis
SESSION_TYPE = "redis"
# Set session as not permanent, meaning sessions expire when the user logs out or after a certain period of inactivity
SESSION_PERMANENT = False
# Use a secret key signer for session data to enhance security
SESSION_USE_SIGNER = True
# Configure the path to the Redis server
SESSION_REDIS = redis.from_url("redis://127.0.0.1:6379")
app.py
from flask import Flask, request, jsonify, session
# This is used to load environment variables from a `.env` file.
from dotenv import load_dotenv
# Import the built-in `os` module, which provides functions to interact with the operating system.
# It is used here to access environment variables.
import os
# Import Bcrypt for password hashing
from flask_bcrypt import Bcrypt
from flask_sqlalchemy import SQLAlchemy
# Import Flask-Session for session management
from flask_session import Session
# Import Flask-CORS for Cross-Origin Resource Sharing
from flask_cors import CORS
# Import your application configuration from config.py
from config import ApplicationConfig
#create a flask application
app = Flask(__name__)
# initialize application
app.config.from_object(ApplicationConfig)
#for pasword hashing
bcrypt = Bcrypt(app)
#set up the session
server_session = Session(app)
#for Cross-origin resource sharing
CORS(app, supports_credentials=True)
# Create an instance of the SQLAlchemy extension
db = SQLAlchemy(app)
with app.app_context():
db.create_all()
#Models
#User model
class User(db.Model):
__tablename__ = "users" #for table name
id = db.Column( db.Integer, primary_key=True ) #assigns an id as a primary Key
email = db.Column( db.String(180), unique = True ) #each email given has to be unique
password = db.Column(db.String(255)) #limit bycrypt password hash 30
# Initialize the database
def initialize_database():
with app.app_context():
db.create_all()
#Register User route
@app.route("/api/register", methods=["POST"])
def register_user():
# Get email and password input from the request body
email = request.json["email"]
password = request.json["password"]
# Check if the user with the given email already exists
user_exists = User.query.filter_by(email=email).first() is not None
if user_exists:
# Return an error response if the user already exists (HTTP status code 409 - Conflict)
return jsonify({"error": "User already exists"}), 409
# Hash the password using the Bcrypt library
hashed_password = bcrypt.generate_password_hash(password)
# Create a new User instance with the email and hashed password
new_user = User(email=email, password=hashed_password)
# Add the new user to the database session
db.session.add(new_user)
# Commit the changes to the database
db.session.commit()
# Set the user's session to keep them logged in
session["user_id"] = new_user.id
# Return a JSON response with the new user's ID and email
return jsonify({
"id": new_user.id,
"email": new_user.email
})
#Login route
@app.route("/api/login", methods=["POST"])
def login_user():
email = request.json["email"]
password = request.json["password"]
# Query the database to find a user with the provided email
user = User.query.filter_by(email=email).first()
if user is None:
# Return an error response if the user does not exist (HTTP status code 401 - Unauthorized)
return jsonify({"error": "Unauthorized"}), 401
# Check if the provided password matches the stored hashed password
if not bcrypt.check_password_hash(user.password, password):
# Return an error response if the password does not match (HTTP status code 401 - Unauthorized)
return jsonify({"error": "Unauthorized"}), 401
# Set the user's session to log them in
session["user_id"] = user.id
# Return a JSON response with the user's ID and email to indicate successful login
return jsonify({
"id": user.id,
"email": user.email
})
# Run the application
if __name__ == "__main__":
initialize_database()
app.run(debug=True, port=5555)
When I run the command at the terminal:
flask run
Since I have already set My flask app in the .env. The application works well. Upon testing the routes like the register and the login route I keep getting this error:
ERROR:
RuntimeError: The session is unavailable because no secret key was set. Set the secret_key on the application to something unique and secret.
I really do know why because upon further research I had to set up the SECRET_KEY which I beleive I have already done in my config.py file.
Here is another thing in postman, the register route when I test it with some raw data it first shows the error and if I click it again it shows that it has been inserted into the database. But when I test the login route it doesnt work, it get stucked at the same error.
Please what is missing?
2
Answers
So after getting the error persistently, I decided to start over again and then encountering the same error, but this time I found out that I was missing two necessary steps.
#Step 1: start the redis server I brewed install redis on my macos
Then started the server
I also installed redis in the virtual environment of my application
#Step 2: add the session settings to the ApplicationConfig class in the config.py
import redis from decouple import config from dotenv import load_dotenv load_dotenv()
After making this modifications to the code. I tested the register and the login url in postman and the error didnt come up again.
From what you shared it seems you are missing
.env
file!Create a file called
.env
at the root directory of flask project.in that file put this:
replace "your_secret_key_here" with a proper secret.
in order to debug your code, put this line at the
config.py
to see if the secret is correctly set or not: