Jwtlib
jwtlib
jwtlib: A framework-agnostic JWT authentication library
jwtlib provides a set of pure logic components for handling JWT discovery,
user registration, login, and token introspection. It is designed to be
decoupled from any specific web framework (like FastAPI or Flask).
Features
- Stateless Auth: Clean JWT-based authentication and logout.
- Service-to-Service: Built-in support for token introspection.
- Async-First: All core logic handlers are async-safe.
- Fully Typed: Use with
mypyorpyrightfor static safety.
Installation
pip install py-jwt
Quick Start
import asyncio
from jwtlib import login_user, LoginRequest
async def main():
request = LoginRequest(username="admin", password="password")
response = await login_user(request)
print(f"Access Token: {response.access_token}")
if __name__ == "__main__":
asyncio.run(main())
AuthError
Bases: Exception
Base authentication and authorization error.
All authentication-related exceptions raised by this library inherit from this class.
Consumers may catch this exception to handle all auth failures uniformly, or catch more specific subclasses for finer control.
IntrospectRequest
Bases: BaseModel
Payload for requesting token introspection.
Used by internal services to verify the validity of a JWT and retrieve the associated public user information.
Fields
token: JWT access token to introspect.
Notes
- Intended for service-to-service communication.
- Not meant for direct end-user consumption.
IntrospectResponse
Bases: BaseModel
Result of a token introspection operation.
This model communicates whether a JWT is valid and, if so, provides the associated public user information.
Fields
active: Indicates whether the token is valid and active. user: Public user details if the token is valid; otherwise null.
Notes
- This model is designed to avoid raising exceptions.
- All introspection outcomes are represented as data.
InvalidToken
Bases: AuthError
Raised when a JWT is missing, malformed, expired, or invalid.
This error indicates that the provided token cannot be used to authenticate a request.
LoginRequest
Bases: IdentityMixin, PasswordMixin
Payload for authenticating a user and issuing a JWT.
This model is used to verify user credentials and request an access token.
Fields
username: Username identifier. password: Plain-text password to be verified.
Notes
- Successful authentication results in a LoginResponse.
- Failed authentication raises an AuthError.
LoginResponse
Bases: BaseModel
Response returned after successful authentication.
Contains the issued JWT access token and the authenticated user's public profile.
Fields
access_token: JWT access token for authenticated requests. user: Public profile of the authenticated user.
Notes
- The token is stateless and must be stored client-side.
- Token expiration and validation are handled elsewhere.
LogoutResponse
Bases: BaseModel
Response returned after a logout operation.
Since logout is stateless, this response serves only as a confirmation message instructing the client to discard its token.
Fields
message: Human-readable logout confirmation.
PublicUser
Bases: IdentityMixin, ActiveStateMixin
Public-facing user representation returned by authentication APIs.
This model represents a user profile that is safe to expose outside the authentication system.
Fields
username: Unique username identifier. email: User's email address. is_active: Whether the user account is active.
Notes
- Contains no sensitive data.
- Can be constructed from persistence models via
from_attributes.
RegisterRequest
Bases: IdentityMixin, PasswordMixin
Payload for registering a new user account.
This model contains the minimum required identity and credential information to create a new user.
Fields
username: Unique username identifier. email: User's email address. password: Plain-text password (to be hashed by the repository layer).
Notes
- Validation and normalization handled by mixins.
- This model is never returned in responses.
TokenPayload
Bases: BaseModel
Decoded JWT payload.
Represents the validated claims extracted from a JWT after signature verification. This model is used internally to enforce required claims and provide a typed interface to token data.
Fields
sub: Subject claim identifying the user (typically a username or user ID). exp: Expiration time as a Unix timestamp (seconds since epoch).
Notes
- This model assumes the JWT signature has already been verified.
- No authorization decisions should be made solely on this model.
- Additional claims may exist but are intentionally ignored.
User
Bases: BaseDocument, IdentityMixin, ActiveStateMixin
Internal user persistence model.
Represents a user record as stored in the database. This model includes sensitive fields and is strictly confined to the persistence layer.
Fields
hashed_password: Secure hash of the user's password.
Notes
- This model MUST NOT be returned from authentication APIs.
- Consumers should use
PublicUserinstead. - Password verification is handled by the repository layer.
- Inherits identity and active-state behavior via mixins.
UserNotFound
Bases: AuthError
Raised when a valid token does not map to an existing user.
Indicates that authentication succeeded at the token level, but the associated user record could not be resolved.
authenticate_request
async
authenticate_request(should_skip_authentication: Callable[[str, str], bool], *, method: str, path: str, authorization_token: Optional[str]) -> Optional[PublicUser]
Authenticate an incoming request using token introspection.
Determines whether authentication should be skipped for the given request context and, if not, resolves the authenticated user via token introspection.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
should_skip_authentication |
Callable[[str, str], bool]
|
Callable that decides whether authentication is required for a given HTTP method and path. |
required |
method |
str
|
HTTP method of the incoming request. |
required |
path |
str
|
Request path. |
required |
authorization_token |
Optional[str]
|
JWT access token provided by the caller. |
required |
Returns:
| Type | Description |
|---|---|
Optional[PublicUser]
|
PublicUser if authentication succeeds. |
Optional[PublicUser]
|
None if authentication is skipped. |
Raises:
| Type | Description |
|---|---|
InvalidToken
|
If authentication is required but the token is missing, invalid, or revoked. |
AuthServiceUnavailable
|
If the auth service cannot be reached. |
Notes
- This function does not parse Authorization headers; callers must supply the raw token.
- Access-control policy is externalized via
should_skip_authentication. - The returned PublicUser contains no sensitive information.
get_logged_in_user
async
get_logged_in_user(token: str, repo: Optional[UserRepository] = None) -> PublicUser
Resolve the currently authenticated user from a JWT.
Validates the provided JWT, extracts its subject, and resolves the corresponding user from persistence.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
token |
str
|
JWT access token. |
required |
repo |
Optional[UserRepository]
|
Optional user repository instance. If not provided, a default repository is obtained via dependency utilities. |
None
|
Returns:
| Type | Description |
|---|---|
PublicUser
|
The authenticated user as a PublicUser. |
Raises:
| Type | Description |
|---|---|
InvalidToken
|
If the token is missing, malformed, or invalid. |
AuthError
|
If the token is valid, but the user cannot be resolved. |
introspect_token
async
introspect_token(token: str, repo: Optional[UserRepository] = None) -> IntrospectResponse
Introspect a JWT for service-to-service authentication.
Validates the provided token and resolves the associated user, returning a structured introspection response suitable for internal service use.
This function never raises authentication exceptions. Instead, it returns a typed response indicating token validity and user presence.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
token |
str
|
JWT access token to introspect. |
required |
repo |
Optional[UserRepository]
|
Optional user repository instance. If not provided, a default repository is obtained via dependency utilities. |
None
|
Returns:
| Type | Description |
|---|---|
IntrospectResponse
|
IntrospectResponse indicating one of: |
IntrospectResponse
|
|
IntrospectResponse
|
|
IntrospectResponse
|
|
login_user
async
login_user(user: LoginRequest, repo: Optional[UserRepository] = None) -> LoginResponse
Authenticate a user and issue an access token.
Verifies the provided credentials and returns a JWT access token on success.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
user |
LoginRequest
|
Login payload containing username and password. |
required |
repo |
Optional[UserRepository]
|
Optional user repository instance. If not provided, a default repository is obtained via dependency utilities. |
None
|
Returns:
| Type | Description |
|---|---|
LoginResponse
|
LoginResponse containing the issued access token and related metadata. |
Raises:
| Type | Description |
|---|---|
AuthError
|
If the credentials are invalid. |
logout_user
async
logout_user() -> LogoutResponse
Perform a stateless logout.
This function does not invalidate tokens server-side. Instead, it provides a standardized response indicating that the client must discard its token.
Returns:
| Type | Description |
|---|---|
LogoutResponse
|
LogoutResponse containing a logout confirmation message. |
register_user
async
register_user(user: RegisterRequest, repo: Optional[UserRepository] = None) -> PublicUser
Register a new user.
Creates a new user record using the provided registration data.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
user |
RegisterRequest
|
Registration payload containing username, email, and password. |
required |
repo |
Optional[UserRepository]
|
Optional user repository instance. If not provided, a default repository is obtained via dependency utilities. |
None
|
Returns:
| Type | Description |
|---|---|
PublicUser
|
The newly created user as a public user representation. |