Skip to main content
Archived

This project has been archived by its maintainers, and is no longer receiving any updates.

Starlite JWT

Starlite logo

PyPI - License PyPI - Python Version

Quality Gate Status Coverage

Maintainability Rating Security Rating Reliability Rating Code Smells

Discord Matrix

This library offers simple JWT authentication for Starlite.

Checkout the docs 📚.

Installation

pip install starlite-jwt

This library uses the excellent python-jose library, which supports multiple cryptographic backends. You can install either pyca/cryptography or pycryptodome, and it will be used as the backend automatically. Note that if you want to use a certificate based encryption scheme, you must install one of these backends - please refer to the python-jose readme for more details.

Example

import os
from typing import Any, Optional
from uuid import UUID, uuid4

from pydantic import BaseModel, EmailStr
from starlite import OpenAPIConfig, Request, Response, ASGIConnection, Starlite, get

from starlite_jwt import JWTAuth, Token


# Let's assume we have a User model that is a pydantic model.
# This though is not required - we need some sort of user class -
# but it can be any arbitrary value, e.g. an SQLAlchemy model, a representation of a MongoDB  etc.
class User(BaseModel):
    id: UUID
    name: str
    email: EmailStr


# The JWTAuth package requires a handler callable that takes a unique identifier, and returns the 'User'
# instance correlating to it.
#
# The identifier is the 'sub' key of the JWT, and it usually correlates to a user ID.
# It can be though any arbitrary value you decide upon - as long as the handler function provided
# can receive this value and return the model instance for it.
#
# Note: The callable can be either sync or async - both will work.
async def retrieve_user_handler(
    unique_identifier: str, connection: ASGIConnection[Any, Any, Any]
) -> Optional[User]:
    # logic here to retrieve the user instance
    ...


# The minimal configuration required for the library is the callable for the 'retrieve_user_handler' key, and a string
# value for the token secret.
#
# Important: secrets should never be hardcoded. Its best practice to pass the secret using ENV.
#
# Tip: It's also a good idea to use the pydantic settings management functionality
jwt_auth = JWTAuth(
    retrieve_user_handler=retrieve_user_handler,
    token_secret=os.environ.get("JWT_SECRET", "abcd123"),
    # we are specifying which endpoints should be excluded from authentication. In this case the login endpoint
    # and our openAPI docs.
    exclude=["/login", "/schema"],
)


# Given an instance of 'JWTAuth' we can create a login handler function:
@get("/login")
def login_handler() -> Response[User]:
    # we have a user instance - probably by retrieving it from persistence using another lib.
    # what's important for our purposes is to have an identifier:
    user = User(name="Moishe Zuchmir", email="zuchmir@moishe.com", id=uuid4())

    response = jwt_auth.login(identifier=str(user.id), response_body=user)

    # you can do whatever you want to update the response instance here
    # e.g. response.set_cookie(...)

    return response


# We also have some other routes, for example:
@get("/some-path")
def some_route_handler(request: Request[User, Token]) -> Any:
    # request.user is set to the instance of user returned by the middleware
    assert isinstance(request.user, User)
    # request.auth is the instance of 'starlite_jwt.Token' created from the data encoded in the auth header
    assert isinstance(request.auth, Token)
    # do stuff ...


# We add the jwt security schema to the OpenAPI config.
openapi_config = OpenAPIConfig(
    title="My API",
    version="1.0.0",
    components=[jwt_auth.openapi_components],
    security=[jwt_auth.security_requirement],
)

# We initialize the app instance, passing to it the 'jwt_auth.middleware' and the 'openapi_config'.
app = Starlite(
    route_handlers=[login_handler, some_route_handler],
    middleware=[jwt_auth.middleware],
    openapi_config=openapi_config,
)

Customization

This integrates with the OpenAPI configuration of Starlite, and it uses the SecurityScheme configuration to format the header and/or cookie value.

The default implementation follows the Bearer {encoded_token} format, but you may optionally override this configuration by modifying the openapi_component attribute of your JWTAuth instance.

If you wanted your authentication header to be Token {encoded_token}, you could use the following as your security scheme configuration:

from pydantic_openapi_schema.v3_1_0 import Components, SecurityScheme
from starlite_jwt import JWTAuth


class CustomJWTAuth(JWTAuth):
    @property
    def openapi_components(self) -> Components:
        """Creates OpenAPI documentation for the JWT auth schema used.

        Returns:
            An [Components][pydantic_schema_pydantic.v3_1_0.components.Components] instance.
        """
        return Components(
            securitySchemes={
                self.openapi_security_scheme_name: SecurityScheme(
                    type="http",
                    scheme="Token",
                    name=self.auth_header,
                    bearerFormat="JWT",
                    description="JWT api-key authentication and authorization.",
                )
            }
        )

Contributing

Starlite and all its official libraries is open to contributions big and small.

You can always join our discord server or join our Matrix space to discuss contributions and project maintenance. For guidelines on how to contribute to this library, please see the contribution guide.

Metadata

Release files for starlite-jwt 1.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for starlite-jwt 1.5.0
File Size Uploaded
starlite_jwt-1.5.0.tar.gz 14.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for starlite-jwt 1.5.0
File Interpreter ABI Platform
starlite_jwt-1.5.0-py3-none-any.whl Python 3 none any Details

Total release size: 26.8 kB

Release files / starlite_jwt-1.5.0.tar.gz

Download URL starlite_jwt-1.5.0.tar.gz
Size 14.2 kB
Tags Source
SHA-256 checksum
How to use checksums
53b8bf35db63249dcc26275412f8aa5deb43365a14a7e1a31cc15b2e951cacdf
BLAKE2b-256 checksum
How to use checksums
f5cb804445d9ecec0489b3ab4e18dfe59cfba2b890253fc7611772d122c331ad
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.2.2 CPython/3.10.8 Linux/5.15.0-1022-azure

Release files / starlite_jwt-1.5.0-py3-none-any.whl

Download URL starlite_jwt-1.5.0-py3-none-any.whl
Size 12.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
cdecacec7e9545a5b349f4d68bd629209c4b1191d6777d786b0043d0a177cbaa
BLAKE2b-256 checksum
How to use checksums
71622d39d1feaf54e85693e1abe8e44410643151a3429b0176b15524a7c56133
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.2.2 CPython/3.10.8 Linux/5.15.0-1022-azure
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page