Skip to content

Platform Integration

This page is for service authors wiring authentication into Aetos applications. It covers both supported integration paths.

Path 1: jwtlib client (py-jwt)

Services that depend on the py-jwt library can authenticate requests without an OpenAPI generator. Set the auth server base URL:

export JWT_SERVER=http://auth.aetoskia.com

Then verify incoming requests:

1
2
3
4
5
6
7
8
from jwtlib.introspection import authenticate_request

authorized = await authenticate_request(
    should_skip_authentication,  # e.g. allow public paths
    method,
    path,
    authorization_token,         # "Bearer <jwt>" or None
)

authenticate_request POSTs {"token": "<jwt>"} to {JWT_SERVER}/introspect (3 second timeout) and treats {"active": true, "user": {...}} as valid. Transport errors surface as AuthServiceUnavailable.

For zero-request validation (offline token decode), jwtlib also exposes the token payload helpers used by the auth server itself — see the py-jwt documentation.

Path 2: openapi-first generated dependencies

Services declared with an OpenAPI-first contract can generate their FastAPI dependencies from the spec. Declare a bearer security scheme pointing at the auth server:

1
2
3
4
5
6
securitySchemes:
  HTTPBearer:
    type: http
    scheme: bearer
    x-server-url: https://auth.aetoskia.com
    x-introspect-path: /introspect

The generated dependency then POSTs {"token": token} to the introspection path and returns the user on active == true, raising 401 on invalid or inactive tokens and 503 when the auth server is unreachable.

The /introspect contract

Field Type Description
request token (string) The JWT to verify
response active (bool) Whether the token is valid and active
response user (PublicUser | null) The profile when active

The endpoint always answers 200 — validity is expressed through active. IntrospectResponse never raises, so the caller can act on the tri-state (valid / invalid / user missing) without exception handling.

Protecting endpoints in FastAPI

For first-party services, mount the auth router's dependency directly:

1
2
3
4
5
6
7
from fastapi import Depends
from jwtlib import PublicUser
from jwt import get_current_user

@app.get("/profile")
async def profile(current_user: PublicUser = Depends(get_current_user)):
    return current_user

Golden rules

  1. Never trust an unverified token — always decode through jwtlib or introspect before handling the request.
  2. Treat active: false as unauthenticated, even if the JWT decodes.
  3. Do not implement your own JWT parsing — use a generated dependency or the jwtlib client so revocation and issuer changes stay centralized.