Difficulty: Intermediate
Cookies and sessions are mechanisms for maintaining state across HTTP requests. HTTP is stateless by nature, meaning each request is independent. Cookies store small pieces of data in the browser, while sessions provide server-side state management. Flask uses a clever approach where sessions are actually stored in signed cookies on the client side.
Cookies are key-value pairs that the server sends to the browser via the Set-Cookie response header. The browser stores them and sends them back with every subsequent request to the same domain. You can set cookies by calling response.set_cookie() on a Response object, and read them from request.cookies.
Cookies have several attributes that control their behavior. max_age sets the lifetime in seconds. expires sets an absolute expiration datetime. path restricts the cookie to specific URL paths. domain sets which domain can access the cookie. secure ensures the cookie is only sent over HTTPS. httponly prevents JavaScript from accessing the cookie (important for security). samesite controls cross-site request behavior (Lax or Strict).
Flask sessions provide a higher-level abstraction over cookies. The session object (imported from flask) works like a dictionary. When you modify session data, Flask serializes it, signs it with the app's SECRET_KEY, and stores it in a cookie. On subsequent requests, Flask reads the cookie, verifies the signature, and deserializes the data back into the session object.
The SECRET_KEY is critical for session security. It is used to cryptographically sign the session cookie. If an attacker discovers your secret key, they can forge session data. Always use a strong, random secret key in production and never commit it to version control. Flask uses the itsdangerous library for signing.
Because Flask sessions are stored in cookies (client-side), they have limitations. The total cookie size must be under 4 KB. Session data is visible to the client (though not tamper-proof thanks to signing). For larger session data or truly secret server-side sessions, use an extension like Flask-Session, which stores session data in Redis, Memcached, or a database.
Flask sessions support several configuration options. SESSION_COOKIE_NAME (default 'session') sets the cookie name. PERMANENT_SESSION_LIFETIME (default 31 days) sets the expiration for permanent sessions. SESSION_COOKIE_SECURE ensures the cookie is only sent over HTTPS. SESSION_COOKIE_HTTPONLY prevents JavaScript access. SESSION_COOKIE_SAMESITE controls cross-site behavior.
from flask import Flask, request, make_response
app = Flask(__name__)
@app.route('/set-cookie')
def set_cookie():
resp = make_response('Cookie set!')
resp.set_cookie(
'username', 'alice',
max_age=3600, # 1 hour
httponly=True, # Not accessible via JS
secure=True, # HTTPS only
samesite='Lax' # CSRF protection
)
return resp
@app.route('/get-cookie')
def get_cookie():
username = request.cookies.get('username', 'Guest')
return f'Hello, {username}!'
@app.route('/delete-cookie')
def delete_cookie():
resp = make_response('Cookie deleted!')
resp.delete_cookie('username')
return resp
Cookies are set on the response with set_cookie() and read from request.cookies. Always set httponly for sensitive cookies and secure for HTTPS. delete_cookie() sends an expired cookie to remove it.
from flask import Flask, session, redirect, url_for, request
app = Flask(__name__)
app.secret_key = 'your-secret-key-change-in-production'
@app.route('/')
def index():
if 'username' in session:
return f'Logged in as {session["username"]}'
return 'You are not logged in'
@app.route('/login', methods=['POST'])
def login():
session['username'] = request.form['username']
session['visits'] = session.get('visits', 0) + 1
return redirect(url_for('index'))
@app.route('/logout')
def logout():
session.pop('username', None) # Remove specific key
# Or: session.clear() # Remove everything
return redirect(url_for('index'))
Flask sessions work like dictionaries. Set values with assignment, check with 'in', remove with pop() or clear(). The secret_key is required for session signing. All session data is stored in a signed cookie.
from flask import Flask, session
from datetime import timedelta
app = Flask(__name__)
app.secret_key = 'your-secret-key'
# Session expires after 7 days
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=7)
@app.route('/login', methods=['POST'])
def login():
session.permanent = True # Enable permanent session
session['user_id'] = 42
session['role'] = 'admin'
return {'message': 'Logged in'}
@app.route('/profile')
def profile():
if 'user_id' not in session:
return {'error': 'Not authenticated'}, 401
return {
'user_id': session['user_id'],
'role': session['role']
}
By default, session cookies expire when the browser closes. Setting session.permanent = True makes the session last for PERMANENT_SESSION_LIFETIME (default 31 days). Set it per-request in the login handler.
from flask import Flask
import os
app = Flask(__name__)
# Session configuration
app.config.update(
SECRET_KEY=os.environ.get('SECRET_KEY', 'dev-fallback-key'),
SESSION_COOKIE_NAME='myapp_session',
SESSION_COOKIE_HTTPONLY=True,
SESSION_COOKIE_SECURE=True, # Requires HTTPS
SESSION_COOKIE_SAMESITE='Lax',
PERMANENT_SESSION_LIFETIME=3600, # 1 hour in seconds
)
# For server-side sessions, use Flask-Session:
# pip install Flask-Session
# from flask_session import Session
# app.config['SESSION_TYPE'] = 'redis'
# Session(app)
Configure session cookies for security: httponly prevents XSS cookie theft, secure ensures HTTPS-only, samesite prevents CSRF. For server-side sessions, Flask-Session stores data in Redis or a database instead of cookies.
Cookies, Sessions, SECRET_KEY, session Object, Signed Cookies, Expiration