{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"\ud83d\udd10 py-jwt \u2014 JWT Authentication Library","text":"

Doc model: This wiki describes the runtime, architectural, and integration behavior of jwtlib \u2014 the pure, framework-agnostic JWT authentication logic powering service auth. For the full API reference and machine-readable surface, see the Library and MCP tabs.

jwtlib provides pure logic components for user registration, login, token introspection, and authentication verification. It has no web-framework dependencies: FastAPI, Flask, or plain asyncio apps can use the same coroutine-based API.

"},{"location":"#key-features","title":"\ud83d\ude80 Key Features","text":""},{"location":"#quick-start","title":"\u26a1 Quick Start","text":"
import asyncio\nfrom jwtlib import login_user, LoginRequest\n\nasync def main():\n    response = await login_user(LoginRequest(username=\"admin\", password=\"password\"))\n    print(response.access_token)\n    print(response.user.username)\n\nasyncio.run(main())\n

See How to Use for registration, session checks, and introspection flows.

"},{"location":"#documentation-structure","title":"\ud83d\udcd6 Documentation Structure","text":"Section Description Overview Architecture, layers, and public API surface How to Use Register, login, session lookup, logout, introspection Framework Integration Wiring jwtlib into FastAPI and resource servers Development Setup, tests, and docforge build

The reference implementations of these skills live in the auth-server service.

"},{"location":"#related-resources","title":"\ud83d\udd17 Related Resources","text":"

\u00a9 Aetoskia Internal \u2014 py-jwt 0.0.4

"},{"location":"01_overview/","title":"\ud83e\udde0 Overview","text":"

jwtlib is a small, focused authentication library. It keeps transport concerns out of auth logic so the same code backs an API service and a CLI or test harness.

"},{"location":"01_overview/#architecture","title":"\ud83c\udfd7\ufe0f Architecture","text":"
\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502                        Your application                      \u2502\n\u2502   (FastAPI / Flask / CLI / tests)                            \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n                            \u2502 coroutine API\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25bc\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502  jwtlib.app                                                 \u2502\n\u2502  register_user \u00b7 login_user \u00b7 get_logged_in_user            \u2502\n\u2502  logout_user \u00b7 introspect_token                             \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502  jwtlib.introspection     \u2502  jwtlib.security (token ops)    \u2502\n\u2502  authenticate_request     \u2502                                 \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25bc\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502  jwtlib.models                                            \u2502\n\u2502  RegisterRequest \u00b7 LoginRequest \u00b7 LoginResponse            \u2502\n\u2502  PublicUser \u00b7 IntrospectRequest \u00b7 IntrospectResponse       \u2502\n\u2502  TokenPayload \u00b7 User                                      \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502  jwtlib.repository                                       \u2502\n\u2502  UserRepository (MongoDB-backed default)                  \u2502\n\u2502                     \u25b2                                      \u2502\n\u2502   inject your own repository for other backends            \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n
"},{"location":"01_overview/#public-api-layers","title":"\ud83e\udde9 Public API layers","text":""},{"location":"01_overview/#authentication-operations-jwtlibapp","title":"Authentication operations (jwtlib.app)","text":"Function Purpose register_user(user, repo=None) Create a user from RegisterRequest login_user(user, repo=None) Verify credentials, issue an access token get_logged_in_user(token, repo=None) Resolve the token's subject to a user logout_user() Model the client-side logout signal introspect_token(token, repo=None) Verify a token and produce an introspection verdict

Every operation is an async function; the default UserRepository is a MongoDB-backed implementation of the repository contract.

"},{"location":"01_overview/#introspection-helpers-jwtlibintrospection","title":"Introspection helpers (jwtlib.introspection)","text":""},{"location":"01_overview/#domain-models-jwtlibmodels","title":"Domain models (jwtlib.models)","text":""},{"location":"01_overview/#errors-jwtlibexceptions","title":"Errors (jwtlib.exceptions)","text":"

AuthError is the base for InvalidToken, InvalidAuthorizationHeader, UserNotFound, AuthServiceUnavailable, and NotAuthenticated.

"},{"location":"01_overview/#security-posture","title":"\ud83d\udd12 Security posture","text":""},{"location":"01_overview/#read-next","title":"\ud83d\udcda Read Next","text":""},{"location":"02_how_to_use/","title":"\ud83d\udcd6 How to Use","text":"

All operations are plain async functions that work identically under FastAPI, Flask, a CLI, or a script. Substitute your own repository to change the persistence backend.

"},{"location":"02_how_to_use/#register-a-user","title":"\u270d\ufe0f Register a user","text":"
import asyncio\nfrom jwtlib import register_user, RegisterRequest\n\nasync def main():\n    user = await register_user(\n        RegisterRequest(username=\"admin\", email=\"admin@aetoskia.com\", password=\"hunter2\")\n    )\n    print(user.username, user.is_active)\n\nasyncio.run(main())\n

Returns a PublicUser. Registration hashes the password before it reaches the repository.

"},{"location":"02_how_to_use/#log-in","title":"\ud83d\udd11 Log in","text":"
from jwtlib import login_user, LoginRequest\n\nresponse = await login_user(LoginRequest(username=\"admin\", password=\"hunter2\"))\n\nresponse.access_token  # store this in the Authorization header\nresponse.user.username\n

A successful login returns LoginResponse with an access token and the public user. Failures raise AuthError subclasses; catch them and map to your HTTP semantics (e.g. 401).

"},{"location":"02_how_to_use/#check-the-current-user","title":"\ud83d\udc64 Check the current user","text":"
from jwtlib import get_logged_in_user\n\nuser = await get_logged_in_user(bearer_token)\nprint(user.username, user.email, user.is_active)\n

Resolves the token subject to a PublicUser. Raises InvalidToken if the token is missing, expired, or malformed, and UserNotFound if the subject no longer exists.

"},{"location":"02_how_to_use/#log-out","title":"\ud83d\udeaa Log out","text":"
from jwtlib import logout_user\n\nresult = await logout_user()\nprint(result.message)\n

Logout is a client-side signal: the returned LogoutResponse tells the caller to discard the stored token. Stateless services should simply stop using the token after logout.

"},{"location":"02_how_to_use/#introspect-a-token","title":"\ud83d\udd0e Introspect a token","text":"

Verify an arbitrary token and get a structured verdict:

from jwtlib import introspect_token\n\nverdict = await introspect_token(bearer_token)\n\nverdict.active        # True when the token is valid\nverdict.user.username # resolved subject, or None\n

IntrospectResponse also provides result helpers used by the canonical service for error mapping. For a pure boolean authorization check:

from jwtlib.introspection import authenticate_request\n\nok = await authenticate_request(bearer_token)  # True / False\n
"},{"location":"02_how_to_use/#injecting-a-custom-repository","title":"\ud83d\udc89 Injecting a custom repository","text":"

Every operation accepts an optional repo. Provide your own UserRepository-compatible object to swap storage:

from jwtlib import login_user, LoginRequest\n\nclass MyRepo:\n    async def get_by_username(self, username: str): ...\n    async def authenticate_user(self, user_auth: LoginRequest): ...\n\nresponse = await login_user(LoginRequest(username=\"admin\", password=\"x\"), repo=MyRepo())\n
"},{"location":"02_how_to_use/#read-next","title":"\ud83d\udcda Read Next","text":""},{"location":"03_integration/","title":"\ud83d\udd0c Framework Integration","text":"

jwtlib is intentionally framework-agnostic. This page shows the idiomatic wiring used by the canonical auth-server service.

"},{"location":"03_integration/#fastapi-dependency","title":"\u2699\ufe0f FastAPI dependency","text":"

Expose the token from the Authorization header and resolve it to a user via a dependency:

from fastapi import Depends, FastAPI, HTTPException, status\nfrom jwtlib import get_logged_in_user\nfrom jwtlib.exceptions import AuthError\n\napp = FastAPI()\n\n\ndef bearer_token(authorization: str = Header(...)) -> str:\n    scheme, _, token = authorization.partition(\" \")\n    if scheme.lower() != \"bearer\" or not token:\n        raise HTTPException(status.HTTP_401_UNAUTHORIZED, \"Invalid authorization header\")\n    return token\n\n\nasync def current_user(token: str = Depends(bearer_token)):\n    try:\n        return await get_logged_in_user(token)\n    except AuthError:\n        raise HTTPException(status.HTTP_401_UNAUTHORIZED, \"Not authenticated\")\n\n\n@app.get(\"/me\")\nasync def me(user=Depends(current_user)):\n    return {\"username\": user.username, \"email\": user.email}\n

On any auth failure the dependency translates AuthError into a 401 \u2014 the library never couples to the HTTP layer.

"},{"location":"03_integration/#resource-server-microservice","title":"\ud83d\udce1 Resource server / microservice","text":"

A consumer service that does not own the user database can verify tokens via introspection without a shared session store:

from jwtlib.introspection import authenticate_request\n\n\nasync def is_allowed(authorization: str) -> bool:\n    scheme, _, token = authorization.partition(\" \")\n    if scheme.lower() != \"bearer\":\n        return False\n    return await authenticate_request(token)\n
"},{"location":"03_integration/#routing-tokens","title":"\ud83e\udded Routing tokens","text":"

Keep Authorization: Bearer <token> consistent across all callers.

"},{"location":"03_integration/#error-mapping-cheat-sheet","title":"\u26a0\ufe0f Error mapping cheat-sheet","text":"Raised exception Typical HTTP result InvalidAuthorizationHeader 401 \u2014 malformed header InvalidToken 401 \u2014 expired, bad signature, or malformed UserNotFound 401 \u2014 subject no longer exists AuthServiceUnavailable 503 \u2014 upstream auth unavailable NotAuthenticated 401 \u2014 missing credentials"},{"location":"03_integration/#read-next","title":"\ud83d\udcda Read Next","text":""},{"location":"04_development/","title":"\ud83d\udee0\ufe0f Development","text":"

Working on jwtlib itself.

"},{"location":"04_development/#repository-layout","title":"\ud83d\udcc2 Repository layout","text":"Path Purpose jwtlib/ The library package (app, introspection, models, repository, security, utils, exceptions) jwtlib/*.pyi Type stubs published alongside the implementations tests/ Auth-flow tests (register \u2192 login \u2192 verify \u2192 logout) docs/lib/ Generated library reference (docforge, flat layout) docs/mcp/ Machine-readable bundle served by the MCP server docs/wiki/ This hand-written wiki"},{"location":"04_development/#setup","title":"\ud83d\udd27 Setup","text":"
python -m venv .venv\n.venv/Scripts/pip install -e \".[dev]\"\n
"},{"location":"04_development/#tests","title":"\ud83e\uddea Tests","text":"
.venv/Scripts/python -m pytest\n

The suite drives the full async auth flow: registration, login, duplicate handling, session lookup, logout, and introspection.

"},{"location":"04_development/#quality-gates","title":"\u2705 Quality gates","text":"

The CI quality gate runs, matching the Drone pipeline:

.venv/Scripts/black --check .\n.venv/Scripts/ruff check .\n.venv/Scripts/mypy\n.venv/Scripts/python -m pytest\n
"},{"location":"04_development/#building-documentation-docforge","title":"\ud83d\udcdd Building documentation (docforge)","text":"

The site is generated by docforge and served per kind under site/{kind}:

doc-forge build \\\n  --mkdocs --mcp --wiki \\\n  --module-is-source --module jwtlib \\\n  --site-name \"JWT Authentication Library\"\n

Preview locally:

doc-forge serve --lib\ndoc-forge serve --wiki\ndoc-forge serve --mcp\n
"},{"location":"04_development/#security-checklist","title":"\ud83d\udd12 Security checklist","text":""},{"location":"04_development/#read-next","title":"\ud83d\udcda Read Next","text":""}]}