Skip to main content

Shared authentication schemas, JWT utilities and FastAPI base components for m8 microservices.

Project description

auth-sdk-m8

Shared authentication schemas, JWT utilities, and FastAPI base components for m8 microservices.

This package is extracted from auth_user_service and is intended to be installed by any service that integrates with it via Docker Compose. It provides the Pydantic schemas matching the auth service's API, JWT validation helpers, and optional FastAPI/SQLModel base classes.


Installation

From GitLab Package Registry (recommended after first publish)

pip install auth-sdk-m8 \
  --index-url https://gitlab.com/api/v4/projects/<PROJECT_ID>/packages/pypi/simple \
  --extra-index-url https://pypi.org/simple

With a deploy token in pip.conf or ~/.netrc:

# pip.conf
[global]
index-url = https://gitlab.com/api/v4/projects/<PROJECT_ID>/packages/pypi/simple
extra-index-url = https://pypi.org/simple

Directly from GitLab via git

pip install "auth-sdk-m8 @ git+https://gitlab.com/yourorg/auth-sdk-m8.git@v0.1.0"

For development (editable install)

git clone https://gitlab.com/yourorg/auth-sdk-m8.git
cd auth-sdk-m8
pip install -e ".[all,dev]"

Optional dependency groups

Install only what your service needs:

Extra Installs Use when
(none) pydantic, email-validator schemas only
[security] PyJWT local JWT validation
[fastapi] fastapi cookie helpers, BaseController
[redis] redis Redis event bus
[config] pydantic-settings CommonSettings base class
[db] sqlmodel, sqlalchemy TimestampMixin, DB error parsing
[all] everything above full feature set

Examples:

# A service that only validates tokens locally
pip install "auth-sdk-m8[security]"

# A FastAPI service using BaseController and JWT
pip install "auth-sdk-m8[security,fastapi,db]"

# A service that only listens to Redis events
pip install "auth-sdk-m8[redis]"

Quick start

Validate a JWT from auth_user_service

from auth_sdk_m8.core.security import ComSecurityHelper
from auth_sdk_m8.core.exceptions import InvalidToken
from auth_sdk_m8.schemas.auth import TokenDecodeProps
from pydantic import SecretStr

try:
    user = ComSecurityHelper.decode_access_token(
        TokenDecodeProps(
            access_token=bearer_token,
            secret_key=SecretStr(ACCESS_SECRET_KEY),
            algorithm="HS256",
        )
    )
    print(user.email, user.role)
except InvalidToken:
    # token expired or invalid signature
    ...

FastAPI dependency for token validation

from fastapi import Depends, HTTPException
from fastapi.security import OAuth2PasswordBearer
from auth_sdk_m8.core.security import ComSecurityHelper
from auth_sdk_m8.core.exceptions import InvalidToken
from auth_sdk_m8.schemas.auth import TokenDecodeProps
from auth_sdk_m8.schemas.user import UserModel
from pydantic import SecretStr

oauth2 = OAuth2PasswordBearer(tokenUrl="/auth/login/access-token")

def get_current_user(token: str = Depends(oauth2)) -> UserModel:
    try:
        payload = ComSecurityHelper.decode_access_token(
            TokenDecodeProps(
                access_token=token,
                secret_key=SecretStr(settings.ACCESS_SECRET_KEY),
                algorithm=settings.TOKEN_ALGORITHM,
            )
        )
    except InvalidToken as exc:
        raise HTTPException(status_code=403, detail="Could not validate credentials.") from exc
    return UserModel(id=payload.sub, **payload.model_dump(exclude={"sub", "jti", "exp", "type"}))

Extend CommonSettings for your service

from pathlib import Path
from auth_sdk_m8.core.config import CommonSettings
from auth_sdk_m8.utils.paths import find_dotenv
from pydantic_settings import SettingsConfigDict

class Settings(CommonSettings):
    ENV_FILE_DIR = Path(__file__).resolve().parent
    model_config = SettingsConfigDict(
        env_file=find_dotenv(ENV_FILE_DIR),
        env_file_encoding="utf-8",
    )
    # add service-specific fields here
    MY_SERVICE_SECRET: str

settings = Settings()

Listen to Redis events from auth_user_service

import asyncio
from auth_sdk_m8.redis_events.event_bus import EventBus
from auth_sdk_m8.schemas.user_events import UserDeletedEvent

bus = EventBus(redis_url="redis://localhost:6379")

async def on_user_deleted(event: UserDeletedEvent) -> None:
    print(f"User {event.user_id} was deleted — cleaning up local data.")

async def main():
    await bus.subscribe("user.deleted", UserDeletedEvent, on_user_deleted)
    await asyncio.sleep(3600)  # keep running

asyncio.run(main())

Package layout

src/auth_sdk_m8/
├── schemas/
│   ├── auth.py          # JWT payload schemas (TokenUserData, TokenAccessData, …)
│   ├── base.py          # Enums (AuthProviderType, RoleType, Period) + response models
│   ├── shared.py        # ValidationConstants (regex patterns)
│   ├── user.py          # UserModel, SessionModel
│   ├── redis_events.py  # EventBase
│   └── user_events.py   # UserDeletedEvent
├── core/
│   ├── config.py        # CommonSettings (pydantic-settings base class)
│   ├── exceptions.py    # InvalidToken
│   └── security.py      # ComSecurityHelper: JWT decode, PKCE, token hashing
├── redis_events/
│   ├── event_bus.py     # EventBus (typed pub/sub)
│   ├── publisher.py     # EventPublisher
│   └── subscriber.py    # EventSubscriber
├── controllers/
│   └── base.py          # BaseController: unified exception → JSONResponse
├── models/
│   └── shared.py        # TimestampMixin, Message, Token, TokenPayload (SQLModel)
└── utils/
    ├── errors_parser.py # parse_integrity_error, parse_pydantic_errors
    └── paths.py         # find_dotenv

Publishing a new version

  1. Bump version in pyproject.toml
  2. Add an entry to CHANGELOG.md
  3. Commit and push
  4. Create a git tag: git tag v0.2.0 && git push origin v0.2.0
  5. GitLab CI builds and publishes automatically to the Package Registry

Architecture note

This SDK is intentionally thin. It contains no business logic — only schemas, validation helpers, and infrastructure base classes. Each consuming service validates JWTs locally using ComSecurityHelper (no network call per request). The auth_user_service remains the sole authority for issuing tokens; this SDK only provides the tools to read them.

For production deployments with multiple teams, consider switching to RS256 asymmetric signing so consuming services only need the public key (never the secret).

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

auth_sdk_m8-0.1.0.2.tar.gz (29.3 kB view details)

Uploaded Source

Built Distribution

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

auth_sdk_m8-0.1.0.2-py3-none-any.whl (24.4 kB view details)

Uploaded Python 3

File details

Details for the file auth_sdk_m8-0.1.0.2.tar.gz.

File metadata

  • Download URL: auth_sdk_m8-0.1.0.2.tar.gz
  • Upload date:
  • Size: 29.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for auth_sdk_m8-0.1.0.2.tar.gz
Algorithm Hash digest
SHA256 a6428c3363993ddb12da9b1cdee59d6327508c8368cf6240a73fdfe876895d0d
MD5 9bddde1fa23b66c3d0ea06dd295a0696
BLAKE2b-256 d484db9713f826140c9ff3ff8e0aba6dfc1efb82552e5bdcaf38ddced0082aac

See more details on using hashes here.

File details

Details for the file auth_sdk_m8-0.1.0.2-py3-none-any.whl.

File metadata

  • Download URL: auth_sdk_m8-0.1.0.2-py3-none-any.whl
  • Upload date:
  • Size: 24.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for auth_sdk_m8-0.1.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 a94b318d1ce715074434d9ffc8ac014490ca29e12182b6fd0122e556c5be586f
MD5 de0058a5693fcf858cd79457d20a06d3
BLAKE2b-256 a2ae213b03da4bc9bd5998df1762aa176cbd8933063055b18ac75dd3e3082ed1

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