Auth Plugin API Reference¶
Authentication and authorization plugin for Structum Lab.
Structum Auth (structum-auth)¶
Structum Auth è il plugin ufficiale per la gestione dell’autenticazione JWT, l’hashing sicuro delle password (Argon2) e il controllo degli accessi (RBAC).
🚀 Installazione¶
pip install structum-auth
📚 Documentazione Completa¶
Documentazione, API Reference e Guide: 👉 https://structum-lab.pages.dev/plugins/auth
✨ Funzionalità Principali¶
JWT Management: Creazione e validazione token sicura.
Argon2 Hashing: Standard di sicurezza per lo storage delle password.
RBAC: Controllo accessi basato sui ruoli.
Integrazione FastAPI: Dipendenze pronte all’uso per proteggere le route.
Auth Plugin Package¶
Authentication plugin for Structum Lab.
- class structum_lab.plugins.auth.AuthInterface(*args, **kwargs)[source]¶
Bases:
ProtocolProtocol for authentication providers in Structum Lab.
This is the main entry point for all authentication operations. Implementations provide JWT-based authentication, password hashing, and token management.
The auth system is storage-agnostic - it doesn’t manage users directly. Instead, it uses
UserRepositoryInterfaceto fetch user data, keeping authentication logic decoupled from storage.- Implementations:
JWTAuthProvider(recommended)
Example
See usage in specific implementations like JWTAuthProvider.
- authenticate(username: str, password: str, user_repo: UserRepositoryInterface) TokenPair | None[source]¶
Authenticate a user.
- refresh(refresh_token: str, user_repo: UserRepositoryInterface) TokenPair | None[source]¶
Refresh access token.
- class structum_lab.plugins.auth.PasswordHasherInterface(*args, **kwargs)[source]¶
Bases:
ProtocolProtocol for secure password hashing in Structum Lab.
Implementations must use cryptographically secure hashing algorithms (e.g., Argon2, b
- crypt, scrypt). Never use fast hashes like MD5 or SHA-1
for passwords.
- Implementations:
Argon2Hasher(recommended)BcryptHasher
- Example:
Using password hasher:
from structum_lab.plugins.auth.password import Argon2Hasher hasher = Argon2Hasher() # Hash password during registration hashed = hasher.hash("user_password_123") # Store hashed in database: user.hashed_password = hashed # Verify during login if hasher.verify("user_password_123", hashed): # Password matches return create_token(user) else: # Invalid password raise AuthenticationError("Invalid credentials")- Warning:
Never log, display, or store plain-text passwords. Always hash passwords immediately upon receipt.
- See Also:
AuthInterface: Auth provider using password hasherUserInterface: User entity with hashed_password property
- hash(password: str) str[source]¶
Hash a plain-text password securely.
- Parameters:¶
- Returns:¶
- Hashed password string including algorithm identifier and salt.
Format is implementation-specific (e.g., Argon2:
$argon2id$v=19$...).
- Return type:¶
Example
Creating user with hashed password:
# During user registration plain_password = request.form["password"] hashed = auth.hash_password(plain_password) user = User( id=generate_id(), username=request.form["username"], hashed_password=hashed, # Store this roles=["user"] ) user_repo.save(user)Warning
Hashing is intentionally slow (100-500ms) to resist brute-force attacks. Do not hash passwords in tight loops or performance-critical paths.
Note
Each call generates a unique hash (due to random salt) even for the same password. This is expected and secure behavior.
- verify(password: str, hashed: str) bool[source]¶
Verify a plain-text password against a hash.
Example
Password verification during login:
# Get user from database user = user_repo.find_by_username(username) if not user: return None # User not found # Verify password if auth.verify_password(password, user.hashed_password): # Authentication successful return auth.create_tokens(user) else: # Invalid password log.warning("Failed login attempt", username=username) return NoneWarning
Always use constant-time comparison internally to prevent timing attacks. Most modern hashing libraries handle this automatically.
Note
Returns False for invalid/malformed hashes rather than raising exceptions. This prevents information leakage about hash format.
-
class structum_lab.plugins.auth.TokenPair(access_token: str, refresh_token: str, token_type: str =
'bearer', expires_at: datetime | None =None)[source]¶ Bases:
objectData class containing JWT access and refresh token pair.
Example
Creating and using token pair:
tokens = TokenPair( access_token="eyJ0eXAiOiJKV1QiLCJhbGc...", refresh_token="eyJ0eXAiOiJKV1QiLCJhbGc...", token_type="bearer", expires_at=datetime.now() + timedelta(hours=1) ) # Use in HTTP Authorization header headers = {"Authorization": f"{tokens.token_type} {tokens.access_token}"}Note
This class is frozen (immutable) to prevent accidental token modification. Tokens should be treated as opaque strings and never parsed by clients.
See also
AuthInterface.authenticate(): Method that returns token pairsAuthInterface.refresh(): Refresh access tokens-
__init__(access_token: str, refresh_token: str, token_type: str =
'bearer', expires_at: datetime | None =None)¶
-
__init__(access_token: str, refresh_token: str, token_type: str =
- class structum_lab.plugins.auth.UserInterface(*args, **kwargs)[source]¶
Bases:
ProtocolProtocol for authenticated user entities in Structum Lab.
Applications must implement this protocol for their User model to integrate with the authentication system. The auth system never creates or modifies users - it only queries them via
UserRepositoryInterface.Example
Implementing UserInterface:
from dataclasses import dataclass @dataclass class User: id: str username: str hashed_password: str roles: list[str] permissions: set[str] def has_permission(self, permission: str) -> bool: # Check role-based permissions for role in self.roles: if permission in ROLE_PERMISSIONS.get(role, set()): return True # Check user-specific permissions return permission in self.permissionsUsing with auth:
user = user_repo.find_by_username("john") if user and user.has_permission("users:write"): # Allow operation passNote
This is a Protocol, not a base class. Your User model doesn’t need to inherit from this - just implement the required properties and methods.
See also
UserRepositoryInterface: Repository for user data accessAuthInterface: Authentication provider using users- has_permission(permission: str) bool[source]¶
Check if user has a specific permission.
Example
Permission-based authorization:
@app.delete("/users/{user_id}") async def delete_user(user_id: str, current_user: User = Depends(get_current_user)): if not current_user.has_permission("users:delete"): raise HTTPException(403, "Permission denied") # Delete userRole-based permission mapping:
ROLE_PERMISSIONS = { "admin": {"users:read", "users:write", "users:delete"}, "user": {"users:read"}, } def has_permission(self, permission: str) -> bool: return any( permission in ROLE_PERMISSIONS.get(role, set()) for role in self.roles )Note
Permission format is application-defined. Use a consistent naming scheme (e.g., resource:action).
- property hashed_password : str¶
User’s hashed password.
Warning
Never store or transmit plain-text passwords. This property should only return hashed values.
Example
Password verification:
if auth.verify_password(input_password, user.hashed_password): # Password matches passSee also
PasswordHasherInterface.hash(): Hash passwordsPasswordHasherInterface.verify(): Verify passwords
- property id : str¶
Unique identifier for the user.
Example
User ID in token payload:
token_payload = {"user_id": user.id, "exp": ...}
- property roles : list[str]¶
List of roles assigned to the user.
Example
Role-based access control:
if "admin" in user.roles: # Allow admin operation passNote
Roles should be lowercase strings. Use
has_permission()for fine-grained permission checks.
-
class structum_lab.plugins.auth.JWTAuthProvider(secret_key: str, refresh_secret_key: str | None =
None, algorithm: str ='HS256', access_token_expire_minutes: int =15, refresh_token_expire_days: int =7)[source]¶ Bases:
BaseAuthProvider,AuthInterfaceJWT-based authentication provider.
Manages: - User authentication (verifying password) - Token generation (Access + Refresh) - Token verification - Password hashing (via Argon2)
Example
>>> auth = JWTAuthProvider.from_config() >>> tokens = auth.authenticate("user", "pass", user_repo)-
__init__(secret_key: str, refresh_secret_key: str | None =
None, algorithm: str ='HS256', access_token_expire_minutes: int =15, refresh_token_expire_days: int =7)[source]¶ Initialize JWT provider.
- Parameters:¶
- secret_key: str¶
Secret for signing access tokens
- refresh_secret_key: str | None =
None¶ Secret for refresh tokens (defaults to secret_key)
- algorithm: str =
'HS256'¶ Signing algorithm (HS256, RS256, etc.)
- access_token_expire_minutes: int =
15¶ Access token TTL
- refresh_token_expire_days: int =
7¶ Refresh token TTL
- authenticate(username: str, password: str, user_repo: UserRepositoryInterface) TokenPair | None[source]¶
Authenticate user and return tokens.
-
classmethod from_config(config_key: str | None =
None, *, config: ConfigInterface | None =None) JWTAuthProvider[source]¶ Factory method to create provider from config.
- refresh(refresh_token: str, user_repo: UserRepositoryInterface) TokenPair | None[source]¶
Refresh tokens using refresh token.
-
__init__(secret_key: str, refresh_secret_key: str | None =
-
class structum_lab.plugins.auth.Argon2PasswordHasher(time_cost: int =
2, memory_cost: int =65536, parallelism: int =1, hash_len: int =32, salt_len: int =16)[source]¶ Bases:
PasswordHasherInterfaceArgon2 implementation of PasswordHasherInterface.
- class structum_lab.plugins.auth.RoleChecker[source]¶
Bases:
objectHelper for checking roles and permissions.
- static check_permission(user: UserInterface, permission: str) bool[source]¶
Check permission (delegates to user object).
Base Authentication¶
Base class for auth implementations with Factory Pattern support.
- class structum_lab.plugins.auth.base.BaseAuthProvider[source]¶
Bases:
objectBase class providing Factory Pattern configuration.
JWT Authentication¶
JWT Authentication Provider.
Implements AuthInterface using JSON Web Tokens (access + refresh).
-
class structum_lab.plugins.auth.jwt.JWTAuthProvider(secret_key: str, refresh_secret_key: str | None =
None, algorithm: str ='HS256', access_token_expire_minutes: int =15, refresh_token_expire_days: int =7)[source]¶ Bases:
BaseAuthProvider,AuthInterfaceJWT-based authentication provider.
Manages: - User authentication (verifying password) - Token generation (Access + Refresh) - Token verification - Password hashing (via Argon2)
Example
>>> auth = JWTAuthProvider.from_config() >>> tokens = auth.authenticate("user", "pass", user_repo)-
__init__(secret_key: str, refresh_secret_key: str | None =
None, algorithm: str ='HS256', access_token_expire_minutes: int =15, refresh_token_expire_days: int =7)[source]¶ Initialize JWT provider.
- Parameters:¶
- secret_key: str¶
Secret for signing access tokens
- refresh_secret_key: str | None =
None¶ Secret for refresh tokens (defaults to secret_key)
- algorithm: str =
'HS256'¶ Signing algorithm (HS256, RS256, etc.)
- access_token_expire_minutes: int =
15¶ Access token TTL
- refresh_token_expire_days: int =
7¶ Refresh token TTL
-
classmethod from_config(config_key: str | None =
None, *, config: ConfigInterface | None =None) JWTAuthProvider[source]¶ Factory method to create provider from config.
- authenticate(username: str, password: str, user_repo: UserRepositoryInterface) TokenPair | None[source]¶
Authenticate user and return tokens.
- refresh(refresh_token: str, user_repo: UserRepositoryInterface) TokenPair | None[source]¶
Refresh tokens using refresh token.
-
__init__(secret_key: str, refresh_secret_key: str | None =
OAuth Support¶
OAuth2 interface stub for future implementation.
- class structum_lab.plugins.auth.oauth.OAuthProvider(*args, **kwargs)[source]¶
Bases:
ProtocolProtocol for OAuth2 providers (Google, GitHub, etc.).
- get_login_url(redirect_uri: str) str[source]¶
Password Hashing¶
Password hashing using Argon2 (argon2-cffi).
-
class structum_lab.plugins.auth.password.Argon2PasswordHasher(time_cost: int =
2, memory_cost: int =65536, parallelism: int =1, hash_len: int =32, salt_len: int =16)[source]¶ Bases:
PasswordHasherInterfaceArgon2 implementation of PasswordHasherInterface.
Role-Based Access Control (RBAC)¶
RBAC utilities for permission checking.
- class structum_lab.plugins.auth.rbac.RoleChecker[source]¶
Bases:
objectHelper for checking roles and permissions.
- static has_any_role(user: UserInterface, roles: list[str]) bool[source]¶
Check if user has any of the specified roles.
- static check_permission(user: UserInterface, permission: str) bool[source]¶
Check permission (delegates to user object).