### Install Flask-Login Source: https://github.com/maxcountryman/flask-login/blob/main/docs/index.md Install the Flask-Login library using pip. This command should be run in your project's virtual environment. ```bash $ pip install flask-login ``` -------------------------------- ### Complete Example: Activity Logging with Multiple Signals Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/api-reference/signals.md A comprehensive example demonstrating how to use multiple Flask-Login signals (user_logged_in, user_logged_out, user_accessed) to implement a robust activity logging system. ```python from flask import Flask from flask_login import LoginManager, login_user, user_logged_in, user_logged_out, user_accessed from datetime import datetime app = Flask(__name__) login_manager = LoginManager(app) class ActivityLog: """Track user activity with signals.""" @staticmethod @user_logged_in.connect_via(app) def log_login(sender, user, **extra): print(f"[{datetime.now()}] User {user.id} logged in") # db.session.add(Log(user_id=user.id, action='login', timestamp=datetime.now())) # db.session.commit() @staticmethod @user_logged_out.connect_via(app) def log_logout(sender, user, **extra): print(f"[{datetime.now()}] User {user.id} logged out") # db.session.add(Log(user_id=user.id, action='logout', timestamp=datetime.now())) # db.session.commit() @staticmethod @user_accessed.connect_via(app) def update_last_activity(sender, **extra): from flask_login import current_user if current_user.is_authenticated: current_user.last_activity = datetime.now() # db.session.commit() ``` -------------------------------- ### Complete Flask-Login Configuration Example Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/configuration.md A comprehensive example demonstrating how to configure Flask-Login within a Flask application factory, including session settings, remember-me cookies, and flash messages. ```python from flask import Flask from flask_login import LoginManager from datetime import timedelta def create_app(): app = Flask(__name__) # Flask config app.config['SECRET_KEY'] = 'your-secret-key' app.config['SESSION_PROTECTION'] = 'strong' app.config['USE_SESSION_FOR_NEXT'] = True # Remember-me cookie config app.config['REMEMBER_COOKIE_DURATION'] = timedelta(days=30) app.config['REMEMBER_COOKIE_SECURE'] = True app.config['REMEMBER_COOKIE_HTTPONLY'] = True app.config['REMEMBER_COOKIE_SAMESITE'] = 'Lax' app.config['REMEMBER_COOKIE_REFRESH_EACH_REQUEST'] = True # Flash messages app.config['LOGIN_MESSAGE'] = 'You must sign in to access this page.' app.config['LOGIN_MESSAGE_CATEGORY'] = 'info' app.config['REFRESH_MESSAGE'] = 'Please verify your identity to continue.' app.config['REFRESH_MESSAGE_CATEGORY'] = 'warning' # LoginManager config login_manager = LoginManager(app) login_manager.login_view = 'auth.login' login_manager.refresh_view = 'auth.refresh' login_manager.session_protection = 'strong' # Blueprint-specific logins login_manager.blueprint_login_views = { 'admin': 'admin.login', 'api': 'api.token_login', } return app ``` -------------------------------- ### Basic Flask-Login Setup Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/README.md Initializes Flask-Login, sets the secret key, configures the LoginManager, and defines a basic User model and user loader callback. ```python from flask import Flask from flask_login import LoginManager, UserMixin, login_user, login_required, current_user app = Flask(__name__) app.secret_key = 'your-secret-key' login_manager = LoginManager() login_manager.init_app(app) login_manager.login_view = 'login' class User(UserMixin): def __init__(self, id): self.id = id @login_manager.user_loader def load_user(user_id): return User(int(user_id)) @app.route('/login') def login(): user = User(1) login_user(user) return 'Logged in' @app.route('/protected') @login_required def protected(): return f'Hello, {current_user.id}' ``` -------------------------------- ### FlaskLoginClient Initialization Example Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/api-reference/test-client.md Demonstrates how to set up a Flask application and FlaskLoginClient for testing. This includes defining a user model, a user loader, and creating a test client, optionally with a pre-logged-in user or by setting FlaskLoginClient as the default test client class. ```python from flask import Flask from flask_login import LoginManager, UserMixin, FlaskLoginClient app = Flask(__name__) app.config['TESTING'] = True app.secret_key = 'test-secret' login_manager = LoginManager(app) class User(UserMixin): def __init__(self, id): self.id = id @login_manager.user_loader def load_user(user_id): return User(int(user_id)) # Create a test client without a logged-in user client = app.test_client_class(app) # Or with a pre-logged-in user user = User(1) client = app.test_client_class(app, user=user) # Or specify app.test_client_class app.test_client_class = FlaskLoginClient client = app.test_client(user=user) ``` -------------------------------- ### Multi-Blueprint Setup with Different Auth Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/integration-guide.md Configures a Flask application with multiple blueprints, each potentially using a different authentication method (sessions vs. tokens). ```python from flask import Blueprint app = Flask(__name__) login_manager = LoginManager() login_manager.init_app(app) # Web blueprint uses sessions web = Blueprint('web', __name__) login_manager.blueprint_login_views['web'] = 'web.login' # API blueprint uses tokens api = Blueprint('api', __name__) login_manager.blueprint_login_views['api'] = 'api.token_auth' @web.route('/login') def login(): # Session-based login pass @api.route('/token') def get_token(): # Issue API token pass app.register_blueprint(web, url_prefix='/web') app.register_blueprint(api, url_prefix='/api') ``` -------------------------------- ### Login User Example Source: https://github.com/maxcountryman/flask-login/blob/main/docs/index.md This snippet demonstrates how to log in a user after successful form validation. It includes redirecting to the next page or the index page, and emphasizes the importance of validating the 'next' parameter to prevent open redirects. ```python from flask import redirect, url_for, request from flask_login import login_user, url_has_allowed_host_and_scheme # Assuming LoginForm and User are defined elsewhere # Assuming app is your Flask application instance @app.route('/login', methods=['GET', 'POST']) def login(): form = LoginForm() if form.validate_on_submit(): # user should be an instance of your `User` class user = User.query.filter_by(username=form.username.data).first() # Example user retrieval if user and user.check_password(form.password.data): # Example password check login_user(user) flask.flash('Logged in successfully.') next = flask.request.args.get('next') if not url_has_allowed_host_and_scheme(next, request.host): return flask.abort(400) return flask.redirect(next or flask.url_for('index')) return flask.render_template('login.html', form=form) ``` -------------------------------- ### Login View Implementation Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/integration-guide.md Handles user login requests using GET and POST methods. It checks credentials, logs the user in using `login_user`, and redirects. Requires a `User` model and `db` session. ```python from flask import Blueprint, render_template, request, redirect, url_for, flash from flask_login import login_user, current_user from wtforms import StringField, PasswordField, BooleanField, SubmitField from wtforms.validators import DataRequired, Email auth_bp = Blueprint('auth', __name__, url_prefix='/auth') class LoginForm: # Note: This is a placeholder class definition, actual form would be in a separate file or class email = StringField('Email', validators=[DataRequired(), Email()]) password = PasswordField('Password', validators=[DataRequired()]) remember = BooleanField('Remember me') submit = SubmitField('Sign In') @auth_bp.route('/login', methods=['GET', 'POST']) def login(): if current_user.is_authenticated: return redirect(url_for('index')) if request.method == 'POST': email = request.form.get('email') password = request.form.get('password') remember = request.form.get('remember', False) user = User.query.filter_by(email=email).first() if user and user.check_password(password): login_user(user, remember=remember) user.last_login = datetime.utcnow() db.session.commit() next_page = request.args.get('next') return redirect(next_page) if next_page else redirect(url_for('index')) else: flash('Invalid email or password', 'error') return render_template('auth/login.html') ``` -------------------------------- ### Testing Protected Routes With Login Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/api-reference/test-client.md Illustrates testing a protected route with a user logged in using FlaskLoginClient. This example shows how to create a client with a specific user and verify that the protected route returns the expected content and a 200 OK status code. ```python from flask import Flask from flask_login import login_required, current_user, UserMixin app = Flask(__name__) app.secret_key = 'test-secret' app.test_client_class = FlaskLoginClient class User(UserMixin): def __init__(self, id, name): self.id = id self.name = name @app.route('/protected') @login_required def protected(): return f'Hello, {current_user.name}' # Test with a logged-in user user = User(1, 'Alice') client = app.test_client(user=user) response = client.get('/protected') assert response.status_code == 200 assert response.data == b'Hello, Alice' ``` -------------------------------- ### Example Usage of @fresh_login_required Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/api-reference/login-manager.md This example demonstrates how to use the @fresh_login_required decorator. When a user accesses the '/change-password' route with a non-fresh session, the needs_refresh() method will be invoked. ```python from flask_login import fresh_login_required, current_user @app.route('/change-password') @fresh_login_required def change_password(): return "Change your password" # When accessed with a non-fresh session, needs_refresh() is called ``` -------------------------------- ### Testing Fresh vs. Non-Fresh Sessions Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/api-reference/test-client.md Demonstrates testing routes that require a fresh login using FlaskLoginClient. This example shows how to simulate both a fresh login (default) and a non-fresh login (e.g., from a remember-me cookie) to test the behavior of `@fresh_login_required`. ```python from flask import Flask from flask_login import fresh_login_required, UserMixin app = Flask(__name__) app.secret_key = 'test-secret' app.test_client_class = FlaskLoginClient class User(UserMixin): def __init__(self, id): self.id = id @app.route('/sensitive') @fresh_login_required def sensitive_operation(): return 'Sensitive data' # Test with fresh login user = User(1) client = app.test_client(user=user, fresh_login=True) response = client.get('/sensitive') assert response.status_code == 200 # Allowed # Test with non-fresh login (from remember-me) client = app.test_client(user=user, fresh_login=False) response = client.get('/sensitive') assert response.status_code == 401 # Requires fresh login ``` -------------------------------- ### Connect signals in an application factory pattern Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/api-reference/signals.md Illustrates how to connect to user_logged_in and user_logged_out signals within an application factory function. This pattern is common for organizing Flask application setup. ```python from flask import Flask from flask_login import LoginManager, user_logged_in, user_logged_out def create_app(): app = Flask(__name__) login_manager = LoginManager(app) @user_logged_in.connect_via(app) def on_login(sender, user, **extra): print(f"User {user.id} logged in") @user_logged_out.connect_via(app) def on_logout(sender, user, **extra): print(f"User {user.id} logged out") return app ``` -------------------------------- ### AnonymousUserMixin get_id() Method Example Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/api-reference/mixins.md Shows how to use the get_id() method of AnonymousUserMixin, which returns None. This example also demonstrates checking the authentication and anonymity status of an anonymous user object. ```python from flask_login import AnonymousUserMixin anon = AnonymousUserMixin() print(anon.get_id()) # None print(anon.is_anonymous) # True print(anon.is_authenticated) # False ``` -------------------------------- ### Using Flask-Login Test Client Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/README.md Configures the Flask test client to use `FlaskLoginClient` for simulating logged-in users during testing without manual session setup. ```python from flask_login import FlaskLoginClient app.test_client_class = FlaskLoginClient user = User(1) client = app.test_client(user=user) response = client.get('/protected') assert response.status_code == 200 ``` -------------------------------- ### Define Custom Anonymous User Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/configuration.md Example of creating a custom anonymous user class that extends AnonymousUserMixin and adds a nickname property. ```python class CustomAnonymous(AnonymousUserMixin): @property def nickname(self): return 'Guest' login_manager.anonymous_user = CustomAnonymous ``` -------------------------------- ### Logout User Example Source: https://github.com/maxcountryman/flask-login/blob/main/docs/index.md This Python snippet shows how to log out the current user using the `logout_user` function and redirect them to another page. It also requires the user to be logged in to access this route. ```default @app.route("/logout") @login_required def logout(): logout_user() return redirect(somewhere) ``` -------------------------------- ### Custom Anonymous User with Extra Attributes Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/api-reference/mixins.md Provides an example of creating a custom anonymous user class by inheriting from AnonymousUserMixin and adding custom properties like 'nickname' and 'is_premium'. This custom class is then assigned to the LoginManager. ```python from flask_login import AnonymousUserMixin, LoginManager from flask import Flask class CustomAnonymous(AnonymousUserMixin): """Custom anonymous user with extra attributes.""" @property def nickname(self): return "Guest" @property def is_premium(self): return False app = Flask(__name__) login_manager = LoginManager(app) login_manager.anonymous_user = CustomAnonymous @app.route('/') def index(): from flask_login import current_user if current_user.is_anonymous: return f"Welcome, {current_user.nickname}!" return f"Welcome back, {current_user.username}!" ``` -------------------------------- ### User Loading Order in Flask-Login Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/session-handling.md Illustrates the sequence Flask-Login follows to load the current user, starting from session protection checks, then attempting to load from session, remember-me cookies, request callbacks, and finally defaulting to an anonymous user. ```python def _load_user(self): """Internal method that loads user in order.""" # Step 1: Check session protection if self._session_protection_failed(): return # Session cleared, user set to anonymous # Step 2: Try loading from session user_id = session.get("_user_id") if user_id and self._user_callback: user = self._user_callback(user_id) if user: return # User loaded successfully # Step 3: Try loading from remember-me cookie if remember_cookie_present(): user_id = decode_cookie(request.cookies[cookie_name]) if user_id: session["_user_id"] = user_id session["_fresh"] = False user = self._user_callback(user_id) if user: return # User loaded from cookie # Step 4: Try loading from request if self._request_callback: user = self._request_callback(request) if user: return # User loaded from request # Step 5: No user found, use anonymous return AnonymousUserMixin() ``` -------------------------------- ### Testing with FlaskLoginClient Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/integration-guide.md Demonstrates how to set up a Flask application with FlaskLoginClient for testing authenticated routes. Includes fixtures for the app and an authenticated client. ```python import pytest from flask_login import FlaskLoginClient @pytest.fixture def app(): app = Flask(__name__) app.config['TESTING'] = True app.config['SECRET_KEY'] = 'test' app.test_client_class = FlaskLoginClient # ... initialize login_manager ... return app @pytest.fixture def authenticated_client(app): user = User(id=1, username='testuser') return app.test_client(user=user) def test_protected_route_requires_login(app): client = app.test_client() response = client.get('/protected') assert response.status_code == 401 def test_protected_route_with_login(authenticated_client): response = authenticated_client.get('/protected') assert response.status_code == 200 ``` -------------------------------- ### API Unauthorized Handler Example Source: https://github.com/maxcountryman/flask-login/blob/main/docs/index.md This snippet provides an example of a custom unauthorized handler that checks the request blueprint. If the request is from the 'api' blueprint, it returns an Unauthorized status; otherwise, it redirects to the login page. ```default from flask import redirect, url_for, request from http import HTTPStatus @login_manager.unauthorized_handler def unauthorized(): if request.blueprint == 'api': abort(HTTPStatus.UNAUTHORIZED) return redirect(url_for('site.login')) ``` -------------------------------- ### Use Flask-Babel for Localization Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/configuration.md Example of setting the localize_callback to Flask-Babel's gettext function for message translation. ```python from flask_babel import gettext login_manager.localize_callback = gettext ``` -------------------------------- ### Application Factory with Flask-Login Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/integration-guide.md Sets up a Flask application using the factory pattern and initializes Flask-Login. Ensure you have a SECRET_KEY configured. ```python from flask import Flask from flask_login import LoginManager login_manager = LoginManager() def create_app(config=None): """Application factory for creating Flask app instances.""" app = Flask(__name__) # Configuration app.config['SECRET_KEY'] = 'your-secret-key' app.config['SESSION_PROTECTION'] = 'strong' if config: app.config.update(config) # Initialize extensions login_manager.init_app(app) login_manager.login_view = 'auth.login' # Register blueprints from myapp.auth import auth_bp from myapp.api import api_bp app.register_blueprint(auth_bp) app.register_blueprint(api_bp) return app ``` -------------------------------- ### User Get ID Method Source: https://github.com/maxcountryman/flask-login/blob/main/docs/index.md Implement the get_id method to return the alternative ID for user identification. ```python def get_id(self): return str(self.alternative_id) ``` -------------------------------- ### Construct Login URL Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/api-reference/utils.md Shows how to create a login URL, optionally including a 'next' parameter for redirection after authentication. Handles both view names and absolute URLs. ```python from flask_login import login_url from flask import url_for # Simple case url = login_url('auth.login') # Returns: '/login' # With next parameter url = login_url('auth.login', next_url='/dashboard') # Returns: '/login?next=/dashboard' # With absolute URL url = login_url('https://auth.example.com/login', next_url='/dashboard') # Returns: 'https://auth.example.com/login?next=/dashboard' ``` -------------------------------- ### Testing Fresh Login Scenarios Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/integration-guide.md Illustrates testing scenarios that require a fresh login versus a non-fresh login for sensitive routes. ```python def test_fresh_login_required(app): user = User(id=1, username='testuser') # Fresh login - allowed fresh_client = app.test_client(user=user, fresh_login=True) response = fresh_client.get('/sensitive') assert response.status_code == 200 # Non-fresh login - requires reauthentication stale_client = app.test_client(user=user, fresh_login=False) response = stale_client.get('/sensitive') assert response.status_code == 401 ``` -------------------------------- ### User Activity Logging with Signals Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/integration-guide.md Sets up signal handlers for user login, logout, and access events to log user activity and update timestamps. Requires datetime and logging modules. ```python from flask_login import user_logged_in, user_logged_out, user_accessed from datetime import datetime import logging logger = logging.getLogger(__name__) @user_logged_in.connect_via(app) def on_user_login(sender, user, **extra): logger.info(f"User logged in: {user.username} from {request.remote_addr}") # Update last_login timestamp user.last_login = datetime.utcnow() db.session.commit() @user_logged_out.connect_via(app) def on_user_logout(sender, user, **extra): logger.info(f"User logged out: {user.username}") @user_accessed.connect_via(app) def on_user_accessed(sender, **extra): # Update last activity timestamp if current_user.is_authenticated: current_user.last_activity = datetime.utcnow() db.session.commit() ``` -------------------------------- ### Initialize Flask App and LoginManager Source: https://github.com/maxcountryman/flask-login/blob/main/README.md Sets up a basic Flask application and initializes the Flask-Login LoginManager. Ensure you change the 'super secret string' in a production environment. ```python import flask import flask_login app = flask.Flask(__name__) app.secret_key = "super secret string" # Change this! login_manager = flask_login.LoginManager() login_manager.init_app(app) ``` -------------------------------- ### Handle Unauthorized Access with @login_required Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/api-reference/login-manager.md The @login_required decorator automatically calls the unauthorized() handler when a user is not authenticated. This example shows a basic route protected by @login_required. ```python from flask import current_app, redirect from flask_login import login_required, current_user @app.route('/admin') @login_required def admin(): return "Admin page" # When accessed without logging in, unauthorized() is called automatically ``` -------------------------------- ### Use Custom User ID Attribute Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/configuration.md Example of setting the id_attribute to a different property name like 'id' if your user model uses it instead of 'get_id'. ```python # If your users have an 'id' property but not 'get_id': login_manager.id_attribute = 'id' ``` -------------------------------- ### Configure Flask-Login with Environment Variables (os.environ) Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/configuration.md Demonstrates how to set Flask-Login configuration values using Python's os.environ, providing default values if the environment variables are not set. ```python import os app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY', 'dev-key') app.config['SESSION_PROTECTION'] = os.environ.get('SESSION_PROTECTION', 'basic') app.config['REMEMBER_COOKIE_SECURE'] = os.environ.get('REMEMBER_COOKIE_SECURE', 'False').lower() == 'true' ``` -------------------------------- ### Use Custom User ID Method Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/configuration.md Example of setting the id_attribute to a method name like 'get_uuid' if your user model provides a custom method for ID retrieval. ```python # Or if you need custom ID format: class User: def get_uuid(self): return str(self.uuid) login_manager.id_attribute = 'get_uuid' ``` -------------------------------- ### Initialize Flask-Login Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/quick-reference.md Set up Flask-Login by initializing the LoginManager with your Flask application and configuring the login view. ```python from flask import Flask from flask_login import LoginManager, UserMixin app = Flask(__name__) app.secret_key = 'your-secret-key' # Required! login_manager = LoginManager() login_manager.init_app(app) login_manager.login_view = 'login' # Where to redirect when auth required ``` -------------------------------- ### UserMixin Implementation Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/api-reference/mixins.md Demonstrates how to implement the UserMixin in a SQLAlchemy model for Flask-Login integration. ```APIDOC ## UserMixin Implementation ### Description Inherit from `UserMixin` to integrate your user model with Flask-Login. ### Usage ```python from flask_login import UserMixin from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy() class User(UserMixin, db.Model): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(80), unique=True) email = db.Column(db.String(120), unique=True) # ... other fields and methods ``` ``` -------------------------------- ### Internal Function to Get Current User Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/api-reference/utils.md This is an internal function used to retrieve the currently logged-in user from the request context. It returns None if no user is logged in or if not within a request context. ```python _get_user() -> User | None ``` -------------------------------- ### Registration View Implementation Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/integration-guide.md Handles user registration requests, validating input and checking for existing usernames or emails before creating a new user. Redirects to login upon successful registration. ```python @auth_bp.route('/register', methods=['GET', 'POST']) def register(): if current_user.is_authenticated: return redirect(url_for('index')) if request.method == 'POST': username = request.form.get('username') email = request.form.get('email') password = request.form.get('password') if User.query.filter_by(username=username).first(): flash('Username already taken', 'error') return redirect(url_for('auth.register')) if User.query.filter_by(email=email).first(): flash('Email already registered', 'error') return redirect(url_for('auth.register')) user = User(username=username, email=email) user.set_password(password) db.session.add(user) db.session.commit() flash('Registration successful! Please log in.', 'success') return redirect(url_for('auth.login')) return render_template('auth/register.html') ``` -------------------------------- ### Create Compact Next Parameter URL Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/api-reference/utils.md Illustrates how to make the 'next' URL parameter more compact by removing scheme and host if they match the login URL. This ensures same-origin redirects. ```python from flask_login import make_next_param # Same host result = make_next_param( login_url='http://example.com/login', current_url='http://example.com/dashboard' ) # Returns: '/dashboard' # Different host result = make_next_param( login_url='http://example.com/login', current_url='http://other.com/page' ) # Returns: 'http://other.com/page' ``` -------------------------------- ### Fresh Login Required for Sensitive Actions Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/integration-guide.md Ensures the user has logged in recently (within the 'freshness' period) before allowing sensitive actions like changing a password. Handles both GET and POST requests. ```python from flask_login import fresh_login_required @app.route('/change-password', methods=['GET', 'POST']) @fresh_login_required def change_password(): if request.method == 'POST': new_password = request.form.get('new_password') current_user.set_password(new_password) db.session.commit() flash('Password changed successfully', 'success') return redirect(url_for('dashboard')) return render_template('change_password.html') ``` -------------------------------- ### Registering a User Loader Callback Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/quick-reference.md Implement the required `user_loader` callback to load a user from the database based on their ID. ```python @login_manager.user_loader def load_user(id): return User.query.get(id) ``` -------------------------------- ### Flask-Login Project File Structure Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/MANIFEST.md This snippet illustrates the directory structure of the Flask-Login project, showing the location of various documentation files and the API reference subdirectory. ```text /workspace/home/output/ ├── INDEX.md # Master index ├── README.md # Overview & quick start ├── MANIFEST.md # This file ├── quick-reference.md # Cheat sheet ├── configuration.md # Config options ├── integration-guide.md # Real-world patterns ├── session-handling.md # Session mechanics └── api-reference/ # API documentation ├── login-manager.md # LoginManager class ├── utils.md # Utility functions ├── mixins.md # User mixins ├── signals.md # Signal definitions └── test-client.md # Test utilities ``` -------------------------------- ### init_app() Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/api-reference/login-manager.md Configures a Flask application with the LoginManager. This method registers necessary hooks and optionally adds a template context processor. ```APIDOC ## init_app() ### Description Configures a Flask application with the LoginManager. This registers an `after_request` hook to update the remember-me cookie and optionally adds a template context processor. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **app** (`flask.Flask`) - Required. The Flask application to configure. - **add_context_processor** (`bool`) - Optional. Default: `True`. Whether to add a context processor that exposes `current_user` in templates. ### Returns `None` ### Side Effects: - Attaches `LoginManager` instance to `app.login_manager` - Registers `_update_remember_cookie()` as an `after_request` handler - If `add_context_processor=True`, registers `_user_context_processor()` as a template context processor ### Example ```python from flask import Flask from flask_login import LoginManager app = Flask(__name__) app.secret_key = "your-secret-key" login_manager = LoginManager() login_manager.init_app(app) # Now app.login_manager is available app.login_manager.login_view = "login" ``` ``` -------------------------------- ### Implementing Remember-Me Cookies Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/README.md Shows how to enable the 'remember-me' functionality during user login, allowing sessions to persist across browser closures. ```python from flask_login import login_user @app.route('/login', methods=['POST']) def login(): user = authenticate(request.form) remember = request.form.get('remember', False) login_user(user, remember=remember, duration=timedelta(days=7)) return redirect(url_for('dashboard')) ``` -------------------------------- ### Configure Blueprint Specific Login Views Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/configuration.md Map blueprint names to their respective login views. A `None` key can specify the default login view for all blueprints. ```python login_manager.blueprint_login_views = { 'admin': 'admin.login', 'api': 'api.token_login', None: 'auth.login' # Default for all blueprints } ``` ```python admin_bp = Blueprint('admin', __name__) api_bp = Blueprint('api', __name__) login_manager.blueprint_login_views = { 'admin': 'admin.login', 'api': None, # Uses default } login_manager.login_view = 'auth.login' # Default ``` -------------------------------- ### Connecting to Authentication Signals Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/README.md Illustrates how to connect to Flask-Login signals like `user_logged_in` and `user_logged_out` to perform actions upon authentication events. ```python from flask_login import user_logged_in, user_logged_out @user_logged_in.connect_via(app) def on_login(sender, user, **extra): print(f'User {user.id} logged in') @user_logged_out.connect_via(app) def on_logout(sender, user, **extra): print(f'User {user.id} logged out') ``` -------------------------------- ### Database Integration with Flask-Login Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/README.md Demonstrates how to integrate Flask-Login with Flask-SQLAlchemy by defining a User model that inherits from UserMixin and implementing the required user_loader callback. ```python from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy() class User(UserMixin, db.Model): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(80), unique=True) @login_manager.user_loader def load_user(user_id): return User.query.get(int(user_id)) ``` -------------------------------- ### Configure Session for Next URL Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/configuration.md Choose whether to store the 'next' URL in the session or as a query parameter. Storing in the session results in cleaner URLs. ```python app.config['USE_SESSION_FOR_NEXT'] = False ``` ```python # Keep "next" URL in session for cleaner URLs app.config['USE_SESSION_FOR_NEXT'] = True ``` -------------------------------- ### Full Flask-Login Demo Application Source: https://github.com/maxcountryman/flask-login/wiki/A-simple-working-demo This is a complete Flask application demonstrating user authentication with Flask-Login. It includes user model definition, login/logout routes, and session management. ```python from flask import Flask, flash, redirect, url_for, request, get_flashed_messages from flask.ext.login import LoginManager, UserMixin, current_user, login_user, logout_user app = Flask(__name__) # use for encrypt session app.config['SECRET_KEY'] = 'SET T0 4NY SECRET KEY L1KE RAND0M H4SH' login_manager = LoginManager() login_manager.init_app(app) class UserNotFoundError(Exception): pass # Simple user class base on UserMixin # http://flask-login.readthedocs.org/en/latest/_modules/flask/ext/login.html#UserMixin class User(UserMixin): '''Simple User class''' USERS = { # username: password 'john': 'love mary', 'mary': 'love peter' } def __init__(self, id): if not id in self.USERS: raise UserNotFoundError() self.id = id self.password = self.USERS[id] @classmethod def get(self_class, id): '''Return user instance of id, return None if not exist''' try: return self_class(id) except UserNotFoundError: return None # Flask-Login use this to reload the user object from the user ID stored in the session @login_manager.user_loader def load_user(id): return User.get(id) @app.route('/') def index(): return ( '''

Hello {1}

{0}

{2}

'''.format( # flash message ', '.join([ str(m) for m in get_flashed_messages() ]), current_user.get_id() or 'Guest', ('Logout' if current_user.is_authenticated else 'Login') ) ) @app.route('/login') def login(): return '''

Username:

Password:

''' @app.route('/login/check', methods=['post']) def login_check(): # validate username and password user = User.get(request.form['username']) if (user and user.password == request.form['password']): login_user(user) else: flash('Username or password incorrect') return redirect(url_for('index')) @app.route('/logout') def logout(): logout_user() return redirect(url_for('index')) if __name__ == '__main__': app.run(debug = True) ``` -------------------------------- ### Connect to user_logged_in and user_logged_out signals using decorators Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/api-reference/signals.md Demonstrates connecting to user_logged_in and user_logged_out signals using decorators. These handlers can be used for logging user activity or performing actions upon login/logout. ```python from flask_login import user_logged_in, user_logged_out @user_logged_in.connect_via(app) def on_login(sender, user, **extra): print(f"User {user.id} logged in") @user_logged_out.connect_via(app) def on_logout(sender, user, **extra): print(f"User {user.id} logged out") ``` -------------------------------- ### Create Login URL with Next Parameter Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/quick-reference.md Generates a login URL that includes a 'next' parameter, specifying the URL to redirect to after successful login. ```python from flask_login import login_url, make_next_param # Create a login URL with next parameter url = login_url('login', next_url='/dashboard') # Returns: '/login?next=/dashboard' # Reduce URL for next parameter short_url = make_next_param( login_url='http://example.com/login', current_url='http://example.com/page' ) # Returns: '/page' (same host) or full URL (different host) ``` -------------------------------- ### Flask-Login Source Code Structure Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/INDEX.md Overview of the Flask-Login project's directory structure and key files. Each file is listed with its primary content and line count. ```text src/flask_login/ ├── __init__.py # Public API exports ├── login_manager.py # LoginManager class (457 lines) ├── utils.py # Utility functions (394 lines) ├── mixins.py # User mixins (66 lines) ├── signals.py # Signal definitions (42 lines) ├── test_client.py # Test client (20 lines) ├── config.py # Configuration (53 lines) └── __about__.py # Version info ``` -------------------------------- ### Make Next Parameter Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/quick-reference.md Creates a 'next' parameter for redirecting after login. ```APIDOC ## make_next_param(login_url, current_url) ### Description Generates a URL-encoded `next` parameter suitable for login redirects. It intelligently handles same-host vs. different-host scenarios. ### Parameters - **login_url** (string) - The base URL of the login page. - **current_url** (string) - The current URL from which the redirect is initiated. ### Returns - (string) The URL-encoded `next` parameter or the full URL if hosts differ. ``` -------------------------------- ### Hash Passwords Securely Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/integration-guide.md Demonstrates hashing passwords using the scrypt algorithm for secure storage. ```python from werkzeug.security import generate_password_hash, check_password_hash user.password_hash = generate_password_hash(password, method='scrypt') ``` -------------------------------- ### Remember-Me Cookie Configuration Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/integration-guide.md Configures settings for remember-me cookies, including duration, security flags, and SameSite policy. Also shows how to initiate a persistent login. ```python from datetime import timedelta app.config['REMEMBER_COOKIE_DURATION'] = timedelta(days=30) app.config['REMEMBER_COOKIE_SECURE'] = True app.config['REMEMBER_COOKIE_HTTPONLY'] = True app.config['REMEMBER_COOKIE_SAMESITE'] = 'Lax' app.config['REMEMBER_COOKIE_REFRESH_EACH_REQUEST'] = True # In login view: login_user(user, remember=True, duration=timedelta(days=30)) ``` -------------------------------- ### FlaskLoginClient Constructor Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/api-reference/test-client.md Initializes FlaskLoginClient with an application instance and optional user for automatic login. Use this to create a test client that can log in users without manual session manipulation. ```python FlaskLoginClient( app, use_cookies=True, user=None, fresh_login=True, **kwargs ) ``` -------------------------------- ### Basic Session Protection Behavior and Effects Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/session-handling.md Demonstrates how basic session protection works with login-required and fresh-login-required decorators. Non-fresh sessions are allowed for general access but deny sensitive operations. ```python # Session hijacked, but can still access normal pages @app.route('/dashboard') @login_required def dashboard(): return "Allowed (basic protection)" # Session hijacked, requires fresh login @app.route('/settings') @fresh_login_required def settings(): return "Denied (needs fresh login)" ``` -------------------------------- ### Login View Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/quick-reference.md Handles user login via POST request with email and password. ```APIDOC ## POST /login ### Description Handles user login by verifying credentials and redirecting to the next page or login page. ### Method POST ### Endpoint /login ### Parameters #### Request Body - **email** (string) - Required - User's email address. - **password** (string) - Required - User's password. - **remember** (boolean) - Optional - Whether to remember the user. ### Response Redirects to the next page or the login page. ``` -------------------------------- ### Testing with Standard Flask Client for Request Loaders Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/api-reference/test-client.md Illustrates using the standard FlaskClient when testing with request loaders, as FlaskLoginClient bypasses them. ```python app.test_client_class = FlaskClient client = app.test_client() response = client.get('/api/data', headers={'Authorization': 'Bearer token123'}) ``` -------------------------------- ### Manually connect to user_logged_in signal Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/api-reference/signals.md Shows how to manually connect a function to the user_logged_in signal using the .connect() method. This provides an alternative to the decorator pattern for signal connections. ```python from flask_login import user_logged_in def on_login(sender, user, **extra): print(f"User {user.id} logged in") user_logged_in.connect(on_login, app) ``` -------------------------------- ### Load User with Redis Caching Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/session-handling.md Implements user loading with an external cache like Redis for improved performance. User data is serialized to JSON and stored in Redis with a timeout, reducing direct database interaction. ```python @login_manager.user_loader def load_user(user_id): user_json = cache.get(f'user:{user_id}') if user_json: return User.from_json(user_json) user = User.query.get(int(user_id)) cache.set(f'user:{user_id}', user.to_json(), timeout=3600) return user ``` -------------------------------- ### Pytest Fixtures for Flask-Login Testing Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/api-reference/test-client.md Sets up Flask application and test client fixtures for pytest, including a user loader and authenticated client. ```python import pytest from flask import Flask from flask_login import LoginManager, UserMixin, FlaskLoginClient class User(UserMixin): def __init__(self, id, name): self.id = id self.name = name @pytest.fixture def app(): app = Flask(__name__) app.config['TESTING'] = True app.secret_key = 'test-secret' app.test_client_class = FlaskLoginClient login_manager = LoginManager(app) @login_manager.user_loader def load_user(user_id): return User(int(user_id), f'User {user_id}') return app @pytest.fixture def client(app): return app.test_client() @pytest.fixture def auth_client(app): return app.test_client(user=User(1, 'Alice')) def test_protected_route_requires_login(client): """Test that protected route denies anonymous access.""" response = client.get('/protected') assert response.status_code == 401 def test_protected_route_allows_authenticated(auth_client): """Test that protected route allows authenticated access.""" response = auth_client.get('/protected') assert response.status_code == 200 ``` -------------------------------- ### Configure Fresh Login Requirements Source: https://github.com/maxcountryman/flask-login/blob/main/docs/index.md Customize the behavior for handling non-fresh logins, including the redirect view, message, and message category. ```python login_manager.refresh_view = "accounts.reauthenticate" login_manager.needs_refresh_message = ( u"To protect your account, please reauthenticate to access this page." ) login_manager.needs_refresh_message_category = "info" ``` -------------------------------- ### Custom User Implementation without Inheriting UserMixin Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/api-reference/mixins.md Demonstrates how to implement the required properties and methods for a user object if direct inheritance from UserMixin is not possible. This includes is_authenticated, is_active, is_anonymous, and get_id. ```python class User: def __init__(self, id): self.id = id @property def is_authenticated(self): return True @property def is_active(self): return True @property def is_anonymous(self): return False def get_id(self): return str(self.id) ``` -------------------------------- ### Login View Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/quick-reference.md Handles user login via POST request. It checks credentials, logs the user in, and redirects to the dashboard or login page. ```python from flask import request, redirect, url_for from flask_login import login_user, UserMixin # Assuming User model and db are defined elsewhere # class User(UserMixin): # def check_password(self, password): # ... # db = ... @app.route('/login', methods=['POST']) def login(): email = request.form['email'] password = request.form['password'] user = User.query.filter_by(email=email).first() if user and user.check_password(password): login_user(user, remember=request.form.get('remember', False)) return redirect(request.args.get('next', url_for('dashboard'))) return redirect(url_for('login')) ``` -------------------------------- ### Connect signals from a Blueprint Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/api-reference/signals.md Demonstrates connecting to the user_logged_in signal from within a Flask Blueprint. This allows signal handling logic to be encapsulated within specific application modules. ```python from flask import Blueprint from flask_login import user_logged_in auth_bp = Blueprint('auth', __name__) @user_logged_in.connect_via(app) def log_user_activity(sender, user, **extra): # This works across the entire application from flask import current_user print(f"Activity: User {current_user.id} logged in") ``` -------------------------------- ### login_url() Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/api-reference/utils.md Constructs a login URL with an optional "next" parameter for redirecting after login. ```APIDOC ## login_url() ### Description Constructs a login URL with an optional "next" parameter for redirecting after login. ### Method Not applicable (Python function) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **login_view** (str) - Required - The name of the login view or an absolute URL (e.g., `"auth.login"` or `"https://example.com/login"`). - **next_url** (str | None) - Optional - The URL to redirect to after login. If `None`, no next parameter is added. - **next_field** (str) - Optional - The query parameter name for the next URL (default: `"next"`). ### Response #### Success Response - **login_url** (str) - The login URL with query parameters. ### Request Example ```python from flask_login import login_url from flask import url_for # Simple case url = login_url('auth.login') # Returns: '/login' # With next parameter url = login_url('auth.login', next_url='/dashboard') # Returns: '/login?next=/dashboard' # With absolute URL url = login_url('https://auth.example.com/login', next_url='/dashboard') # Returns: 'https://auth.example.com/login?next=/dashboard' ``` ``` -------------------------------- ### Logout View Implementation Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/integration-guide.md Logs out the current user, flashes a message, and redirects to the index page. Requires the user to be logged in. ```python from flask_login import logout_user, login_required @auth_bp.route('/logout') @login_required def logout(): logout_user() flash('You have been logged out.', 'info') return redirect(url_for('index')) ``` -------------------------------- ### Logging In a User Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/api-reference/utils.md Use `login_user` to log in a user by creating a session. It supports persistent 'remember me' cookies and can force login even if the user is inactive. ```python from flask import request, redirect, url_for from flask_login import login_user @app.route('/login', methods=['POST']) def login(): email = request.form.get('email') password = request.form.get('password') user = User.query.filter_by(email=email).first() if user and user.check_password(password): remember = request.form.get('remember', False) login_user(user, remember=remember) return redirect(url_for('dashboard')) return redirect(url_for('login')) ``` -------------------------------- ### Implement __eq__ Comparison Method Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/api-reference/mixins.md Implement the __eq__ method to compare user objects based on their IDs. It returns True if both are UserMixin instances with the same ID. ```python from flask_login import UserMixin class User(UserMixin): def __init__(self, id): self.id = id user1 = User(1) user2 = User(1) user3 = User(2) print(user1 == user2) # True print(user1 == user3) # False print(user1 == "not a user") # False ``` -------------------------------- ### Configure Blueprint Specific Login Views Source: https://github.com/maxcountryman/flask-login/blob/main/_autodocs/api-reference/login-manager.md Use blueprint_login_views to map blueprint names to their respective login views, enabling different login pages for different blueprints. ```python login_manager.blueprint_login_views = { 'admin': 'admin.login', 'api': 'api.token_login', } ```