Additional claims

You can store additional information in access, refresh, or custom tokens and read it later from protected endpoints.

Pass a dictionary through the user_claims parameter of create_access_token(), create_refresh_token(), or create_token(), then read it back with get_token_payload().

Storing data in tokens can reduce repeated database lookups, but you still need to choose those claims carefully.

user_claims is only for custom application data. Reserved top-level claims such as sub, type, jti, exp, nbf, iat, iss, aud, and fresh cannot be overridden there.

Use the dedicated parameters instead:

  • subject= for sub
  • fresh= for access-token freshness
  • audience= for aud
  • issuer= for iss
  • expires_time= for exp
  • create_token(type="...") for custom token types

When using the public purpose, the token payload is signed but not encrypted. Anyone with the token can read its contents, so do not store sensitive information there. Whether local tokens are appropriate for sensitive data is still your own security decision.

from fastapi import FastAPI, HTTPException, Depends, Request
from fastapi.responses import JSONResponse
from fastapi_paseto import AuthPASETO
from fastapi_paseto.exceptions import AuthPASETOException
from pydantic import BaseModel

app = FastAPI()


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")

    # user_claims is for application-specific claims only. Reserved top-level
    # claims such as sub, exp, iss, aud, and jti have dedicated parameters.
    extra_claims = {"foo": ["fiz", "baz"]}
    access_token = Authorize.create_access_token(
        subject=user.username, user_claims=extra_claims
    )
    return {"access_token": access_token}


# In protected route, get the claims you added to the paseto with the
# get_token_payload() method
@app.get("/claims")
def user(Authorize: AuthPASETO = Depends()):
    Authorize.paseto_required()

    foo_claims = Authorize.get_token_payload()["foo"]
    return {"foo": foo_claims}