Footers and Assertions
FastAPI PASETO can carry optional PASETO footers and verify implicit assertions when you need stronger token binding than payload claims alone.
from fastapi import Depends, FastAPI, HTTPException, Request
from fastapi.responses import JSONResponse
from pydantic import BaseModel
from fastapi_paseto import AuthPASETO
from fastapi_paseto.exceptions import AuthPASETOException
app = FastAPI()
IMPLICIT_ASSERTION = "tenant-alpha"
class User(BaseModel):
username: str
password: str
@AuthPASETO.load_config
def get_config():
return {"authpaseto_secret_key": "secret"}
@app.exception_handler(AuthPASETOException)
def authpaseto_exception_handler(request: Request, exc: AuthPASETOException):
return JSONResponse(status_code=exc.status_code, content={"detail": exc.message})
@app.post("/login")
def login(user: User, Authorize: AuthPASETO = Depends()):
if user.username != "test" or user.password != "test":
raise HTTPException(status_code=401, detail="Bad username or password")
access_token = Authorize.create_access_token(
subject=user.username,
footer={"kid": "k4.lid.demo"},
)
bound_token = Authorize.create_access_token(
subject=user.username,
implicit_assertion=IMPLICIT_ASSERTION,
)
return {"access_token": access_token, "bound_token": bound_token}
@app.get("/footer")
def footer(Authorize: AuthPASETO = Depends()):
Authorize.paseto_required()
return {
"footer": Authorize.get_token_footer(),
"payload": Authorize.get_token_payload(),
}
@app.get("/bound")
def bound(Authorize: AuthPASETO = Depends()):
Authorize.paseto_required(implicit_assertion=IMPLICIT_ASSERTION)
return {"user": Authorize.get_subject()}
What They Are¶
- Footer
- Extra authenticated data attached to the token outside the payload. A footer travels with the token and is protected by PASETO integrity checks, but it is not meant for confidential application data.
- Implicit assertion
- Extra authenticated data that does not travel inside the token at all. The same value must be supplied again at verification time or validation fails.
In practice:
- Put application claims you want to read later in the payload.
- Put non-secret token metadata you want attached to the token in the footer.
- Put request-bound context that should never be embedded in the token in the implicit assertion.
Footers¶
PASETO footers are useful for metadata such as:
kidvalues for key selection- routing or tenant hints
-
integration metadata that should stay outside the payload
-
Pass
footer=tocreate_access_token(),create_refresh_token(), orcreate_token()to include an optional PASETO footer. - After
paseto_required()succeeds, callget_token_footer()to read the decoded footer. - Footer data is authenticated by PASETO, but for
publictokens it remains visible to anyone holding the token.
Example:
token = Authorize.create_access_token(
subject="alice",
footer={"kid": "k4.lid.primary"},
)
Authorize.paseto_required()
footer = Authorize.get_token_footer()
Use a footer when the metadata belongs to the token itself and can safely travel with it.
Implicit Assertions¶
Implicit assertions are useful when the token must be bound to external context such as:
- a tenant identifier chosen by the server
- a channel or transport binding
-
a deployment- or service-specific contract
-
Pass
implicit_assertion=when creating a token. - Pass the same
implicit_assertion=value topaseto_required()when validating it. - If the assertion is missing or mismatched, token validation fails.
Example:
token = Authorize.create_access_token(
subject="alice",
implicit_assertion="tenant-alpha",
)
Authorize.paseto_required(implicit_assertion="tenant-alpha")
Use an implicit assertion when the value should influence verification but should not be readable from the token or transported inside it.
Choosing Between Them¶
Choose a footer when:
- the verifier needs to read the metadata from the token itself
- the value can safely travel with the token
Choose an implicit assertion when:
- the verifier already knows the value from surrounding context
- the value should not be embedded into or exposed by the token
Do not use either one for ordinary application claims such as user roles, permissions, or profile data. Those belong in the token payload.