Skip to main content

Authentication utilities for Smart Platform - JWT, password hashing, and auth services

Project description

smart-auth-kit

Authentication utilities for Smart Platform - JWT tokens, password hashing, and extensible auth services

Installation

pip install smart-auth-kit

Features

  • JWT Tokens: Access and refresh token generation with role-based claims
  • Password Hashing: Argon2id for secure password storage
  • Auth Service: Extensible authentication service with hooks
  • FastAPI Integration: Dependencies for current user and role-based access
  • Multi-tenancy: Built-in tenant ID support
  • Type Safe: Full type hints with Pydantic

Quick Start

1. Implement User Provider

from uuid import UUID
from typing import Optional
from mehdashti_auth.services.auth_service import UserProvider

class MyUserProvider:
    """Custom user provider backed by your database."""

    def __init__(self, db):
        self.db = db

    async def get_user_by_email(self, email: str) -> Optional[dict]:
        # Query your database
        user = await self.db.users.find_one({"email": email})
        if not user:
            return None
        return {
            "uid": user["id"],
            "email": user["email"],
            "hashed_password": user["password"],
            "is_active": user["is_active"],
            "role": user["role"],
        }

    async def get_user_by_uid(self, uid: UUID) -> Optional[dict]:
        user = await self.db.users.find_one({"id": uid})
        if not user:
            return None
        return {
            "uid": user["id"],
            "email": user["email"],
            "is_active": user["is_active"],
            "role": user["role"],
        }

    async def create_user(self, user_data: dict) -> dict:
        result = await self.db.users.insert_one(user_data)
        return {**user_data, "uid": result.inserted_id}

2. Setup Auth Service

from mehdashti_auth import AuthService, AuthServiceConfig, hash_password

# Configuration
config = AuthServiceConfig(
    secret_key="your-secret-key-here",
    access_token_expire_minutes=30,
    refresh_token_expire_days=7,
)

# Initialize
user_provider = MyUserProvider(db)
auth_service = AuthService(config, user_provider)

3. FastAPI Integration

from fastapi import FastAPI, Depends
from typing import Annotated
from mehdashti_auth.dependencies.current_user import (
    create_get_current_user_dependency,
    create_require_roles_dependency,
)

app = FastAPI()

# Create dependencies
get_current_user = create_get_current_user_dependency(auth_service)
require_admin = create_require_roles_dependency(auth_service, ["admin"])

# Login endpoint
@app.post("/auth/login")
async def login(email: str, password: str):
    try:
        result = await auth_service.login(email, password)
        return result
    except ValueError as e:
        raise HTTPException(status_code=401, detail=str(e))

# Refresh token
@app.post("/auth/refresh")
async def refresh(refresh_token: str):
    try:
        result = await auth_service.refresh_access_token(refresh_token)
        return result
    except ValueError as e:
        raise HTTPException(status_code=401, detail=str(e))

# Protected endpoint
@app.get("/users/me")
async def read_users_me(current_user: Annotated[dict, Depends(get_current_user)]):
    return current_user

# Admin-only endpoint
@app.delete("/users/{user_id}")
async def delete_user(
    user_id: str,
    current_user: Annotated[dict, Depends(require_admin)]
):
    # Only admins can access this
    return {"message": f"User {user_id} deleted"}

Password Hashing

from mehdashti_auth import hash_password, verify_password

# Hash password
hashed = hash_password("my_secure_password")

# Verify password
is_valid = verify_password("my_secure_password", hashed)  # True
is_valid = verify_password("wrong_password", hashed)      # False

JWT Tokens

Creating Tokens

from mehdashti_auth import create_access_token, create_refresh_token

# Access token
access_token = create_access_token(
    subject="user-uuid",
    secret_key="your-secret",
    roles=["admin", "user"],
    tenant_id="tenant-123",
    email="user@example.com",
)

# Refresh token
refresh_token = create_refresh_token(
    subject="user-uuid",
    secret_key="your-secret",
)

Decoding Tokens

from mehdashti_auth import decode_token, verify_token_type

# Decode token
payload = decode_token(token, "your-secret")

# Verify type
if payload and verify_token_type(payload, "access"):
    user_id = payload["sub"]
    roles = payload["roles"]

Extension Points

Custom Role Extraction

class CustomAuthService(AuthService):
    def get_user_roles(self, user: dict) -> list[str]:
        # Custom logic: combine role + permissions
        roles = [user["role"]]
        if user.get("is_superuser"):
            roles.append("superuser")
        return roles

Custom Login Validation

class MFAAuthService(AuthService):
    async def validate_login(self, user: dict) -> None:
        # Add MFA check
        if user.get("mfa_enabled"):
            # Verify MFA code (implementation depends on your MFA system)
            if not await self.verify_mfa(user):
                raise ValueError("Invalid MFA code")

Multi-Tenancy

# Create token with tenant
token = create_access_token(
    subject="user-uuid",
    secret_key="secret",
    tenant_id="tenant-123",
)

# Extract tenant from token
payload = decode_token(token, "secret")
tenant_id = payload.get("tenant_id")

Error Handling

from mehdashti_auth import AuthService

try:
    result = await auth_service.login(email, password)
except ValueError as e:
    # Authentication failed
    # Possible reasons:
    # - Invalid email or password
    # - User account is inactive
    # - Custom validation failed
    print(f"Login failed: {e}")

Security Best Practices

  1. Secret Key: Use a strong, random secret key (at least 32 characters)

    import secrets
    secret_key = secrets.token_urlsafe(32)
    
  2. Password Requirements: Enforce strong passwords in your application

  3. Token Expiration: Use short expiration for access tokens (30 min)

  4. HTTPS Only: Always use HTTPS in production

  5. Token Storage: Store tokens securely (HttpOnly cookies recommended)

Configuration

Auth Service Config

from mehdashti_auth import AuthServiceConfig

config = AuthServiceConfig(
    secret_key="your-secret-key",
    access_token_expire_minutes=30,  # Access token TTL
    refresh_token_expire_days=7,     # Refresh token TTL
)

Environment Variables

# .env file
SECRET_KEY=your-secret-key-here
ACCESS_TOKEN_EXPIRE_MINUTES=30
REFRESH_TOKEN_EXPIRE_DAYS=7

Complete Example

See the examples/ directory for a complete FastAPI application with:

  • User registration
  • Login/logout
  • Token refresh
  • Protected endpoints
  • Role-based access control

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mehdashti_auth_kit-0.2.0.tar.gz (7.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mehdashti_auth_kit-0.2.0-py3-none-any.whl (10.3 kB view details)

Uploaded Python 3

File details

Details for the file mehdashti_auth_kit-0.2.0.tar.gz.

File metadata

  • Download URL: mehdashti_auth_kit-0.2.0.tar.gz
  • Upload date:
  • Size: 7.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.11 {"installer":{"name":"uv","version":"0.9.11"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for mehdashti_auth_kit-0.2.0.tar.gz
Algorithm Hash digest
SHA256 7b229b98a64ad0a06385bc8fb622175a8d81bc4779a3bee73b8ff16469b122b9
MD5 3ba246fcdae47128246650afd3fc7459
BLAKE2b-256 3cfaddb5e5826579cd889b1b36feb03effc7c9de0afe4811e27f62521465fe91

See more details on using hashes here.

File details

Details for the file mehdashti_auth_kit-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: mehdashti_auth_kit-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 10.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.11 {"installer":{"name":"uv","version":"0.9.11"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for mehdashti_auth_kit-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 87716edcd65d2c7206465a2bb9d086447d50acf24887ae4a4cf340c6529fa3e0
MD5 207f0bec168111f4b64a4205326f0b60
BLAKE2b-256 c9d336fc570e8a324de15aeeba3fd59f52a9b47b0fecdb67aaffed0dc400324d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page