Sessions & Cookies — User Authentication in Flask
804 words
4 min read
Visual companion
Python
Type and operator map
Python Week 1: the first filter for runtime behavior
View
Revision summary
What this note is really saying
Short form
# Sessions & Cookies — User Authentication in Flask ## 🎯 Learning Objectives - Understand why HTTP needs sessions (statelessness) - Use Flask sessions for user-specific data - Implement login/logout with session management - Secure passwords with hashing - Protect routes from unauthorized access ## 1. Why Sessions?

Sessions & Cookies — User Authentication in Flask
🎯 Learning Objectives
- Understand why HTTP needs sessions (statelessness)
- Use Flask sessions for user-specific data
- Implement login/logout with session management
- Secure passwords with hashing
- Protect routes from unauthorized access
1. Why Sessions?
HTTP is stateless — each request is independent. But web apps need to remember:
- "Is this user logged in?"
- "What's in their shopping cart?"
- "What's their language preference?" Cookies store data in the browser. Sessions store data on the server, with only a session ID in the cookie.
2. Flask Sessions
Flask sessions are client-side (data is encrypted and stored in the cookie itself).
pythonfrom flask import Flask, session, redirect, url_for app = Flask(__name__) app.secret_key = 'your-secret-key-here' # Required for sessions! @app.route('/') def index(): # Store in session session['username'] = 'alice' session['visits'] = session.get('visits', 0) + 1 return f'Visits: {session["visits"]}' @app.route('/clear') def clear_session(): session.clear() # Remove all session data return 'Session cleared'
Important:
secret_key is mandatory for sessions. The key signs the cookie cryptographically to prevent tampering.3. User Authentication
3.1 Login
python@app.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'POST': username = request.form['username'] password = request.form['password'] with get_db() as conn: user = conn.execute( 'SELECT * FROM users WHERE username = ?', (username,) ).fetchone() if user and check_password_hash(user['password'], password): session['user_id'] = user['id'] session['username'] = user['username'] flash('Login successful!', 'success') return redirect('/dashboard') else: flash('Invalid credentials!', 'error') return render_template('login.html')
3.2 Logout
python@app.route('/logout') def logout(): session.pop('user_id', None) session.pop('username', None) flash('You have been logged out.', 'info') return redirect('/')
3.3 Protecting Routes
pythonfrom functools import wraps def login_required(f): @wraps(f) def decorated_function(*args, **kwargs): if 'user_id' not in session: flash('Please log in first!', 'warning') return redirect('/login') return f(*args, **kwargs) return decorated_function @app.route('/dashboard') @login_required # Must be logged in def dashboard(): return render_template('dashboard.html', username=session['username'])
3.4 Password Hashing
Never store passwords in plain text! Use Werkzeug's hashing:
python# pip install Werkzeug (comes with Flask) from werkzeug.security import generate_password_hash, check_password_hash # When user registers: hashed = generate_password_hash(password) conn.execute('INSERT INTO users (username, password) VALUES (?, ?)', (username, hashed)) # When user logs in: if check_password_hash(stored_hash, password): # Password matches!
4. Session in Templates
html{% if session.username %} <p>Welcome, {{ session.username }}!</p> <a href="/logout">Logout</a> {% else %} <a href="/login">Login</a> <a href="/register">Register</a> {% endif %}
5. Security Best Practices
- Strong secret key: Use
os.urandom(24).hex()to generate - HTTPS: Set
SESSION_COOKIE_SECURE = Truein production - HttpOnly: Cookies not accessible via JavaScript (default in Flask)
- Session timeout: Set
PERMANENT_SESSION_LIFETIME - Password hashing: Always use
generate_password_hash(uses pbkdf2:sha256)
6. Practice Questions
Q1: Why are sessions needed in web applications?Answer: HTTP is stateless — each request is independent. Sessions allow the server to remember user-specific data across requests (login status, preferences, cart contents). Flask stores session data in an encrypted cookie on the client side. Q2: What does app.secret_key do?Answer: It's used to cryptographically sign session cookies. Without it, Flask can't secure session data. The key should be a random string kept secret. If someone knows your secret_key, they can forge session cookies. Q3: How do you protect a route so only logged-in users can access it?Answer: Create alogin_requireddecorator that checkssession['user_id']and redirects to login if absent:pythondef login_required(f): @wraps(f) def wrapper(*args, **kwargs): if 'user_id' not in session: return redirect('/login') return f(*args, **kwargs) return wrapperQ4: How should passwords be stored?Answer: Never in plain text. Usegenerate_password_hash()which salts and hashes the password (default: pbkdf2:sha256 with a random salt). Verify withcheck_password_hash(). Q5: What's the difference between session.pop and session.clear?Answer:session.pop('key')removes a specific key.session.clear()removes all session data (effectively logging the user out completely). Q6: How do you make session cookies secure in production?Answer: Setapp.config['SESSION_COOKIE_SECURE'] = True(HTTPS only),SESSION_COOKIE_HTTPONLY = True(not accessible via JS), andSESSION_COOKIE_SAMESITE = 'Lax'(CSRF protection). Q7: What happens if you don't set a secret_key?Answer: Flask raises a RuntimeError when you try to use sessions or flash messages: "The session is unavailable because no secret key was set." Q8: How do you check if a user is logged in a template?html{% if 'user_id' in session %} <p>Welcome back, {{ session.username }}!</p> {% else %} <a href="/login">Login</a> {% endif %}
📐 Key Concepts
| Concept | Code | Purpose |
|---|---|---|
| Set session | session['key'] = value | Store data |
| Get session | session.get('key') | Retrieve data |
| Remove key | session.pop('key') | Delete specific data |
| Clear all | session.clear() | Logout (destroy all) |
| Hash password | generate_password_hash(pwd) | Secure storage |
| Verify password | check_password_hash(hash, pwd) | Login check |