Flask-Login

0.6.3 · active · verified Sun Mar 29

Flask-Login is a popular extension for Flask that provides user session management. It handles the common tasks of logging in, logging out, and remembering user sessions over extended periods. Version 0.6.3 is currently active, with a release cadence that addresses compatibility with newer Flask and Werkzeug versions, and ongoing maintenance.

Warnings

Install

Imports

Quickstart

This quickstart demonstrates a minimal Flask application with Flask-Login. It initializes the LoginManager, defines a simple `User` class inheriting `UserMixin`, implements a `user_loader` callback to load users by ID, and provides basic login, logout, and a protected route. Remember to set a strong `SECRET_KEY` in production. User authentication logic (e.g., password hashing) and user storage are handled by the application, not Flask-Login directly.

import os
from flask import Flask, redirect, url_for, request, render_template_string
from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required, current_user

app = Flask(__name__)
app.config['SECRET_KEY'] = os.environ.get('FLASK_SECRET_KEY', 'a_secret_key_for_dev_only') # IMPORTANT: Change in production!

login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login'

# A simple 'database' for demonstration
USERS = {
    "testuser": {"password": "testpass", "id": "1"},
    "another": {"password": "anotherpass", "id": "2"}
}

class User(UserMixin):
    def __init__(self, id, password, username):
        self.id = id
        self.password = password
        self.username = username

    def get_id(self):
        return str(self.id)

@login_manager.user_loader
def load_user(user_id):
    # This callback is used to reload the user object from the user ID stored in the session.
    # It should take the unicode ID of a user, and return the corresponding user object.
    for username, data in USERS.items():
        if data['id'] == user_id:
            return User(data['id'], data['password'], username)
    return None

@app.route('/')
def index():
    if current_user.is_authenticated:
        return f'Hello, {current_user.username}! <a href="{url_for("protected")}">Protected Page</a> | <a href="{url_for("logout")}">Logout</a>'
    return '<a href="/login">Login</a>'

@app.route('/login', methods=['GET', 'POST'])
def login():
    if current_user.is_authenticated:
        return redirect(url_for('index'))

    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']
        if username in USERS and USERS[username]['password'] == password:
            user_data = USERS[username]
            user = User(user_data['id'], user_data['password'], username)
            login_user(user)
            next_page = request.args.get('next')
            return redirect(next_page or url_for('index'))
        return 'Invalid credentials'
    return render_template_string('''
        <form method="post">
            <p><input type=text name=username placeholder="Username"></p>
            <p><input type=password name=password placeholder="Password"></p>
            <p><input type=submit value=Login></p>
        </form>
    ''')

@app.route('/logout')
@login_required
def logout():
    logout_user()
    return redirect(url_for('index'))

@app.route('/protected')
@login_required
def protected():
    return f'This is a protected page. Only {current_user.username} can see this! <a href="{url_for("index")}">Home</a>'

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

view raw JSON →