Skip to content

/litestar-security

Auto-activate for litestar_security, SecurityPlugin, SecurityConfig, CurrentUser, Principal, SecurityContext, requires_role, requires_scope, requires_authenticated, requires_tenant, or requires_capability. Not for raw auth guards alone — use litestar-auth-guards.

From plugin
litestar
1362 skills1 agent1 hook
Install
$ npx -y skills add litestar-org/litestar-skills --skill litestar-security --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/litestar-security

Context preview

The summary Claude sees to decide when to auto-load this skill.

Auto-activate for litestar_security, SecurityPlugin, SecurityConfig, CurrentUser, Principal, SecurityContext, requires_role, requires_scope, requires_authenticated, requires_tenant, or requires_capability. Not for raw auth guards alone — use litestar-auth-guards.

SKILL.md

litestar-security.SKILL.md
name: litestar-security
description: "Auto-activate for litestar_security, SecurityPlugin, SecurityConfig, CurrentUser, Principal, SecurityContext, requires_role, requires_scope, requires_authenticated, requires_tenant, or requires_capability. Not for raw auth guards alone — use litestar-auth-guards."

Litestar Security

`litestar-security` 0.3.0 is a declarative authentication and authorization framework for Litestar. It provides credential slots and mechanisms, unified session management, local accounts, MFA, WebAuthn passkeys, OAuth/OIDC, API keys, workload JWTs, and browser hardening.

Two separate axes, wired through two separate Litestar keywords:

  • **Authentication** — *who is calling* — is a policy on `auth=` (or `opt={"auth": ...}`).
  • **Authorization** — *what they may do* — is a predicate in Litestar's native `guards=[...]`.

Do not conflate them: the policy helpers (`public`, `required`, `any_of`, `all_of`, `at_least`) take **mechanism names**, while the guard combinators (`guard_any_of`, `guard_all_of`, `guard_at_least`, `guard_one_of`) take **predicates**.

Code Style Rules

  • **Declare authentication with `auth=`.** Put policy on the route, or on a router/controller/app through `opt={"auth": ...}`. The nearest native owner wins.
  • **Keep authorization in `guards=[...]`.** Litestar's `security=` parameter is reserved for the OpenAPI requirements projected from `auth`.
  • **Inject the user with `CurrentUser[T]`.** Use `NamedDependency[CurrentUser[UserType]]`; it rejects anonymous and userless service principals. `principal` and `security_context` stay typed on public routes too.
  • **Authorize from the snapshot.** Guards read the `AuthorizationSnapshot` produced by the configured `authorization_resolver`. Never query the database inside a guard.
  • **Exclude other plugins' routes by path.** Static assets and dashboards carry no `auth` and compile to implicit `required()`, so they answer `401` until listed in `SecurityConfig(exclude=[...])`.
  • **Secure WebSockets with connect tokens.** Browsers cannot set handshake headers; mint a short-lived token over authenticated HTTP.
  • **Load protector keys from a secret store.** MFA and OAuth protectors need application-owned 32-byte AES-256-GCM keys, never source literals.

Quick Reference

Plugin Registration

from litestar import Litestar, get
from litestar.di import NamedDependency

from litestar_security import (
    SecurityConfig,
    SecurityContext,
    SecurityPlugin,
    public,
)


@get("/", auth=public(), sync_to_thread=False)
def index(security_context: NamedDependency[SecurityContext]) -> dict[str, bool]:
    return {"authenticated": bool(security_context.evidence)}


app = Litestar(
    route_handlers=[index],
    plugins=[SecurityPlugin(SecurityConfig())],
)

With mechanisms configured and no inherited policy, routes default to implicit `required()`. With no mechanisms at all they are public.

Authentication Policy

from litestar import Controller, get
from litestar_security import all_of, any_of, at_least, public, required

required()  # any configured mechanism
required("session")  # one named mechanism
any_of("session", "api_key")  # either
all_of("api_key", "workload_jwt")  # both, same subject
at_least(2, "session", "api_key", "passkey")  # N of M
public()  # no authentication, excluded from native CSRF

Apply it at whichever layer owns the decision:

@get("/health", auth=public())
async def health() -> dict[str, str]:
    return {"status": "ok"}


class AccountController(Controller):
    opt = {"auth": required("session")}

Custom controller class attributes are not propagated by Litestar — policy must live in `opt`, or use the typed `SecureController` / `PublicController` base classes.

Authorization Guards

from litestar import Controller, get
from litestar_security import guard_any_of, requires_role, requires_scope


class ReportsController(Controller):
    path = "/reports"
    opt = {"auth": required("session")}
    guards = [requires_role("analyst")]

    @get("/", guards=[guard_any_of(requires_scope("read:all"), requires_scope("read:reports"))])
    async def list_reports(self) -> list[dict[str, str]]: ...

Reserved Dependency Names

The plugin registers these; do not shadow them.

| Key | Type | Use | | --- | --- | --- | | `principal` | `Principal` | Stable envelope identity plus the active user model | | `security_context` | `SecurityContext` | Active session, evidence, snapshot, and restrictions | | `current_user` | `CurrentUser[User]` | Narrowing shortcut; rejects anonymous and service principals | | `websocket_connect_tokens` | `WebSocketConnectTokenService` | WebSocket connect-token manager |

Status Code Contract

| Outcome | Status | | --- | --- | | Authentication failure | `401` | | Guard denial | `403` | | Verification unavailable (fails closed) | `503` |

<workflow>

Workflow

Step 1: Install the capabilities in use

Core install covers JWT/JWKS validation, API keys, IAP, and OIDC token verification. Add an extra only for what the application uses: `[mfa]`, `[passkeys]`, `[oauth]`, `[argon2]`, or `[all]`.

Step 2: Choose providers

Pick where identity is established — local accounts, OAuth/OIDC, Google IAP, API keys, or workload JWTs. Adding a provider makes its mechanism available; route policy decides where it is accepted. See [Providers](references/providers.md).

Step 3: Implement the authorization resolver

Write a callable taking the authenticated `Principal` and returning an `AuthorizationSnapshot` of granted roles, scopes, capabilities, teams, and tenants. It runs once per request, which is why guards must not perform I/O.

from litestar_security import AuthorizationSnapshot, Principal


async def resolve_user_authorization(principal: Principal[User]) -> AuthorizationSnapshot:
    if not principal.is_authenticated:
        return AuthorizationSnapshot()
    user = principal.
Read more
Ships withlitestar

Opinionated, first-party agent skills, plugins, subagents, slash commands, and MCP servers for the Litestar framework and its ecosystem — publishable to every major AI agent and IDE from a single repo.

Get the whole plugin, auto-invoked
Stats
13
Stars
0
Views
0
Forks
Active
Maintenance
Python
Language
MIT
License
18h ago
Last commit
3mo ago
Created

Repo: litestar-org/litestar-skills