Skip to content

Commit

Permalink
Add regenerate method
Browse files Browse the repository at this point in the history
Closes #27 #39 #65
  • Loading branch information
Lxstr committed Feb 27, 2024
1 parent ede231f commit 80df635
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 17 deletions.
2 changes: 0 additions & 2 deletions docs/config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ Configuration

.. include:: config_cleanup.rst

.. include:: config_security.rst

.. include:: config_exceptions.rst

.. include:: config_flask.rst
Expand Down
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Table of Contents
installation
usage
config
security
api
contributing
license
Expand Down
26 changes: 22 additions & 4 deletions docs/config_security.rst → docs/security.rst
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@

Security
----------------------
==========

.. warning::

Flask is a micro-framework and does not provide all security features out of the box. It is important to configure security settings for your application.

Flask configuration
------------------

Please refer to documentation for `Flask`_, `OWASP`_, and other resources such as `MDN`_ for the latest information on best practice.

Consider the following Flask configurations in production:
Expand All @@ -25,11 +27,27 @@ Consider the following Flask configurations in production:

You can use a security plugin such as `Flask-Talisman`_ to set these and more.

.. warning::
Storage
------------------

Take care to secure your storage and storage client connection. For example, setup SSL/TLS and storage authentication.
Take care to secure your storage and storage client connection. For example, setup SSL/TLS and storage authentication.


Session fixation
------------------

Session fixation is an attack that permits an attacker to hijack a valid user session. The attacker can fixate a user's session by providing them with a session identifier. The attacker can then use the session identifier to impersonate the user.

As one tool among others that can mitigate session fixation, is regenerating the session identifier when a user logs in. This can be done by calling the ``session.regenerate()`` method.

.. code-block:: python
@app.route('/login')
def login():
# your login logic ...
app.session_interface.regenerate(session)
# your response ...
.. _Flask: https://flask.palletsprojects.com/en/2.3.x/security/#set-cookie-options
.. _MDN: https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies
.. _OWASP: https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html
Expand Down
11 changes: 0 additions & 11 deletions examples/hello.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,5 @@ def delete():
return "deleted"


@app.route("/error/")
def error():
raise RedisError("An error occurred with Redis")


@app.errorhandler(RedisError)
def handle_redis_error(error):
app.logger.error(f"Redis error encountered: {error}")
return "A problem occurred with our Redis service. Please try again later.", 500


if __name__ == "__main__":
app.run(debug=True)
63 changes: 63 additions & 0 deletions examples/kitchen-sink.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
from flask import Flask, session
from flask_session import Session
from redis.exceptions import RedisError

app = Flask(__name__)
app.config.from_object(__name__)
app.config.update(
{
"SESSION_TYPE": "redis",
"SECRET_KEY": "sdfads",
"SESSION_SERIALIZATION_FORMAT": "json",
}
)

Session(app)


@app.route("/")
def index():
return "No cookies in this response if it is your first visit."


@app.route("/add-apple/")
def set():
session["apple_count"] = session.get("apple_count", 0) + 1
return "ok"


@app.route("/get-apples/")
def get():
result = str(session.get("apple_count", "no apples"))
return result


@app.route("/login/")
def login():
# Mitigate session fixation attacks
# If the session is not empty (/add-apple/ was previously visited), the session will be regenerated
app.session_interface.regenerate(session)
# Here you would authenticate the user first
session["logged_in"] = True
return "logged in"


@app.route("/logout/")
def delete():
session.clear()
return "deleted"


@app.route("/error/")
def error():
raise RedisError("An error occurred with Redis")


@app.errorhandler(RedisError)
def handle_redis_error(error):
app.logger.error(f"Redis error encountered: {error}")
return "A problem occurred with our Redis service. Please try again later.", 500


if __name__ == "__main__":
app.run(debug=True)
13 changes: 13 additions & 0 deletions src/flask_session/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,19 @@ def _cleanup_n_requests(self) -> None:
if self.cleanup_n_requests and random.randint(0, self.cleanup_n_requests) == 0:
self._delete_expired_sessions()

# SECURITY API METHODS

def regenerate(self, session: ServerSideSession) -> None:
"""Regenerate the session id for the given session."""
if session:
# Remove the old session from storage
self._delete_session(self._get_store_id(session.sid))
# Generate a new session ID
new_sid = self._generate_sid(self.sid_length)
session.sid = new_sid
# Mark the session as modified to ensure it gets saved
session.modified = True

# METHODS OVERRIDE FLASK SESSION INTERFACE

def save_session(
Expand Down

0 comments on commit 80df635

Please sign in to comment.