Quiz 2

Sessions & Cookies — User Authentication in Flask

804 words
4 min read
Python Week 1: the first filter for runtime behavior
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).
python
from 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

python
from 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

  1. Strong secret key: Use os.urandom(24).hex() to generate
  2. HTTPS: Set SESSION_COOKIE_SECURE = True in production
  3. HttpOnly: Cookies not accessible via JavaScript (default in Flask)
  4. Session timeout: Set PERMANENT_SESSION_LIFETIME
  5. 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 a login_required decorator that checks session['user_id'] and redirects to login if absent:
python
def login_required(f):
    @wraps(f)
    def wrapper(*args, **kwargs):
        if 'user_id' not in session:
            return redirect('/login')
        return f(*args, **kwargs)
    return wrapper
Q4: How should passwords be stored?
Answer: Never in plain text. Use generate_password_hash() which salts and hashes the password (default: pbkdf2:sha256 with a random salt). Verify with check_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: Set app.config['SESSION_COOKIE_SECURE'] = True (HTTPS only), SESSION_COOKIE_HTTPONLY = True (not accessible via JS), and SESSION_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

ConceptCodePurpose
Set sessionsession['key'] = valueStore data
Get sessionsession.get('key')Retrieve data
Remove keysession.pop('key')Delete specific data
Clear allsession.clear()Logout (destroy all)
Hash passwordgenerate_password_hash(pwd)Secure storage
Verify passwordcheck_password_hash(hash, pwd)Login check

🔗 Cross-References

Document outline

Keep your place and jump directly to a heading.

Table of Contents
System Normal // Awaiting Context

Intelligence Hub

Navigate the knowledge graph to generate context. The Hub adapts dynamically to surface backlinks, related notes, and metadata insights.