Skip to content

Transports

The Transport protocol defines how credentials move between client and server: reading token material from an incoming request and attaching issued tokens to responses. Implementations decide where credentials live on the wire; a paired strategy decides how tokens are validated or minted.

BearerTransport uses the Authorization: Bearer <token> header for API-style clients. CookieTransport stores tokens in HTTP-only cookies for browser sessions, which affects CSRF posture when cookies are used without a separate header secret. ApiKeyTransport accepts formatted API keys through either Authorization: Bearer ak_... or X-API-Key; it also parses Authorization: LSA1-HMAC-SHA256 ... for signed API-key requests.

Transports are always composed with a Strategy inside an AuthenticationBackend: the backend wires one transport to one strategy so login, logout, and per-request authentication share the same token semantics. For how backends fit together and when to pick Bearer vs cookies, see Backends: transports and strategies. For cookie-based setups, review Cookie transport and CSRF.

litestar_auth.authentication.transport

Move credentials between client and server (Bearer header vs HTTP-only cookies).

Transports are composed with a :class:~litestar_auth.authentication.strategy.Strategy inside an :class:~litestar_auth.authentication.backend.AuthenticationBackend.

ApiKeyTransport(*, prefix=API_KEY_PREFIX)

Bases: Transport

Transport that reads canonical API keys from bearer auth or X-API-Key.

Store the accepted API-key prefix.

Source code in litestar_auth/authentication/transport/api_key.py
def __init__(self, *, prefix: str = API_KEY_PREFIX) -> None:
    """Store the accepted API-key prefix."""
    self.prefix = prefix

read_token(connection) async

Return an API-key token from Authorization or X-API-Key headers.

Source code in litestar_auth/authentication/transport/api_key.py
@override
async def read_token(self, connection: ASGIConnection[Any, Any, Any, Any]) -> str | None:
    """Return an API-key token from ``Authorization`` or ``X-API-Key`` headers."""
    signed_request_scheme = read_signed_api_key_request(connection)
    if signed_request_scheme is not None:
        return signed_request_scheme

    bearer_token = self._read_bearer_token(connection)
    if bearer_token is not None:
        return bearer_token

    header_token = connection.headers.get(API_KEY_HEADER_NAME)
    if header_token is None:
        return None
    token = header_token.strip()
    if not token.startswith(f"{self.prefix}_"):
        return None
    return token

set_login_token(response, token)

Reject login issuance because API keys are not login-flow tokens.

Raises:

Type Description
TokenError

Always, because API keys are not issued by login.

Source code in litestar_auth/authentication/transport/api_key.py
@override
def set_login_token(self, response: Response[Any], token: str) -> Response[Any]:
    """Reject login issuance because API keys are not login-flow tokens.

    Raises:
        TokenError: Always, because API keys are not issued by login.
    """
    del response, token
    msg = "API-key transport cannot issue login tokens."
    raise TokenError(msg)

set_logout(response)

Leave logout responses unchanged because API keys keep no client state.

Returns:

Type Description
Response[Any]

The original response.

Source code in litestar_auth/authentication/transport/api_key.py
@override
def set_logout(self, response: Response[Any]) -> Response[Any]:
    """Leave logout responses unchanged because API keys keep no client state.

    Returns:
        The original response.
    """
    return response

BearerTransport

Bases: Transport

Transport that reads tokens from the Authorization header.

read_token(connection) async

Return the bearer token from the Authorization header when present.

Source code in litestar_auth/authentication/transport/bearer.py
@override
async def read_token(self, connection: ASGIConnection[Any, Any, Any, Any]) -> str | None:
    """Return the bearer token from the Authorization header when present."""
    authorization = connection.headers.get("Authorization")
    if authorization is None:
        return None

    scheme, _, token = authorization.partition(" ")
    if scheme.lower() != self.scheme:
        return None
    token = token.strip()
    if not token:
        return None
    return token

set_login_token(response, token)

Store the issued bearer token in the response body.

Returns:

Type Description
Response[Any]

The mutated response.

Source code in litestar_auth/authentication/transport/bearer.py
@override
def set_login_token(self, response: Response[Any], token: str) -> Response[Any]:
    """Store the issued bearer token in the response body.

    Returns:
        The mutated response.
    """
    response.content = {"access_token": token, "token_type": self.scheme}
    response.media_type = MediaType.JSON
    return response

set_logout(response)

Clear the response body because bearer transport keeps no client state.

Returns:

Type Description
Response[Any]

The mutated response.

Source code in litestar_auth/authentication/transport/bearer.py
@override
def set_logout(self, response: Response[Any]) -> Response[Any]:
    """Clear the response body because bearer transport keeps no client state.

    Returns:
        The mutated response.
    """
    response.content = None
    return response

CookieTransport(config=None, **options)

Bases: Transport

Transport that stores authentication tokens in HTTP cookies.

Initialize the cookie transport configuration.

Parameters:

Name Type Description Default
config CookieTransportConfig | None

Cookie transport configuration. Omit for secure defaults.

None
**options Unpack[CookieTransportConfigOptions]

Individual cookie transport settings. Do not combine with config.

{}

Raises:

Type Description
ValueError

If config and keyword options are combined.

ValueError

If samesite="none" is configured with secure=False.

Source code in litestar_auth/authentication/transport/cookie.py
def __init__(
    self,
    config: CookieTransportConfig | None = None,
    **options: Unpack[CookieTransportConfigOptions],
) -> None:
    """Initialize the cookie transport configuration.

    Args:
        config: Cookie transport configuration. Omit for secure defaults.
        **options: Individual cookie transport settings. Do not combine with
            ``config``.

    Raises:
        ValueError: If ``config`` and keyword options are combined.
        ValueError: If ``samesite="none"`` is configured with ``secure=False``.
    """
    if config is not None and options:
        msg = "Pass either CookieTransportConfig or keyword options, not both."
        raise ValueError(msg)
    settings = CookieTransportConfig(**options) if config is None else config
    if settings.samesite == "none" and not settings.secure:
        msg = 'CookieTransport with samesite="none" requires secure=True.'
        raise ValueError(msg)
    self.cookie_name = settings.cookie_name
    self.max_age = settings.max_age
    self.path = settings.path
    self.domain = settings.domain
    self.secure = settings.secure
    self.httponly = settings.httponly
    self.samesite = settings.samesite
    self.allow_insecure_cookie_auth = settings.allow_insecure_cookie_auth
    # Security: separate refresh cookie lifetime prevents premature browser
    # deletion when access-token max_age is shorter than the refresh strategy TTL.
    self.refresh_max_age = settings.refresh_max_age

Return the cookie key used to carry refresh tokens in cookie flows.

clear_refresh_token(response)

Expire the refresh-token cookie immediately.

Returns:

Type Description
Response[Any]

The mutated response.

Source code in litestar_auth/authentication/transport/cookie.py
def clear_refresh_token(self, response: Response[Any]) -> Response[Any]:
    """Expire the refresh-token cookie immediately.

    Returns:
        The mutated response.
    """
    return self._set_cookie(
        response,
        key=self.refresh_cookie_name,
        value="",
        max_age=0,
        httponly=True,
    )

read_logout_token(connection) async

Return the access-token cookie value to invalidate during logout.

Logout token sourcing is explicit here: cookie logout invalidates the access-token cookie and does not read refresh-token cookies.

Source code in litestar_auth/authentication/transport/cookie.py
async def read_logout_token(self, connection: ASGIConnection[Any, Any, Any, Any]) -> str | None:
    """Return the access-token cookie value to invalidate during logout.

    Logout token sourcing is explicit here: cookie logout invalidates the
    access-token cookie and does not read refresh-token cookies.
    """
    return await self.read_token(connection)

read_refresh_token(connection) async

Return the refresh token from the dedicated refresh-token cookie.

Source code in litestar_auth/authentication/transport/cookie.py
async def read_refresh_token(self, connection: ASGIConnection[Any, Any, Any, Any]) -> str | None:
    """Return the refresh token from the dedicated refresh-token cookie."""
    return connection.cookies.get(self.refresh_cookie_name)

read_token(connection) async

Return the authentication token from the configured cookie.

Source code in litestar_auth/authentication/transport/cookie.py
@override
async def read_token(self, connection: ASGIConnection[Any, Any, Any, Any]) -> str | None:
    """Return the authentication token from the configured cookie."""
    return connection.cookies.get(self.cookie_name)

set_login_token(response, token)

Persist the issued token in the configured cookie.

Security

When this transport is used for browser-based authentication, you MUST pair it with an explicit CSRF protection mechanism (for example, a separate CSRF cookie and a required X-CSRF-Token header on state-changing requests). This is especially important when samesite=\"none\" is used for cross-site scenarios, because browsers will attach cookies automatically to cross-origin requests.

Returns:

Type Description
Response[Any]

The mutated response.

Source code in litestar_auth/authentication/transport/cookie.py
@override
def set_login_token(self, response: Response[Any], token: str) -> Response[Any]:
    r"""Persist the issued token in the configured cookie.

    Security:
        When this transport is used for browser-based authentication, you MUST
        pair it with an explicit CSRF protection mechanism (for example, a
        separate CSRF cookie and a required X-CSRF-Token header on state-changing
        requests). This is especially important when ``samesite=\"none\"`` is used
        for cross-site scenarios, because browsers will attach cookies
        automatically to cross-origin requests.

    Returns:
        The mutated response.
    """
    return self._set_cookie(
        response,
        key=self.cookie_name,
        value=token,
        max_age=self.max_age,
        httponly=self.httponly,
    )

set_logout(response)

Remove the access-token cookie by expiring it immediately.

Note

This transport-level method clears only the access-token cookie. The refresh-token cookie is cleared by :meth:AuthenticationBackend.logout, which calls :meth:clear_refresh_token after this method.

Returns:

Type Description
Response[Any]

The mutated response.

Source code in litestar_auth/authentication/transport/cookie.py
@override
def set_logout(self, response: Response[Any]) -> Response[Any]:
    """Remove the access-token cookie by expiring it immediately.

    Note:
        This transport-level method clears only the access-token cookie.
        The refresh-token cookie is cleared by
        :meth:`AuthenticationBackend.logout`, which calls
        :meth:`clear_refresh_token` after this method.

    Returns:
        The mutated response.
    """
    return self._set_cookie(
        response,
        key=self.cookie_name,
        value="",
        max_age=0,
        httponly=self.httponly,
    )

set_refresh_token(response, refresh_token)

Persist a refresh token in a dedicated HttpOnly cookie.

Note

This library intentionally treats refresh tokens as a separate artifact from the access-token cookie used for request authentication.

Returns:

Type Description
Response[Any]

The mutated response.

Source code in litestar_auth/authentication/transport/cookie.py
def set_refresh_token(self, response: Response[Any], refresh_token: str) -> Response[Any]:
    """Persist a refresh token in a dedicated HttpOnly cookie.

    Note:
        This library intentionally treats refresh tokens as a separate artifact from the
        access-token cookie used for request authentication.

    Returns:
        The mutated response.
    """
    # Security: use dedicated refresh_max_age so the cookie outlives the access-token cookie.
    effective_max_age = self.refresh_max_age if self.refresh_max_age is not None else self.max_age
    return self._set_cookie(
        response,
        key=self.refresh_cookie_name,
        value=refresh_token,
        max_age=effective_max_age,
        httponly=True,
    )

CookieTransportConfig(cookie_name='litestar_auth', max_age=None, path='/', domain=None, secure=True, httponly=True, samesite='lax', allow_insecure_cookie_auth=False, refresh_max_age=None) dataclass

Configuration for :class:CookieTransport.

Transport

Bases: ABC

Abstract base class for moving auth tokens through HTTP requests.

read_token(connection) abstractmethod async

Extract an authentication token from the incoming connection.

Source code in litestar_auth/authentication/transport/base.py
@abstractmethod
async def read_token(self, connection: ASGIConnection[Any, Any, Any, Any]) -> str | None:
    """Extract an authentication token from the incoming connection."""

set_login_token(response, token) abstractmethod

Attach an authentication token to the login response.

Source code in litestar_auth/authentication/transport/base.py
@abstractmethod
def set_login_token(self, response: Response[Any], token: str) -> Response[Any]:
    """Attach an authentication token to the login response."""

set_logout(response) abstractmethod

Clear any transport-managed authentication state on logout.

Source code in litestar_auth/authentication/transport/base.py
@abstractmethod
def set_logout(self, response: Response[Any]) -> Response[Any]:
    """Clear any transport-managed authentication state on logout."""