Registry / web-framework / flask-principal

flask-principal

JSON →
library0.4.0pypypi✓ verified 86d ago

Flask-Principal is an extension for Flask that provides identity management for users, enabling flexible authorization based on 'Needs' and 'Permissions'. The latest stable version is 0.4.0, released in 2012, and the library is largely unmaintained. It uses a signal-based approach to load user identities and their associated permissions.

pip install Flask-Principal
INSTALL
IMPORT
SIG · FLASK-PRINCIPAL
F
flask-principal
web-frameworkpythonv0.4.0
Install
3.1s avg
Import
469ms
Disk
22MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.93.13
musl
3.93.13
Install & Compatibility
Where this runs
tested against v0.4.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.103.920 runs
installs and imports cleanly · install 0.0s · import 0.486s · 23.8MB
glibc
py 3.103.920 runs
installs and imports cleanly · install 3.1s · import 0.452s · 24MB
22MB installed
● package 22MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

Principal
from flask_principal import Principal
from flaskext.principal import Principal
The 'flaskext' namespace was used in older Flask extensions but is deprecated.
Identity
from flask_principal import Identity
AnonymousIdentity
from flask_principal import AnonymousIdentity
Permission
from flask_principal import Permission
Need
from flask_principal import Need
RoleNeed
from flask_principal import RoleNeed
UserNeed
from flask_principal import UserNeed
current_identity
from flask_principal import current_identity
identity_changed
from flask_principal import identity_changed
identity_loaded
from flask_principal import identity_loaded

This quickstart demonstrates how to set up Flask-Principal with an example Flask application. It includes routes for logging in/out, a profile page, and an admin dashboard protected by a 'RoleNeed'. The `identity_changed` signal is used to update the current identity, and `identity_loaded` is used to assign `Needs` (like 'admin' role) to the identity. Ensure `FLASK_SECRET_KEY` is set for production.

import os from flask import Flask, session, g, redirect, url_for from flask_principal import Principal, Identity, AnonymousIdentity, \ identity_changed, identity_loaded, \ current_identity, \ Need, UserNeed, RoleNeed, Permission # Initialize Flask app app = Flask(__name__) app.secret_key = os.environ.get('FLASK_SECRET_KEY', 'default_secret_key') # Initialize Flask-Principal principals = Principal(app) # Define a permission for 'admin' role admin_permission = Permission(RoleNeed('admin')) @app.before_request def load_identity_from_session(): # Load identity from session or create an anonymous one if 'identity_id' in session: g.identity = Identity(session['identity_id']) # Signal that the identity has loaded identity_changed.send(app, identity=g.identity) else: g.identity = AnonymousIdentity() @identity_loaded.connect_via(app) def on_identity_loaded(sender, identity): # This signal is fired when an identity is loaded (or changed) # Use this to add Needs to the identity based on your application logic if identity.id: # Example: user_id 1 is an admin, others are regular users if identity.id == 1: identity.provides.add(RoleNeed('admin')) identity.provides.add(UserNeed(identity.id)) # All logged-in users get their UserNeed # For anonymous users, no specific Needs are added here by default @app.route('/login/<int:user_id>') def login(user_id): # Simulate a login: set identity in session and emit signal session['identity_id'] = user_id identity_changed.send(app, identity=Identity(user_id)) return f'Logged in as User {user_id}. <a href="{url_for("profile")}">Go to profile</a> <a href="{url_for("admin_dashboard")}">Go to admin dashboard</a>' @app.route('/logout') def logout(): # Simulate a logout: clear session and emit anonymous identity signal if 'identity_id' in session: del session['identity_id'] identity_changed.send(app, identity=AnonymousIdentity()) return 'Logged out. <a href="{url_for("profile")}">Go to profile</a>' @app.route('/') @app.route('/profile') def profile(): if current_identity.is_authenticated(): return f'Hello, User {current_identity.id}! You are authenticated.' \ f' Role: {"Admin" if admin_permission.can() else "User"}.' return 'Hello, Anonymous User! You are not logged in.' @app.route('/admin') @admin_permission.require() # This decorator enforces the 'admin' permission def admin_dashboard(): return f'Welcome to the Admin Dashboard, User {current_identity.id}!' if __name__ == '__main__': # For local testing, ensure a secret key is set if 'FLASK_SECRET_KEY' not in os.environ: print("WARNING: FLASK_SECRET_KEY environment variable not set. Using a default for demonstration.") app.run(debug=True)
Debug
Known issues
deprecatedFlask-Principal is largely unmaintained, with its last release (0.4.0) dating back to 2012. It may not be compatible with newer Flask versions or Python features, and there are no active security updates. Modern Flask applications are advised to use more actively maintained authentication and authorization libraries like Flask-Login (for authentication) combined with custom decorators for role-based access control, or comprehensive solutions for JWT/session management.
fix
Consider migrating to Flask-Login for authentication and implementing authorization logic with custom decorators or a more modern library.
affects: <=0.4.0
gotchaFlask-Principal was originally developed for Python 2. While basic functionality might work on Python 3, subtle compatibility issues or unhandled edge cases may arise due to differences in string handling, standard library changes, or other Python 2/3 specific behaviors. The library's `requires_python` metadata is `None`, indicating no explicit Python 3 support was declared.
fix
Thoroughly test on your target Python 3 version if you must use this library. Prefer alternatives for new projects.
affects: All versions on Python 3.x
gotchaFlask-Principal handles *authorization* (what a user can do), not *authentication* (who the user is). You must integrate it with a separate authentication mechanism (e.g., Flask-Login, a custom session manager, or OAuth) to establish the user's identity before Principal can assign and check permissions.
fix
Implement a robust authentication system to manage user sessions and login states, then use Flask-Principal's `Identity` object to represent the authenticated user.
affects: All versions
gotchaThe signal-based nature of `identity_changed` and `identity_loaded` means they must be sent within an active Flask application context (`app.app_context()` or during a request). Calling `identity_changed.send()` outside of an app context will raise a `RuntimeError`.
fix
Ensure that `identity_changed.send()` is always called within a request context or an explicitly pushed application context (e.g., `with app.app_context():`).
affects: All versions
Errors
Common errors & fixes
RuntimeError: Working outside of application context.
The `identity_changed.send()` method or other Principal operations were called outside of an active Flask application context (e.g., in a background thread or a script without a context pushed).
fix
Ensure all Flask-Principal operations, especially signal emissions, are performed within an active request context or by explicitly pushing an application context: `with app.app_context(): identity_changed.send(...)`.
AssertionError: This Principal extension is not registered to the current application.
Flask-Principal was either not initialized with your Flask application (`principals = Principal(app)` was omitted or called incorrectly), or you are attempting to use Principal features (like `current_identity`) outside of a request where the application context might not be properly set up or associated with the Principal extension.
fix
Verify that `principals = Principal(app)` is correctly called during your application setup. If using an app factory, ensure `Principal()` is initialized with `app` *within* the factory or with `Principal().init_app(app)`.
Access denied / Permission not granted / @requires_role decorator not working.
The `current_identity` does not possess the required `Need` for the permission being checked. This often happens if the `identity_loaded` signal handler doesn't correctly add `Needs` to the identity's `provides` set, or if the `Need` definition in the permission does not match what's provided.
fix
Inspect your `identity_loaded` signal handler to ensure it correctly populates `identity.provides` with the appropriate `Need` objects for the current user. Double-check that the `Need` defined in your `Permission` (e.g., `Permission(RoleNeed('admin'))`) exactly matches the `Need` added to the identity.
Upgrade
Version history
0.4.0latest on PyPI · released Jun 14, 2013
Audit
Dependencies
FlaskrequiredCore web framework dependency.
Agent activity
19 hits · last 30 days
node
18
OpenAI (training)
1
Resources
flask-principal — pip install flask-principal · libregistry