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 smart_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 smart_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 smart_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 smart_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 smart_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 smart_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 smart_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 smart_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.1.0.tar.gz (7.5 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.1.0-py3-none-any.whl (10.2 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: mehdashti_auth_kit-0.1.0.tar.gz
  • Upload date:
  • Size: 7.5 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.1.0.tar.gz
Algorithm Hash digest
SHA256 8b663f6126d40139fe4992ef51153dc32e602fc0e671675d26adfe2870b782a9
MD5 142f0f22bc590de597ce98c4c927acdc
BLAKE2b-256 a9a9b8645ef9eb204145ec25f84388ab4936546eedad825180c34ba77b7785ce

See more details on using hashes here.

File details

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

File metadata

  • Download URL: mehdashti_auth_kit-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 10.2 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.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 019b7c3ae589569977dbfc19c5b0ace5a3f1de191421533023cb71f80ce8cee9
MD5 55701f47559d709dcd89a8e0a1e54721
BLAKE2b-256 31668cb2a336aa5f096bb02c071e7aa4958be61d537f8d38e071f24bb90e6518

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