Implementing Session Timeout in Flask

Step-by-step guide to adding session timeouts in Flask.


What is session timeout in web application?

A "session timeout" in a web application refers to period of inactivity where a user's session automatically expires if they don't interact with the application for a certain amount of time, effectively logging them out and requiring them to re-authenticate to access the site again.

This is a security measure to prevent unauthorized access to sensitive data in case a user leaves their computer unattended and reduces server load as well.

How It Works?

  • When a user logs in, a session is created on the server.

  • If the user remains inactive for a defined period (e.g., 10 minutes), the session expires.

  • The user is logged out and redirected to the login page.

  • If the user interacts with the application before timeout, the session is refreshed.

How to Implement?

You can implement session timeout in Flask by using Flask's session management along with JavaScript on the frontend to detect user inactivity. Here's how you can do it:

Let’s first create a simple web app. Our app will look like:-

Flow of the app will be:-

  • When you visit / or /home, you will land at the home page.

  • /about and /contact are protected endpoints. When you visit /about or /contact

    • If you are not signed-in, you will be redirected to login page. After successful login, a session is created and you will return to the page from where you have come from.

    • If you are a signed-in user, you will be redirected to the respective page.

  • When you visit /products, you will arrive at the products page. No sign-in is required to access this page.

  • When you click on the Sign In button, a sign-in form will open. After successful login, a session is created and you will be redirected to the Home page.

  • Clicking the Log Out button ends the session and logs the user out of the web app.

  • If you stay inactive on the app for more than 5 minutes, you will be automatically logged out, and the session will end.

Now open VS Code and set up the folders and files as shown below:-

Frontend (JavaScript)

To track user inactivity and automatically redirect them to the login page, use JavaScript.

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Web App</title>
    <style>
        .navbar {
            display: flex;
            align-items: baseline;
            column-gap: 15px;
            background-color: antiquewhite;
        }

        h2 {
            margin: 0;
        }

        a {
            text-decoration: none;
        }

        p {
            margin: 0px 0px 0px 35vw;
        }
    </style>
</head>
<body>
    <div class="navbar">
        <h2>MyApp</h2>
        <a href="{{ url_for('home') }}">Home</a>
        <a href="{{ url_for('about') }}">About</a>
        <a href="{{ url_for('contact') }}">Contact</a>
        <a href="{{ url_for('products') }}">Products</a>
        <a href="{{ url_for('login') }}"><button>Sign In</button></a>
        <a href="{{ url_for('logout') }}"><button>Log Out</button></a>
        {% if session["user_name"] %}
        <p>Welcome {{session["user_name"]}}!</p>
        {% endif %}
    </div>
    <hr>

    {% block content %}
    {% endblock %}

    <script>
        let idleTime = 0;

        function resetTimer() {
            idleTime = 0;
        }

        function checkIdleTime() {
            idleTime++;
            if (idleTime > 5 * 60) {  // 5 minutes (300 seconds)
                window.location.href = "/login";
            }
        }

        // Reset timer on user activity
        window.onload = resetTimer;
        document.onmousemove = resetTimer;
        document.onkeypress = resetTimer;
        document.onscroll = resetTimer;
        document.onclick = resetTimer;

        // Check idle time every second
        setInterval(checkIdleTime, 1000);
    </script>

</body>
</html>

The frontend JavaScript detects inactivity and redirects users to the login page if no activity is detected for 5 minutes.

home.html

{% extends "index.html" %}

{% block content %}
<main>
    <h3>You are at the home page!!</h3>
</main>
{% endblock %}

about.html

{% extends "index.html" %}

{% block content %}
<main>
    <h3>You are at the About page!!</h3>
</main>
{% endblock %}

contact.html

{% extends "index.html" %}

{% block content %}
<main>
    <h3>You are at the Contact page!!</h3>
</main>
{% endblock %}

products.html

{% extends "index.html" %}

{% block content %}
<main>
    <h3>Below are the products that we offer.</h3>
    <ul>
        <li>Sofas</li>
        <li>Chairs</li>
        <li>Tables</li>
        <li>Swings</li>
    </ul>
</main>
{% endblock %}

login.html

{% extends "index.html" %}

{% block content %}
<main>
    <h3>Please fill the below form to sign-in!!</h3>
    <form action="{{ url_for('login') }}" method="post">
        <input type="text" value="{{next}}" name="next" hidden>
        <div>
            <label for="username">Username</label>
            <input type="text" id="username" name="username">
        </div>
        <div>
            <label for="password">Password</label>
            <input type="password" id="password">
        </div>
        <div>
            <button type="submit">Submit</button>
        </div>
    </form>
</main>
{% endblock %}

Backend (Flask)

Create a persistent session that lasts for 5 minutes.

If you are creating persistent client-side session use below code.

app.py

from flask import Flask, session, request, redirect, render_template, url_for, make_response
from datetime import timedelta

app = Flask(__name__)
app.config["SECRET_KEY"] = "supersecretkey"  # Required for session security
app.config['PERMANENT_SESSION_LIFETIME'] =  timedelta(minutes=5)



@app.route('/')
@app.route('/home')
def home():
    print("Session data is: ", session)
    return render_template('home.html')


@app.route('/about')
def about():
    # checking whether a user is logged in or not
    if "user_name" not in session:
        return redirect(url_for('login') + f"?next={request.url}")

    return render_template('about.html')


@app.route('/contact')
def contact():
    # checking whether a user is logged in or not
    if "user_name" not in session:
        return redirect(url_for('login') + f"?next={request.url}")

    return render_template('contact.html')


@app.route('/products')
def products():
    return render_template('products.html')


@app.route('/login', methods=['GET', 'POST'])
def login():
    next_url = request.args.get("next")
    if request.method == 'POST':
        session.permanent = True
        # creating session data during login
        session["user_name"] = request.form.get('username')
        session["lang"] = "en"
        session["theme"] = "dark"

        next_url = request.form.get("next")
        return redirect(next_url if next_url!='None' else url_for("home"))

    return render_template('login.html', next=next_url)


@app.route('/logout')
def logout():
    session.clear()     # clears the session data
    return "Signed Out!!!"


if __name__ == '__main__':
    app.run(debug=True)

If you are creating persistent server-side session use below code.

app.py

from flask import Flask, session, request, redirect, render_template, url_for, make_response
from datetime import timedelta
from flask_session import Session     # Required for server-side session

app = Flask(__name__)
app.config["SECRET_KEY"] = "supersecretkey"  # Required for session security
app.config["SESSION_TYPE"] = "filesystem"
app.config['PERMANENT_SESSION_LIFETIME'] =  timedelta(minutes=5)
Session(app)



@app.route('/')
@app.route('/home')
def home():
    print("Session data is: ", session)
    return render_template('home.html')


@app.route('/about')
def about():
    # checking whether a user is logged in or not
    if "user_name" not in session:
        return redirect(url_for('login') + f"?next={request.url}")

    return render_template('about.html')


@app.route('/contact')
def contact():
    # checking whether a user is logged in or not
    if "user_name" not in session:
        return redirect(url_for('login') + f"?next={request.url}")

    return render_template('contact.html')


@app.route('/products')
def products():
    return render_template('products.html')


@app.route('/login', methods=['GET', 'POST'])
def login():
    next_url = request.args.get("next")
    if request.method == 'POST':
        # creating session data during login
        session["user_name"] = request.form.get('username')
        session["lang"] = "en"
        session["theme"] = "dark"

        next_url = request.form.get("next")
        return redirect(next_url if next_url!='None' else url_for("home"))

    return render_template('login.html', next=next_url)


@app.route('/logout')
def logout():
    session.clear()     # clears the session data
    return "Signed Out!!!"


if __name__ == '__main__':
    app.run(debug=True)

Now open the flask server and visit the web app by clicking the link http://127.0.0.1:5000/.

You will arrive at the home page. Open the Cookies section under the "Application" tab in the developer tools. Click the Sign In button and log in. Once you are logged in, a persistent session will be created that lasts for 5 minutes of user inactivity. Sit idle for 5 minutes. You will find that the session has ended, and you are automatically logged out and redirected to the login page.


Thank you for your time! 😊

Connect with me on LinkedIn