Skip to main content

User model and schema library for authentication services

Project description

keylin

Python Versions License: MIT Tests Coverage Code Quality PyPI version

Features

  • User model and schema library for authentication services
  • Designed for integration with FastAPI and fastapi-users
  • Reusable across multiple services

Installation

pip install keylin

Usage

from keylin.models import User
from fastapi import FastAPI, Depends
from sqlalchemy.ext.asyncio import AsyncSession
from keylin.db import get_async_session

app = FastAPI()

@app.get("/users/{user_id}")
async def get_user(user_id: str, session: AsyncSession = Depends(get_async_session)):
    result = await session.execute(
        User.__table__.select().where(User.id == user_id)
    )
    user = result.fetchone()
    if user:
        return user
    return {"error": "User not found"}

Architecture & Integration Guide

Typical Architecture

A recommended architecture for a login/authentication service using keylin:

graph TD
    A[Client App / Frontend]
    B[API Gateway / HTTPS Proxy]
    C[FastAPI Login Service - uses keylin]
    D[Database - PostgreSQL, etc.]
    A --> B
    B --> C
    C --> D
  • keylin provides the user model, schemas, and authentication logic.
  • The login service is a FastAPI app that imports keylin and wires up routers.
  • Other services can import keylin to share the user model and schemas for consistent user data handling.

Example FastAPI Login Service

from fastapi import FastAPI
from keylin.auth import auth_backend, fastapi_users, get_user_manager
from keylin.schemas import UserRead, UserCreate

app = FastAPI()

# Auth routes
app.include_router(fastapi_users.get_auth_router(auth_backend), prefix="/auth/jwt", tags=["auth"])
app.include_router(fastapi_users.get_register_router(UserRead, UserCreate), prefix="/auth", tags=["auth"])
app.include_router(fastapi_users.get_users_router(UserRead, UserRead), prefix="/users", tags=["users"])

Environment Variables (Required for Production)

  • JWT_SECRET: Secret key for JWT signing (required; application will raise an error if not set)
  • RESET_PASSWORD_SECRET: Secret for password reset tokens (optional, defaults to JWT secret)
  • VERIFICATION_SECRET: Secret for verification tokens (optional, defaults to JWT secret)
  • DATABASE_URL: SQLAlchemy DB URL (e.g., postgresql+asyncpg://user:pass@host/dbname)

Note: If JWT_SECRET is not set, the application will raise a RuntimeError at startup.

Security & Deployment Best Practices

  • CORS: Configure CORS in your FastAPI app using CORSMiddleware to restrict allowed origins.
  • HTTPS: Always deploy behind a TLS-terminating proxy (e.g., NGINX, Caddy, cloud load balancer).
  • Secret Management: Never hardcode secrets. Use environment variables or a secrets manager.
  • Rate Limiting: Add rate limiting at the API gateway or with middleware to prevent brute-force attacks.
  • Email Verification: Enable and configure email verification in your login service for new users.
  • Audit Logging: Log authentication events for security monitoring.

Extending the User Model

  • You can add fields to the User model and corresponding Pydantic schemas in your own code or by forking/extending keylin.
  • All models and schemas use type annotations and are compatible with FastAPI and Pydantic.

User Model & Database Schema

Default User Model Fields

Field Type Description Required Notes
id UUID Unique user identifier Yes Primary key
email str User email (unique) Yes Unique, indexed
hashed_password str Hashed password Yes Not exposed in API responses
full_name str/None User's full name No Optional
is_active bool Is the user active? Yes
is_superuser bool Is the user an admin? Yes
is_verified bool Has the user verified email Yes

Note: The table is named "user", which is a reserved word in some databases (e.g., PostgreSQL). Consider renaming to "users" if you encounter issues.

Example User Schema

{
  "id": "uuid",
  "email": "user@example.com",
  "full_name": "User Name",
  "is_active": true,
  "is_superuser": false,
  "is_verified": true
}

Extending the User Model

  • To add fields, update the User SQLAlchemy model and the corresponding Pydantic schemas.
  • Run a new Alembic migration to update the database schema.
  • Update the UI to handle new fields as needed.
  • Keep the UI and backend in sync regarding user data shape.
  • Tip: If you need roles or permissions, add fields (e.g., role, permissions) to the model and schemas, and update your business logic accordingly.

Configuration Usage

The keylin.config.Settings class provides all configuration via environment variables or a .env file. There is no longer a global settings singleton.

  • To use configuration, import and instantiate Settings directly:
from keylin.config import Settings
settings = Settings()
  • If you are building a service that needs additional configuration, subclass Settings:
from keylin.config import Settings as KeylinSettings

class MyServiceSettings(KeylinSettings):
    MY_SERVICE_API_KEY: str

settings = MyServiceSettings()
  • All environment variables must be set before instantiating Settings.
  • JWT_SECRET must be set, or a RuntimeError will be raised at startup.

Testing

  • The test suite sets JWT_SECRET automatically for all tests (see tests/conftest.py).
  • All code and tests should instantiate Settings directly as needed.
  • There is no global singleton; each test or module should create its own Settings instance if configuration is needed.
  • See tests/unit/test_keylin.py for example tests and mocking patterns.

Setting Up the User Database

Before running your login service, you need to ensure the user table exists in your database.

Recommended: Use Alembic for Migrations

For production and team environments, use Alembic to manage database migrations:

alembic revision --autogenerate -m "create user table"
alembic upgrade head

Make sure your Alembic env.py includes the keylin model's metadata:

from keylin.models import Base

target_metadata = Base.metadata

Quick Local Setup: Create Tables Programmatically

For local development or quick tests, you can create the tables directly using SQLAlchemy:

from keylin.models import Base
from sqlalchemy import create_engine

engine = create_engine("sqlite:///./test.db")  # Or your DB URL
Base.metadata.create_all(engine)

Note: For production, always use migrations to avoid data loss and ensure schema consistency.

License

This project is licensed under the MIT License - see the LICENSE file for details.

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

keylin-0.3.1.tar.gz (11.7 kB view details)

Uploaded Source

Built Distribution

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

keylin-0.3.1-py3-none-any.whl (8.9 kB view details)

Uploaded Python 3

File details

Details for the file keylin-0.3.1.tar.gz.

File metadata

  • Download URL: keylin-0.3.1.tar.gz
  • Upload date:
  • Size: 11.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for keylin-0.3.1.tar.gz
Algorithm Hash digest
SHA256 a0c1d56587877763c115dc68212fbb7f7af54b04180dff321cfcdf9ddf7d73fa
MD5 d3f7a4efea313ebe211bf54a4df95ad8
BLAKE2b-256 308401e6b9b7da56beeed003afc081816c2a29724d800efa830a5a87d3c4866e

See more details on using hashes here.

Provenance

The following attestation bundles were made for keylin-0.3.1.tar.gz:

Publisher: publish.yml on beanone/keylin

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file keylin-0.3.1-py3-none-any.whl.

File metadata

  • Download URL: keylin-0.3.1-py3-none-any.whl
  • Upload date:
  • Size: 8.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for keylin-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 322efcad320e7ca47c5450ae7c7c0218bd7090af92e3d9678f88a7702ca9a1a1
MD5 e97d301e23f26e962ac637f8ff1b2e74
BLAKE2b-256 d2d5c768c589c26ee8e915974cb5bcbd8f3dfce34cb410b8668c150a6ecf5fad

See more details on using hashes here.

Provenance

The following attestation bundles were made for keylin-0.3.1-py3-none-any.whl:

Publisher: publish.yml on beanone/keylin

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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