Skip to main content

A JWT auth toolkit for Starlite

Project description

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.

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

starlite_jwt-1.5.0.tar.gz (14.2 kB view details)

Uploaded Source

Built Distribution

starlite_jwt-1.5.0-py3-none-any.whl (12.6 kB view details)

Uploaded Python 3

File details

Details for the file starlite_jwt-1.5.0.tar.gz.

File metadata

  • Download URL: starlite_jwt-1.5.0.tar.gz
  • Upload date:
  • Size: 14.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.2.2 CPython/3.10.8 Linux/5.15.0-1022-azure

File hashes

Hashes for starlite_jwt-1.5.0.tar.gz
Algorithm Hash digest
SHA256 53b8bf35db63249dcc26275412f8aa5deb43365a14a7e1a31cc15b2e951cacdf
MD5 1eec22111a9ff495e3e36b16b20765bb
BLAKE2b-256 f5cb804445d9ecec0489b3ab4e18dfe59cfba2b890253fc7611772d122c331ad

See more details on using hashes here.

File details

Details for the file starlite_jwt-1.5.0-py3-none-any.whl.

File metadata

  • Download URL: starlite_jwt-1.5.0-py3-none-any.whl
  • Upload date:
  • Size: 12.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.2.2 CPython/3.10.8 Linux/5.15.0-1022-azure

File hashes

Hashes for starlite_jwt-1.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 cdecacec7e9545a5b349f4d68bd629209c4b1191d6777d786b0043d0a177cbaa
MD5 9a3899bf729be31524e16075d8919da4
BLAKE2b-256 71622d39d1feaf54e85693e1abe8e44410643151a3429b0176b15524a7c56133

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page