From a115df113d6ef913727a37ab824faf888556943b Mon Sep 17 00:00:00 2001 From: Vishesh 'ironeagle' Bangotra Date: Wed, 16 Sep 2026 19:51:24 +0530 Subject: [PATCH] chore: collect auth-server wiki and lib refresh Picks up the rewritten auth-server wiki (platform anatomy theme) and the regenerated lib artifacts, including the new pep-typed marker bounce. --- auth-server/lib/jwt/app/index.html | 34 +---- auth-server/lib/jwt/index.html | 10 +- auth-server/lib/search/search_index.json | 2 +- auth-server/lib/sitemap.xml.gz | Bin 127 -> 127 bytes .../wiki/01_centralized_auth/index.html | 36 +++-- auth-server/wiki/02_how_to_use/index.html | 41 ++++-- .../wiki/03_platform_integration/index.html | 41 ++++-- auth-server/wiki/04_deployment/index.html | 41 ++++-- auth-server/wiki/05_development/index.html | 51 +++++-- auth-server/wiki/index.html | 129 ++++++++++-------- auth-server/wiki/search/search_index.json | 2 +- auth-server/wiki/sitemap.xml.gz | Bin 127 -> 127 bytes 12 files changed, 233 insertions(+), 154 deletions(-) diff --git a/auth-server/lib/jwt/app/index.html b/auth-server/lib/jwt/app/index.html index 7a12fb5..a24bb13 100644 --- a/auth-server/lib/jwt/app/index.html +++ b/auth-server/lib/jwt/app/index.html @@ -664,11 +664,7 @@ password or token handling is implemented here.

-
1
-2
-3
create_user(
-    user: RegisterRequest = Body(...),
-) -> PublicUser
+
create_user(user: RegisterRequest = Body(...)) -> PublicUser
 
@@ -746,15 +742,7 @@ and password (minimum 6 characters).

-
1
-2
-3
-4
-5
get_current_user(
-    credentials: (
-        HTTPAuthorizationCredentials | None
-    ) = Depends(bearer_scheme),
-) -> PublicUser
+
get_current_user(credentials: HTTPAuthorizationCredentials | None = Depends(bearer_scheme)) -> PublicUser
 
@@ -858,11 +846,7 @@ the credentials are missing or the token is not valid.

-
1
-2
-3
introspect(
-    body: IntrospectRequest = Body(...),
-) -> IntrospectResponse
+
introspect(body: IntrospectRequest = Body(...)) -> IntrospectResponse
 
@@ -1038,11 +1022,7 @@ credentials do not match.

-
1
-2
-3
logout(
-    _: PublicUser = Depends(get_current_user),
-) -> LogoutResponse
+
logout(_: PublicUser = Depends(get_current_user)) -> LogoutResponse
 
@@ -1119,11 +1099,7 @@ the access token.

-
1
-2
-3
read_users_me(
-    current_user: PublicUser = Depends(get_current_user),
-) -> PublicUser
+
read_users_me(current_user: PublicUser = Depends(get_current_user)) -> PublicUser
 
diff --git a/auth-server/lib/jwt/index.html b/auth-server/lib/jwt/index.html index 2f788c5..21d47b8 100644 --- a/auth-server/lib/jwt/index.html +++ b/auth-server/lib/jwt/index.html @@ -619,15 +619,7 @@ comes from mongo_ops.

-
1
-2
-3
-4
-5
get_current_user(
-    credentials: (
-        HTTPAuthorizationCredentials | None
-    ) = Depends(bearer_scheme),
-) -> PublicUser
+
get_current_user(credentials: HTTPAuthorizationCredentials | None = Depends(bearer_scheme)) -> PublicUser
 
diff --git a/auth-server/lib/search/search_index.json b/auth-server/lib/search/search_index.json index 617c434..f9bbc8a 100644 --- a/auth-server/lib/search/search_index.json +++ b/auth-server/lib/search/search_index.json @@ -1 +1 @@ -{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"jwt","text":""},{"location":"#modules","title":"Modules","text":"
  • Jwt
"},{"location":"jwt/","title":"Jwt","text":"
  • App
"},{"location":"jwt/#jwt","title":"jwt","text":""},{"location":"jwt/#jwt--summary","title":"Summary","text":"

The jwt package is the HTTP surface of the Aetoskia Auth Service.

It declares the FastAPI router that exposes the authentication endpoints (/register, /login, /me, /logout, /introspect) and the get_current_user bearer-token dependency used to protect routes.

All user management, hashing, and token logic is delegated to the :mod:jwtlib package (see the py-jwt project), while MongoDB persistence comes from mongo_ops.

"},{"location":"jwt/#jwt--quick-start","title":"Quick start","text":"

Wire the router into an application:

from fastapi import FastAPI\nimport jwt\n\napp = FastAPI()\napp.include_router(jwt.router)\n

Protect a route with the current user:

from fastapi import Depends\nfrom jwtlib import PublicUser\nfrom jwt import get_current_user\n\n@app.get(\"/profile\")\nasync def profile(current_user: PublicUser = Depends(get_current_user)):\n    return current_user\n
"},{"location":"jwt/#jwt--notes","title":"Notes","text":"
  • The router mounts with an empty prefix and the Auth tag.
  • get_current_user raises 401 with WWW-Authenticate: Bearer when the header is missing or the token cannot be validated.
"},{"location":"jwt/#jwt-functions","title":"Functions","text":""},{"location":"jwt/#jwt.get_current_user","title":"get_current_user async","text":"
get_current_user(\n    credentials: (\n        HTTPAuthorizationCredentials | None\n    ) = Depends(bearer_scheme),\n) -> PublicUser\n

Resolve the authenticated user from the bearer credentials.

Decodes the JWT via get_logged_in_user and returns the matching public user profile. Any decoding, validity, or lookup failure produces the same generic 401 response so that the endpoint does not leak token internals.

Parameters:

Name Type Description Default credentials HTTPAuthorizationCredentials | None

Bearer credentials extracted from the Authorization header, or None when the header is absent.

Depends(bearer_scheme)

Returns:

Name Type Description PublicUser PublicUser

The public profile of the authenticated user.

Raises:

Type Description HTTPException

With status 401 and header WWW-Authenticate: Bearer when the credentials are missing or the token is not valid.

"},{"location":"jwt/app/","title":"App","text":""},{"location":"jwt/app/#jwt.app","title":"jwt.app","text":""},{"location":"jwt/app/#jwt.app--summary","title":"Summary","text":"

HTTP routes for the Aetoskia Auth Service.

This module assembles the authentication endpoint set: user registration, login (JWT issuance), current-user lookup, stateless logout, and the internal service-to-service token introspection endpoint. It also provides the get_current_user FastAPI dependency that decodes the bearer token and resolves the authenticated user.

The module is a thin FastAPI layer over the jwtlib application logic; no password or token handling is implemented here.

"},{"location":"jwt/app/#jwt.app--notes","title":"Notes","text":"
  • /introspect is tagged Internal and is consumed by other services via jwtlib.introspection or the openapi-first generated dependencies.
  • Logout is stateless: no server-side token invalidation is performed.
"},{"location":"jwt/app/#jwt.app-functions","title":"Functions","text":""},{"location":"jwt/app/#jwt.app.create_user","title":"create_user async","text":"
create_user(\n    user: RegisterRequest = Body(...),\n) -> PublicUser\n

Register a new user account.

The password is hashed server side and the returned profile never contains the password.

Parameters:

Name Type Description Default user RegisterRequest

Registration payload containing username, optional email, and password (minimum 6 characters).

Body(...)

Returns:

Name Type Description PublicUser PublicUser

The created public user profile.

"},{"location":"jwt/app/#jwt.app.get_current_user","title":"get_current_user async","text":"
get_current_user(\n    credentials: (\n        HTTPAuthorizationCredentials | None\n    ) = Depends(bearer_scheme),\n) -> PublicUser\n

Resolve the authenticated user from the bearer credentials.

Decodes the JWT via get_logged_in_user and returns the matching public user profile. Any decoding, validity, or lookup failure produces the same generic 401 response so that the endpoint does not leak token internals.

Parameters:

Name Type Description Default credentials HTTPAuthorizationCredentials | None

Bearer credentials extracted from the Authorization header, or None when the header is absent.

Depends(bearer_scheme)

Returns:

Name Type Description PublicUser PublicUser

The public profile of the authenticated user.

Raises:

Type Description HTTPException

With status 401 and header WWW-Authenticate: Bearer when the credentials are missing or the token is not valid.

"},{"location":"jwt/app/#jwt.app.introspect","title":"introspect async","text":"
introspect(\n    body: IntrospectRequest = Body(...),\n) -> IntrospectResponse\n

Introspect a JWT for other microservices.

Verifies the token and returns the user only when it is active and valid.

Parameters:

Name Type Description Default body IntrospectRequest

Request containing the token to verify.

Body(...)

Returns:

Name Type Description IntrospectResponse IntrospectResponse

Always a 200 response with active and, when valid, the public user profile.

"},{"location":"jwt/app/#jwt.app.login","title":"login async","text":"
login(user: LoginRequest = Body(...)) -> LoginResponse\n

Authenticate a user and issue a JWT access token.

Parameters:

Name Type Description Default user LoginRequest

Login payload containing username and password.

Body(...)

Returns:

Name Type Description LoginResponse LoginResponse

The issued access token together with the public user profile.

Raises:

Type Description HTTPException

With status 401 and detail Invalid credentials when the credentials do not match.

"},{"location":"jwt/app/#jwt.app.logout","title":"logout async","text":"
logout(\n    _: PublicUser = Depends(get_current_user),\n) -> LogoutResponse\n

Log out the current user (stateless).

No server-side token invalidation is performed; the client must discard the access token.

Parameters:

Name Type Description Default _ PublicUser

The authenticated user (validates the bearer token).

Depends(get_current_user)

Returns:

Name Type Description LogoutResponse LogoutResponse

A message instructing the client to discard the token.

"},{"location":"jwt/app/#jwt.app.read_users_me","title":"read_users_me async","text":"
read_users_me(\n    current_user: PublicUser = Depends(get_current_user),\n) -> PublicUser\n

Return the currently authenticated user's public profile.

Parameters:

Name Type Description Default current_user PublicUser

The authenticated user resolved by the bearer dependency.

Depends(get_current_user)

Returns:

Name Type Description PublicUser PublicUser

The public profile of the requesting user.

"}]} \ No newline at end of file +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"jwt","text":""},{"location":"#modules","title":"Modules","text":"
  • Jwt
"},{"location":"jwt/","title":"Jwt","text":"
  • App
"},{"location":"jwt/#jwt","title":"jwt","text":""},{"location":"jwt/#jwt--summary","title":"Summary","text":"

The jwt package is the HTTP surface of the Aetoskia Auth Service.

It declares the FastAPI router that exposes the authentication endpoints (/register, /login, /me, /logout, /introspect) and the get_current_user bearer-token dependency used to protect routes.

All user management, hashing, and token logic is delegated to the :mod:jwtlib package (see the py-jwt project), while MongoDB persistence comes from mongo_ops.

"},{"location":"jwt/#jwt--quick-start","title":"Quick start","text":"

Wire the router into an application:

from fastapi import FastAPI\nimport jwt\n\napp = FastAPI()\napp.include_router(jwt.router)\n

Protect a route with the current user:

from fastapi import Depends\nfrom jwtlib import PublicUser\nfrom jwt import get_current_user\n\n@app.get(\"/profile\")\nasync def profile(current_user: PublicUser = Depends(get_current_user)):\n    return current_user\n
"},{"location":"jwt/#jwt--notes","title":"Notes","text":"
  • The router mounts with an empty prefix and the Auth tag.
  • get_current_user raises 401 with WWW-Authenticate: Bearer when the header is missing or the token cannot be validated.
"},{"location":"jwt/#jwt-functions","title":"Functions","text":""},{"location":"jwt/#jwt.get_current_user","title":"get_current_user async","text":"
get_current_user(credentials: HTTPAuthorizationCredentials | None = Depends(bearer_scheme)) -> PublicUser\n

Resolve the authenticated user from the bearer credentials.

Decodes the JWT via get_logged_in_user and returns the matching public user profile. Any decoding, validity, or lookup failure produces the same generic 401 response so that the endpoint does not leak token internals.

Parameters:

Name Type Description Default credentials HTTPAuthorizationCredentials | None

Bearer credentials extracted from the Authorization header, or None when the header is absent.

Depends(bearer_scheme)

Returns:

Name Type Description PublicUser PublicUser

The public profile of the authenticated user.

Raises:

Type Description HTTPException

With status 401 and header WWW-Authenticate: Bearer when the credentials are missing or the token is not valid.

"},{"location":"jwt/app/","title":"App","text":""},{"location":"jwt/app/#jwt.app","title":"jwt.app","text":""},{"location":"jwt/app/#jwt.app--summary","title":"Summary","text":"

HTTP routes for the Aetoskia Auth Service.

This module assembles the authentication endpoint set: user registration, login (JWT issuance), current-user lookup, stateless logout, and the internal service-to-service token introspection endpoint. It also provides the get_current_user FastAPI dependency that decodes the bearer token and resolves the authenticated user.

The module is a thin FastAPI layer over the jwtlib application logic; no password or token handling is implemented here.

"},{"location":"jwt/app/#jwt.app--notes","title":"Notes","text":"
  • /introspect is tagged Internal and is consumed by other services via jwtlib.introspection or the openapi-first generated dependencies.
  • Logout is stateless: no server-side token invalidation is performed.
"},{"location":"jwt/app/#jwt.app-functions","title":"Functions","text":""},{"location":"jwt/app/#jwt.app.create_user","title":"create_user async","text":"
create_user(user: RegisterRequest = Body(...)) -> PublicUser\n

Register a new user account.

The password is hashed server side and the returned profile never contains the password.

Parameters:

Name Type Description Default user RegisterRequest

Registration payload containing username, optional email, and password (minimum 6 characters).

Body(...)

Returns:

Name Type Description PublicUser PublicUser

The created public user profile.

"},{"location":"jwt/app/#jwt.app.get_current_user","title":"get_current_user async","text":"
get_current_user(credentials: HTTPAuthorizationCredentials | None = Depends(bearer_scheme)) -> PublicUser\n

Resolve the authenticated user from the bearer credentials.

Decodes the JWT via get_logged_in_user and returns the matching public user profile. Any decoding, validity, or lookup failure produces the same generic 401 response so that the endpoint does not leak token internals.

Parameters:

Name Type Description Default credentials HTTPAuthorizationCredentials | None

Bearer credentials extracted from the Authorization header, or None when the header is absent.

Depends(bearer_scheme)

Returns:

Name Type Description PublicUser PublicUser

The public profile of the authenticated user.

Raises:

Type Description HTTPException

With status 401 and header WWW-Authenticate: Bearer when the credentials are missing or the token is not valid.

"},{"location":"jwt/app/#jwt.app.introspect","title":"introspect async","text":"
introspect(body: IntrospectRequest = Body(...)) -> IntrospectResponse\n

Introspect a JWT for other microservices.

Verifies the token and returns the user only when it is active and valid.

Parameters:

Name Type Description Default body IntrospectRequest

Request containing the token to verify.

Body(...)

Returns:

Name Type Description IntrospectResponse IntrospectResponse

Always a 200 response with active and, when valid, the public user profile.

"},{"location":"jwt/app/#jwt.app.login","title":"login async","text":"
login(user: LoginRequest = Body(...)) -> LoginResponse\n

Authenticate a user and issue a JWT access token.

Parameters:

Name Type Description Default user LoginRequest

Login payload containing username and password.

Body(...)

Returns:

Name Type Description LoginResponse LoginResponse

The issued access token together with the public user profile.

Raises:

Type Description HTTPException

With status 401 and detail Invalid credentials when the credentials do not match.

"},{"location":"jwt/app/#jwt.app.logout","title":"logout async","text":"
logout(_: PublicUser = Depends(get_current_user)) -> LogoutResponse\n

Log out the current user (stateless).

No server-side token invalidation is performed; the client must discard the access token.

Parameters:

Name Type Description Default _ PublicUser

The authenticated user (validates the bearer token).

Depends(get_current_user)

Returns:

Name Type Description LogoutResponse LogoutResponse

A message instructing the client to discard the token.

"},{"location":"jwt/app/#jwt.app.read_users_me","title":"read_users_me async","text":"
read_users_me(current_user: PublicUser = Depends(get_current_user)) -> PublicUser\n

Return the currently authenticated user's public profile.

Parameters:

Name Type Description Default current_user PublicUser

The authenticated user resolved by the bearer dependency.

Depends(get_current_user)

Returns:

Name Type Description PublicUser PublicUser

The public profile of the requesting user.

"}]} \ No newline at end of file diff --git a/auth-server/lib/sitemap.xml.gz b/auth-server/lib/sitemap.xml.gz index e496a0d39e2d89445c665e87a8c93f68e7f55814..89851db59432aa6d7a5d0fe339808593e07e45ef 100644 GIT binary patch delta 13 Ucmb=gXP58h;9$73aw2;L033S+RR910 delta 13 Ucmb=gXP58h;AnWhbRv5N03V_R+yDRo diff --git a/auth-server/wiki/01_centralized_auth/index.html b/auth-server/wiki/01_centralized_auth/index.html index 5df2a6d..dee7103 100644 --- a/auth-server/wiki/01_centralized_auth/index.html +++ b/auth-server/wiki/01_centralized_auth/index.html @@ -412,7 +412,7 @@
  • - The identity model + 🧬 The identity model @@ -421,7 +421,7 @@
  • - Token contract + 🎟️ Token contract @@ -430,7 +430,7 @@
  • - How the ecosystem trusts the server + 🀝 How the ecosystem trusts the server @@ -439,7 +439,16 @@
  • - Benefits + πŸ’‘ Benefits + + + +
  • + +
  • + + + πŸ“š Read Next @@ -557,11 +566,12 @@ -

    Centralized Authentication

    +

    πŸ”— Centralized Authentication

    The Aetoskia Auth Server acts as the single identity provider for every application in the Aetos Platform ecosystem. The model is deliberately small and uniform.

    -

    The identity model

    +
    +

    🧬 The identity model

     1
      2
      3
    @@ -599,7 +609,8 @@ and uniform.

    client, and further use is prevented only by expiry or revocation through introspection-driven policies. -

    Token contract

    +
    +

    🎟️ Token contract

    A valid access token is an HS256 JWT with exactly two claims:

    1
     2
    @@ -615,7 +626,8 @@ and uniform.

    There are no scopes or roles inside the token; authorization decisions belong to the consuming service, while identity and authenticity belong here.

    -

    How the ecosystem trusts the server

    +
    +

    🀝 How the ecosystem trusts the server

    1. Users authenticate once via /login and receive a token.
    2. Services accept that token as proof of identity after verifying it @@ -626,13 +638,19 @@ to the consuming service, while identity and authenticity belong here.

    This keeps authentication centralized while leaving each service in control of its own authorization rules.

    -

    Benefits

    +
    +

    πŸ’‘ Benefits

    • New services onboard with a client library call, not a new auth system.
    • Credential storage, hashing, and issuance policies evolve in one place.
    • A single JWT_SECRET rotation strategy protects the whole platform.

    + + diff --git a/auth-server/wiki/02_how_to_use/index.html b/auth-server/wiki/02_how_to_use/index.html index f68e1a2..4aea674 100644 --- a/auth-server/wiki/02_how_to_use/index.html +++ b/auth-server/wiki/02_how_to_use/index.html @@ -434,7 +434,7 @@
  • - Register a user + πŸ‘€ Register a user @@ -443,7 +443,7 @@
  • - Log in to get a token + πŸ”‘ Log in to get a token @@ -452,7 +452,7 @@
  • - Call a protected endpoint + πŸ”’ Call a protected endpoint @@ -461,7 +461,7 @@
  • - Log out + πŸšͺ Log out @@ -470,7 +470,16 @@
  • - Token lifecycle quick reference + 🧭 Token lifecycle quick reference + + + +
  • + +
  • + + + πŸ“š Read Next @@ -566,10 +575,11 @@ -

    How to Use

    +

    πŸ–₯️ How to Use

    This page covers the plain HTTP usage of the auth server: creating users, logging in, and calling protected endpoints with a bearer token.

    -

    Register a user

    +
    +

    πŸ‘€ Register a user

    1
     2
     3
    curl -X POST http://localhost:8000/register \
    @@ -593,7 +603,8 @@ logging in, and calling protected endpoints with a bearer token.

    }

    The password is never returned.

    -

    Log in to get a token

    +
    +

    πŸ”‘ Log in to get a token

    1
     2
     3
    curl -X POST http://localhost:8000/login \
    @@ -618,7 +629,8 @@ logging in, and calling protected endpoints with a bearer token.

    }

    Invalid credentials return 401 with {"detail": "Invalid credentials"}.

    -

    Call a protected endpoint

    +
    +

    πŸ”’ Call a protected endpoint

    Send the token as a bearer token:

    curl http://localhost:8000/me \
    @@ -626,7 +638,8 @@ logging in, and calling protected endpoints with a bearer token.

    Response 200 OK with the current user profile. A missing or invalid token returns 401 with WWW-Authenticate: Bearer.

    -

    Log out

    +
    +

    πŸšͺ Log out

    curl -X POST http://localhost:8000/logout \
       -H "Authorization: Bearer <jwt>"
    @@ -635,7 +648,8 @@ returns 401 with WWW-Authenticate: Bearer.

    discard the token:

    { "message": "Successfully logged out. Please discard your token on the client." }
     
    -

    Token lifecycle quick reference

    +
    +

    🧭 Token lifecycle quick reference

    @@ -675,6 +689,11 @@ discard the token:

    Interactive examples are available in the API Reference site (Swagger UI), rendered from docs/api/openapi.json.


    + + diff --git a/auth-server/wiki/03_platform_integration/index.html b/auth-server/wiki/03_platform_integration/index.html index 4d7105b..bf6798e 100644 --- a/auth-server/wiki/03_platform_integration/index.html +++ b/auth-server/wiki/03_platform_integration/index.html @@ -456,7 +456,7 @@
  • - Path 1: jwtlib client (py-jwt) + 🧩 Path 1: jwtlib client (py-jwt) @@ -465,7 +465,7 @@
  • - Path 2: openapi-first generated dependencies + πŸ› οΈ Path 2: openapi-first generated dependencies @@ -474,7 +474,7 @@
  • - The /introspect contract + πŸ“‹ The /introspect contract @@ -483,7 +483,7 @@
  • - Protecting endpoints in FastAPI + 🐍 Protecting endpoints in FastAPI @@ -492,7 +492,16 @@
  • - Golden rules + ⚠️ Golden rules + + + +
  • + +
  • + + + πŸ“š Read Next @@ -566,10 +575,11 @@ -

    Platform Integration

    +

    πŸ”Œ 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)

    +
    +

    🧩 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
    @@ -598,7 +608,8 @@ without an OpenAPI generator. Set the auth server base URL:

    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

    +
    +

    πŸ› οΈ 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:

    @@ -617,7 +628,8 @@ at the auth server:

    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

    +
    +

    πŸ“‹ The /introspect contract

    @@ -647,7 +659,8 @@ inactive tokens and 503 when the auth server is unreachable.

    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

    +
    +

    🐍 Protecting endpoints in FastAPI

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

    1
     2
    @@ -663,7 +676,8 @@ tri-state (valid / invalid / user missing) without exception handling.

    async def profile(current_user: PublicUser = Depends(get_current_user)): return current_user
    -

    Golden rules

    +
    +

    ⚠️ Golden rules

    1. Never trust an unverified token β€” always decode through jwtlib or introspect before handling the request.
    2. @@ -672,6 +686,11 @@ tri-state (valid / invalid / user missing) without exception handling.

      the jwtlib client so revocation and issuer changes stay centralized.

    + + diff --git a/auth-server/wiki/04_deployment/index.html b/auth-server/wiki/04_deployment/index.html index f0b8f88..e83c3cc 100644 --- a/auth-server/wiki/04_deployment/index.html +++ b/auth-server/wiki/04_deployment/index.html @@ -478,7 +478,7 @@
  • - Environment variables + βš™οΈ Environment variables @@ -487,7 +487,7 @@
  • - Running locally + πŸ’» Running locally @@ -496,7 +496,7 @@
  • - Container image + 🐳 Container image @@ -505,7 +505,7 @@
  • - CI/CD (Drone) + πŸ”„ CI/CD (Drone) @@ -514,7 +514,16 @@
  • - Environments + 🌍 Environments + + + +
  • + +
  • + + + πŸ“š Read Next @@ -566,9 +575,10 @@ -

    Deployment

    +

    πŸš€ Deployment

    How the auth server is configured and shipped.

    -

    Environment variables

    +
    +

    βš™οΈ Environment variables

    @@ -619,13 +629,15 @@

    Credentials and the token secret live in the environment / Deploy secrets β€” see .env.example for the shape. .env is gitignored.

    -

    Running locally

    +
    +

    πŸ’» Running locally

    cp .env.example .env      # fill in MONGO_HOST, JWT_SECRET
     uvicorn main:app --reload --port 8000
     

    The health endpoint is available at GET /health.

    -

    Container image

    +
    +

    🐳 Container image

    The Dockerfile is a multi-stage build on python:3.13-slim:

    1. Builder installs requirements.txt from the private pip index using @@ -634,7 +646,8 @@ see .env.example for the shape. .env is gitignored.

      8000
      , and runs uvicorn main:app. A HEALTHCHECK curls /health.
    -

    CI/CD (Drone)

    +
    +

    πŸ”„ CI/CD (Drone)

    .drone.yml ships on git tag events (arm64):

    1. Resolve the latest tag.
    2. @@ -647,7 +660,8 @@ see .env.example for the shape. .env is gitignored.

      The deployed container runs with --restart always, maps host 9003 β†’ 8000, resolves private-pi to 192.168.1.111 for Mongo, and receives MONGO_* + JWT_SECRET from secrets.

      -

      Environments

      +
      +

      🌍 Environments

      @@ -671,6 +685,11 @@ see .env.example for the shape. .env is gitignored.


      + + diff --git a/auth-server/wiki/05_development/index.html b/auth-server/wiki/05_development/index.html index a9edef3..2f1e9ec 100644 --- a/auth-server/wiki/05_development/index.html +++ b/auth-server/wiki/05_development/index.html @@ -498,7 +498,7 @@
    3. - Repository layout + πŸ“‚ Repository layout @@ -507,7 +507,7 @@
    4. - Setup + πŸ”§ Setup @@ -516,7 +516,7 @@
    5. - Tests + πŸ§ͺ Tests @@ -525,7 +525,7 @@
    6. - Regenerating the OpenAPI spec + πŸ“œ Regenerating the OpenAPI spec @@ -534,7 +534,16 @@
    7. - Building documentation (docforge) + πŸ“ Building documentation (docforge) + + + +
    8. + +
    9. + + + πŸ“š Read Next @@ -564,9 +573,10 @@ -

      Development

      +

      πŸ› οΈ Development

      Working on the auth server itself.

      -

      Repository layout

      +
      +

      πŸ“‚ Repository layout

      @@ -605,7 +615,8 @@
      -

      Setup

      +
      +

      πŸ”§ Setup

      python -m venv .venv
       .venv/Scripts/pip install -r requirements.txt
      @@ -617,20 +628,23 @@ and the Dockerfile). Core runtime packages:

    10. mongo-ops==0.1.3 β€” MongoDB persistence layer
    11. fastapi, uvicorn, python-jose, passlib, bcrypt, pymongo
    12. -

      Tests

      +
      +

      πŸ§ͺ Tests

      Run the suite (no network or Mongo required β€” an in-memory mock is used):

      .venv/Scripts/pytest --asyncio-mode=auto
       

      Coverage spans the full HTTP flow: register β†’ login β†’ wrong-password 401 β†’ /me with and without a token β†’ stateless logout.

      -

      Regenerating the OpenAPI spec

      +
      +

      πŸ“œ Regenerating the OpenAPI spec

      The committed docs/api/openapi.json is produced offline:

      set MONGO_HOST=127.0.0.1
       python generate_spec.py
       

      MONGO_HOST only needs to be set for the import; no connection is opened.

      -

      Building documentation (docforge)

      +
      +

      πŸ“ Building documentation (docforge)

      The site is generated by docforge and served per kind under site/{kind}:

      1
      @@ -640,15 +654,21 @@ and served per kind under site/{kind}:

      5
      doc-forge build \
         --api --openapi-spec docs/api/openapi.json \
         --mkdocs --wiki \
      -  --module-is-source --module jwt \
      +  --module jwt \
         --site-name "Aetoskia Auth Server"
       
      • --api renders openapi.json with Swagger UI.
      • -
      • --mkdocs renders the library reference from jwt docstrings.
      • +
      • --mkdocs renders the library reference from the jwt package docstrings + (nested under docs/lib/jwt/, matching docforge.nav.yml).
      • --wiki builds this wiki.
      • Navigation layout is defined in docforge.nav.yml.
      +
      +

      The jwt module is rendered without --module-is-source so the library +output stays nested under docs/lib/jwt/, matching the committed +docs/mkdocs.lib.yml nav.

      +

      Preview locally:

      1
       2
      @@ -657,6 +677,11 @@ and served per kind under site/{kind}:

      doc-forge serve --wiki

      + + diff --git a/auth-server/wiki/index.html b/auth-server/wiki/index.html index 6b46c53..5b64602 100644 --- a/auth-server/wiki/index.html +++ b/auth-server/wiki/index.html @@ -70,7 +70,7 @@
      - + Skip to content @@ -386,18 +386,9 @@
      • - + - Why centralize authentication? - - - -
      • - -
      • - - - Sections + πŸš€ Key Features @@ -406,16 +397,25 @@
      • - Endpoints at a glance + ⚑ Endpoints at a Glance
      • - + - Service identity + πŸ“ Documentation Structure + + + +
      • + +
      • + + + πŸ”— Related Resources @@ -555,52 +555,29 @@ -

        Aetoskia Auth Server

        +

        πŸ” Aetoskia Auth Server β€” Central Identity for the Aetos Platform

        The Aetoskia Auth Server is the central identity service of the Aetos Platform ecosystem. It issues, validates, and introspects short-lived JWT access tokens against a single shared user store backed by MongoDB, so every service can trust one issuer instead of shipping its own auth logic.

        -

        Why centralize authentication?

        +
        +

        Doc model: this wiki is written for humans β€” how‑to guides, examples, +and deployment recipes. The authoritative API contracts live in the code +(GSDFC docstrings) and the interactive OpenAPI reference under docs/api/.

        +
        +
        +

        πŸš€ Key Features

          -
        • Single source of identity β€” one user database, one issuer, one secret.
        • -
        • Uniform token contract β€” every service verifies the same HS256 JWT.
        • -
        • No auth code duplication β€” services delegate with jwtlib or a - generated OpenAPI dependency.
        • -
        • Instant revocation surface β€” introspection gives services a live - active check rather than trusting expiry alone.
        • +
        • πŸ”‘ Centralized identity β€” one user database, one issuer, one secret
        • +
        • 🎟️ Uniform token contract β€” every service verifies the same HS256 JWT
        • +
        • 🧩 No auth code duplication β€” services delegate with jwtlib or a + generated OpenAPI dependency
        • +
        • ⚑ Instant revocation surface β€” /introspect gives services a live + active check rather than trusting expiry alone
        • +
        • πŸ”“ Stateless logout β€” no server-side sessions; the client discards the token
        -

        Sections

        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        SectionWhat you'll find
        Centralized AuthThe identity model and how the ecosystem trusts the server
        How to UseRegister, login, and call endpoints with tokens
        Platform IntegrationHow services authenticate requests
        DeploymentEnvironment, Docker, and CI/CD
        DevelopmentLocal setup, tests, and regenerating the spec
        -

        Endpoints at a glance

        +
        +

        ⚑ Endpoints at a Glance

        @@ -642,13 +619,47 @@ service can trust one issuer instead of shipping its own auth logic.

        -

        Service identity

        +
        +

        πŸ“ Documentation Structure

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        SectionWhat you'll find
        Centralized AuthThe identity model and how the ecosystem trusts the server
        How to UseRegister, login, and call endpoints with tokens
        Platform IntegrationHow services authenticate requests
        DeploymentEnvironment, Docker, and CI/CD
        DevelopmentLocal setup, tests, and regenerating docs
        +
        +
          -
        • Title: Aetoskia Auth Server
        • -
        • Version: 0.0.5
        • -
        • API spec: docs/api/openapi.json (rendered in the API reference site)
        • +
        • Source Code: Gitea Repository
        • +
        • API Reference: interactive Swagger UI rendered from docs/api/openapi.json
        • +
        • CI/CD: Drone pipeline ships tagged releases as aetos/auth-server images

        +

        Β© Aetoskia Internal β€” auth-server 0.0.5

        diff --git a/auth-server/wiki/search/search_index.json b/auth-server/wiki/search/search_index.json index d94417c..fcfe96f 100644 --- a/auth-server/wiki/search/search_index.json +++ b/auth-server/wiki/search/search_index.json @@ -1 +1 @@ -{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Aetoskia Auth Server","text":"

        The Aetoskia Auth Server is the central identity service of the Aetos Platform ecosystem. It issues, validates, and introspects short-lived JWT access tokens against a single shared user store backed by MongoDB, so every service can trust one issuer instead of shipping its own auth logic.

        "},{"location":"#why-centralize-authentication","title":"Why centralize authentication?","text":"
        • Single source of identity \u2014 one user database, one issuer, one secret.
        • Uniform token contract \u2014 every service verifies the same HS256 JWT.
        • No auth code duplication \u2014 services delegate with jwtlib or a generated OpenAPI dependency.
        • Instant revocation surface \u2014 introspection gives services a live active check rather than trusting expiry alone.
        "},{"location":"#sections","title":"Sections","text":"Section What you'll find Centralized Auth The identity model and how the ecosystem trusts the server How to Use Register, login, and call endpoints with tokens Platform Integration How services authenticate requests Deployment Environment, Docker, and CI/CD Development Local setup, tests, and regenerating the spec"},{"location":"#endpoints-at-a-glance","title":"Endpoints at a glance","text":"Method Path Purpose POST /register Create a user account POST /login Authenticate and issue a JWT GET /me Current user (Bearer) POST /logout Stateless logout (Bearer) POST /introspect Service-to-service token verification GET /health Health check"},{"location":"#service-identity","title":"Service identity","text":"
        • Title: Aetoskia Auth Server
        • Version: 0.0.5
        • API spec: docs/api/openapi.json (rendered in the API reference site)
        "},{"location":"01_centralized_auth/","title":"Centralized Authentication","text":"

        The Aetoskia Auth Server acts as the single identity provider for every application in the Aetos Platform ecosystem. The model is deliberately small and uniform.

        "},{"location":"01_centralized_auth/#the-identity-model","title":"The identity model","text":"
                    \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n            \u2502        Aetoskia Auth Server         \u2502\n            \u2502  users collection (MongoDB)         \u2502\n            \u2502  HS256 JWT issuer                   \u2502\n            \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n                           \u2502 /login \u2192 JWT\n                           \u2502 /introspect \u2190 verification\n        \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n        \u2502                  \u2502                   \u2502\n   App A (FastAPI)    App B (service)    CLI/web clients\n   verifies via       verifies via\n   jwtlib / OpenAPI   jwtlib introspect\n   dependency\n
        • One issuer. All access tokens are signed with the same JWT_SECRET using HS256 and carry sub (the username) plus an exp claim.
        • One user store. Users live in the shared MongoDB users collection; passwords are bcrypt-hashed and never leave the server.
        • Shared trust. Any service can validate a token locally with jwtlib (decode + signature) or ask the server via /introspect for a live answer.
        • No shared sessions. Logout is stateless: the token is discarded by the client, and further use is prevented only by expiry or revocation through introspection-driven policies.
        "},{"location":"01_centralized_auth/#token-contract","title":"Token contract","text":"

        A valid access token is an HS256 JWT with exactly two claims:

        {\n  \"sub\": \"alice\",\n  \"exp\": 1750000000\n}\n
        • sub \u2014 the username of the authenticated user.
        • exp \u2014 UTC epoch seconds of expiry (60 minutes by default).

        There are no scopes or roles inside the token; authorization decisions belong to the consuming service, while identity and authenticity belong here.

        "},{"location":"01_centralized_auth/#how-the-ecosystem-trusts-the-server","title":"How the ecosystem trusts the server","text":"
        1. Users authenticate once via /login and receive a token.
        2. Services accept that token as proof of identity after verifying it (locally via jwtlib or remotely via /introspect).
        3. Sensitive endpoints recover the user profile from the token through get_current_user or the generated dependency \u2014 never by parsing JWTs by hand.

        This keeps authentication centralized while leaving each service in control of its own authorization rules.

        "},{"location":"01_centralized_auth/#benefits","title":"Benefits","text":"
        • New services onboard with a client library call, not a new auth system.
        • Credential storage, hashing, and issuance policies evolve in one place.
        • A single JWT_SECRET rotation strategy protects the whole platform.
        "},{"location":"02_how_to_use/","title":"How to Use","text":"

        This page covers the plain HTTP usage of the auth server: creating users, logging in, and calling protected endpoints with a bearer token.

        "},{"location":"02_how_to_use/#register-a-user","title":"Register a user","text":"
        curl -X POST http://localhost:8000/register \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"username\": \"alice\", \"email\": \"alice@aetoskia.com\", \"password\": \"s3cret!\"}'\n
        • username \u2014 3 to 50 characters (required).
        • email \u2014 valid email (optional).
        • password \u2014 at least 6 characters (required; stored hashed).

        Response 201 Created:

        {\n  \"username\": \"alice\",\n  \"email\": \"alice@aetoskia.com\",\n  \"is_active\": true\n}\n

        The password is never returned.

        "},{"location":"02_how_to_use/#log-in-to-get-a-token","title":"Log in to get a token","text":"
        curl -X POST http://localhost:8000/login \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"username\": \"alice\", \"password\": \"s3cret!\"}'\n

        Response 200 OK:

        {\n  \"access_token\": \"<jwt>\",\n  \"user\": {\n    \"username\": \"alice\",\n    \"email\": \"alice@aetoskia.com\",\n    \"is_active\": true\n  }\n}\n

        Invalid credentials return 401 with {\"detail\": \"Invalid credentials\"}.

        "},{"location":"02_how_to_use/#call-a-protected-endpoint","title":"Call a protected endpoint","text":"

        Send the token as a bearer token:

        curl http://localhost:8000/me \\\n  -H \"Authorization: Bearer <jwt>\"\n

        Response 200 OK with the current user profile. A missing or invalid token returns 401 with WWW-Authenticate: Bearer.

        "},{"location":"02_how_to_use/#log-out","title":"Log out","text":"
        curl -X POST http://localhost:8000/logout \\\n  -H \"Authorization: Bearer <jwt>\"\n

        Logout is stateless \u2014 the server returns a confirmation and the client must discard the token:

        { \"message\": \"Successfully logged out. Please discard your token on the client.\" }\n
        "},{"location":"02_how_to_use/#token-lifecycle-quick-reference","title":"Token lifecycle quick reference","text":"Event Endpoint Result Create identity POST /register user profile Obtain token POST /login access_token + user Verify (self) GET /me user profile or 401 End session POST /logout discard-token confirmation Verify (other services) POST /introspect active + user

        Interactive examples are available in the API Reference site (Swagger UI), rendered from docs/api/openapi.json.

        "},{"location":"03_platform_integration/","title":"Platform Integration","text":"

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

        "},{"location":"03_platform_integration/#path-1-jwtlib-client-py-jwt","title":"Path 1: jwtlib client (py-jwt)","text":"

        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\n

        Then verify incoming requests:

        from jwtlib.introspection import authenticate_request\n\nauthorized = await authenticate_request(\n    should_skip_authentication,  # e.g. allow public paths\n    method,\n    path,\n    authorization_token,         # \"Bearer <jwt>\" or None\n)\n

        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 \u2014 see the py-jwt documentation.

        "},{"location":"03_platform_integration/#path-2-openapi-first-generated-dependencies","title":"Path 2: openapi-first generated dependencies","text":"

        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:

        securitySchemes:\n  HTTPBearer:\n    type: http\n    scheme: bearer\n    x-server-url: https://auth.aetoskia.com\n    x-introspect-path: /introspect\n

        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.

        "},{"location":"03_platform_integration/#the-introspect-contract","title":"The /introspect contract","text":"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 \u2014 validity is expressed through active. IntrospectResponse never raises, so the caller can act on the tri-state (valid / invalid / user missing) without exception handling.

        "},{"location":"03_platform_integration/#protecting-endpoints-in-fastapi","title":"Protecting endpoints in FastAPI","text":"

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

        from fastapi import Depends\nfrom jwtlib import PublicUser\nfrom jwt import get_current_user\n\n@app.get(\"/profile\")\nasync def profile(current_user: PublicUser = Depends(get_current_user)):\n    return current_user\n
        "},{"location":"03_platform_integration/#golden-rules","title":"Golden rules","text":"
        1. Never trust an unverified token \u2014 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 \u2014 use a generated dependency or the jwtlib client so revocation and issuer changes stay centralized.
        "},{"location":"04_deployment/","title":"Deployment","text":"

        How the auth server is configured and shipped.

        "},{"location":"04_deployment/#environment-variables","title":"Environment variables","text":"Variable Required Default Purpose MONGO_HOST yes \u2014 MongoDB host MONGO_USER no \u2014 MongoDB username MONGO_PASS no \u2014 MongoDB password MONGO_PORT no 27017 MongoDB port MONGO_DB_NAME no auth Database name JWT_SECRET no* superstrongsecretkey Token signing secret (*set in production!)

        Credentials and the token secret live in the environment / Deploy secrets \u2014 see .env.example for the shape. .env is gitignored.

        "},{"location":"04_deployment/#running-locally","title":"Running locally","text":"
        cp .env.example .env      # fill in MONGO_HOST, JWT_SECRET\nuvicorn main:app --reload --port 8000\n

        The health endpoint is available at GET /health.

        "},{"location":"04_deployment/#container-image","title":"Container image","text":"

        The Dockerfile is a multi-stage build on python:3.13-slim:

        1. Builder installs requirements.txt from the private pip index using build args PIP_USERNAME, PIP_PASSWORD, PIP_REPO_URL.
        2. Runtime copies Python 3.13 from the builder, installs curl, exposes port 8000, and runs uvicorn main:app. A HEALTHCHECK curls /health.
        "},{"location":"04_deployment/#cicd-drone","title":"CI/CD (Drone)","text":"

        .drone.yml ships on git tag events (arm64):

        1. Resolve the latest tag.
        2. Skip if the image already exists.
        3. docker build with pip credentials (secrets) \u2192 aetos/auth-server:$TAG and :latest.
        4. Push to $REGISTRY_HOST/aetos/auth-server:*.
        5. Restart the running container auth-server.

        The deployed container runs with --restart always, maps host 9003 \u2192 8000, resolves private-pi to 192.168.1.111 for Mongo, and receives MONGO_* + JWT_SECRET from secrets.

        "},{"location":"04_deployment/#environments","title":"Environments","text":"Environment Base URL Production https://auth.aetoskia.com Internal staging http://server-pi:9002 Local development http://localhost:8000"},{"location":"05_development/","title":"Development","text":"

        Working on the auth server itself.

        "},{"location":"05_development/#repository-layout","title":"Repository layout","text":"Path Purpose main.py FastAPI app factory, environment wiring, lifespan, OpenAPI customization jwt/ The auth routes package (router, get_current_user) generate_spec.py Regenerates the committed OpenAPI spec docs/api/ API reference (Swagger UI embed + openapi.json) docs/lib/ Generated library reference (docforge) docs/wiki/ This hand-written wiki tests/ Async route tests against an in-memory Mongo mock"},{"location":"05_development/#setup","title":"Setup","text":"
        python -m venv .venv\n.venv/Scripts/pip install -r requirements.txt\n

        Dependencies are installed from the private pip index (see requirements.txt and the Dockerfile). Core runtime packages:

        • py-jwt==0.0.4 \u2014 provides jwtlib (applications logic, models, security, introspection)
        • mongo-ops==0.1.3 \u2014 MongoDB persistence layer
        • fastapi, uvicorn, python-jose, passlib, bcrypt, pymongo
        "},{"location":"05_development/#tests","title":"Tests","text":"

        Run the suite (no network or Mongo required \u2014 an in-memory mock is used):

        .venv/Scripts/pytest --asyncio-mode=auto\n

        Coverage spans the full HTTP flow: register \u2192 login \u2192 wrong-password 401 \u2192 /me with and without a token \u2192 stateless logout.

        "},{"location":"05_development/#regenerating-the-openapi-spec","title":"Regenerating the OpenAPI spec","text":"

        The committed docs/api/openapi.json is produced offline:

        set MONGO_HOST=127.0.0.1\npython generate_spec.py\n

        MONGO_HOST only needs to be set for the import; no connection is opened.

        "},{"location":"05_development/#building-documentation-docforge","title":"Building documentation (docforge)","text":"

        The site is generated by docforge and served per kind under site/{kind}:

        doc-forge build \\\n  --api --openapi-spec docs/api/openapi.json \\\n  --mkdocs --wiki \\\n  --module-is-source --module jwt \\\n  --site-name \"Aetoskia Auth Server\"\n
        • --api renders openapi.json with Swagger UI.
        • --mkdocs renders the library reference from jwt docstrings.
        • --wiki builds this wiki.
        • Navigation layout is defined in docforge.nav.yml.

        Preview locally:

        doc-forge serve --api\ndoc-forge serve --lib\ndoc-forge serve --wiki\n
        "}]} \ No newline at end of file +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"\ud83d\udd10 Aetoskia Auth Server \u2014 Central Identity for the Aetos Platform","text":"

        The Aetoskia Auth Server is the central identity service of the Aetos Platform ecosystem. It issues, validates, and introspects short-lived JWT access tokens against a single shared user store backed by MongoDB, so every service can trust one issuer instead of shipping its own auth logic.

        Doc model: this wiki is written for humans \u2014 how\u2011to guides, examples, and deployment recipes. The authoritative API contracts live in the code (GSDFC docstrings) and the interactive OpenAPI reference under docs/api/.

        "},{"location":"#key-features","title":"\ud83d\ude80 Key Features","text":"
        • \ud83d\udd11 Centralized identity \u2014 one user database, one issuer, one secret
        • \ud83c\udf9f\ufe0f Uniform token contract \u2014 every service verifies the same HS256 JWT
        • \ud83e\udde9 No auth code duplication \u2014 services delegate with jwtlib or a generated OpenAPI dependency
        • \u26a1 Instant revocation surface \u2014 /introspect gives services a live active check rather than trusting expiry alone
        • \ud83d\udd13 Stateless logout \u2014 no server-side sessions; the client discards the token
        "},{"location":"#endpoints-at-a-glance","title":"\u26a1 Endpoints at a Glance","text":"Method Path Purpose POST /register Create a user account POST /login Authenticate and issue a JWT GET /me Current user (Bearer) POST /logout Stateless logout (Bearer) POST /introspect Service-to-service token verification GET /health Health check"},{"location":"#documentation-structure","title":"\ud83d\udcc1 Documentation Structure","text":"Section What you'll find Centralized Auth The identity model and how the ecosystem trusts the server How to Use Register, login, and call endpoints with tokens Platform Integration How services authenticate requests Deployment Environment, Docker, and CI/CD Development Local setup, tests, and regenerating docs"},{"location":"#related-resources","title":"\ud83d\udd17 Related Resources","text":"
        • Source Code: Gitea Repository
        • API Reference: interactive Swagger UI rendered from docs/api/openapi.json
        • CI/CD: Drone pipeline ships tagged releases as aetos/auth-server images

        \u00a9 Aetoskia Internal \u2014 auth-server 0.0.5

        "},{"location":"01_centralized_auth/","title":"\ud83d\udd17 Centralized Authentication","text":"

        The Aetoskia Auth Server acts as the single identity provider for every application in the Aetos Platform ecosystem. The model is deliberately small and uniform.

        "},{"location":"01_centralized_auth/#the-identity-model","title":"\ud83e\uddec The identity model","text":"
                    \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n            \u2502        Aetoskia Auth Server         \u2502\n            \u2502  users collection (MongoDB)         \u2502\n            \u2502  HS256 JWT issuer                   \u2502\n            \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n                           \u2502 /login \u2192 JWT\n                           \u2502 /introspect \u2190 verification\n        \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n        \u2502                  \u2502                   \u2502\n   App A (FastAPI)    App B (service)    CLI/web clients\n   verifies via       verifies via\n   jwtlib / OpenAPI   jwtlib introspect\n   dependency\n
        • One issuer. All access tokens are signed with the same JWT_SECRET using HS256 and carry sub (the username) plus an exp claim.
        • One user store. Users live in the shared MongoDB users collection; passwords are bcrypt-hashed and never leave the server.
        • Shared trust. Any service can validate a token locally with jwtlib (decode + signature) or ask the server via /introspect for a live answer.
        • No shared sessions. Logout is stateless: the token is discarded by the client, and further use is prevented only by expiry or revocation through introspection-driven policies.
        "},{"location":"01_centralized_auth/#token-contract","title":"\ud83c\udf9f\ufe0f Token contract","text":"

        A valid access token is an HS256 JWT with exactly two claims:

        {\n  \"sub\": \"alice\",\n  \"exp\": 1750000000\n}\n
        • sub \u2014 the username of the authenticated user.
        • exp \u2014 UTC epoch seconds of expiry (60 minutes by default).

        There are no scopes or roles inside the token; authorization decisions belong to the consuming service, while identity and authenticity belong here.

        "},{"location":"01_centralized_auth/#how-the-ecosystem-trusts-the-server","title":"\ud83e\udd1d How the ecosystem trusts the server","text":"
        1. Users authenticate once via /login and receive a token.
        2. Services accept that token as proof of identity after verifying it (locally via jwtlib or remotely via /introspect).
        3. Sensitive endpoints recover the user profile from the token through get_current_user or the generated dependency \u2014 never by parsing JWTs by hand.

        This keeps authentication centralized while leaving each service in control of its own authorization rules.

        "},{"location":"01_centralized_auth/#benefits","title":"\ud83d\udca1 Benefits","text":"
        • New services onboard with a client library call, not a new auth system.
        • Credential storage, hashing, and issuance policies evolve in one place.
        • A single JWT_SECRET rotation strategy protects the whole platform.
        "},{"location":"01_centralized_auth/#read-next","title":"\ud83d\udcda Read Next","text":"
        • How to Use \u2014 register, login, and call endpoints.
        • Platform Integration \u2014 wiring the token into services.
        "},{"location":"02_how_to_use/","title":"\ud83d\udda5\ufe0f How to Use","text":"

        This page covers the plain HTTP usage of the auth server: creating users, logging in, and calling protected endpoints with a bearer token.

        "},{"location":"02_how_to_use/#register-a-user","title":"\ud83d\udc64 Register a user","text":"
        curl -X POST http://localhost:8000/register \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"username\": \"alice\", \"email\": \"alice@aetoskia.com\", \"password\": \"s3cret!\"}'\n
        • username \u2014 3 to 50 characters (required).
        • email \u2014 valid email (optional).
        • password \u2014 at least 6 characters (required; stored hashed).

        Response 201 Created:

        {\n  \"username\": \"alice\",\n  \"email\": \"alice@aetoskia.com\",\n  \"is_active\": true\n}\n

        The password is never returned.

        "},{"location":"02_how_to_use/#log-in-to-get-a-token","title":"\ud83d\udd11 Log in to get a token","text":"
        curl -X POST http://localhost:8000/login \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"username\": \"alice\", \"password\": \"s3cret!\"}'\n

        Response 200 OK:

        {\n  \"access_token\": \"<jwt>\",\n  \"user\": {\n    \"username\": \"alice\",\n    \"email\": \"alice@aetoskia.com\",\n    \"is_active\": true\n  }\n}\n

        Invalid credentials return 401 with {\"detail\": \"Invalid credentials\"}.

        "},{"location":"02_how_to_use/#call-a-protected-endpoint","title":"\ud83d\udd12 Call a protected endpoint","text":"

        Send the token as a bearer token:

        curl http://localhost:8000/me \\\n  -H \"Authorization: Bearer <jwt>\"\n

        Response 200 OK with the current user profile. A missing or invalid token returns 401 with WWW-Authenticate: Bearer.

        "},{"location":"02_how_to_use/#log-out","title":"\ud83d\udeaa Log out","text":"
        curl -X POST http://localhost:8000/logout \\\n  -H \"Authorization: Bearer <jwt>\"\n

        Logout is stateless \u2014 the server returns a confirmation and the client must discard the token:

        { \"message\": \"Successfully logged out. Please discard your token on the client.\" }\n
        "},{"location":"02_how_to_use/#token-lifecycle-quick-reference","title":"\ud83e\udded Token lifecycle quick reference","text":"Event Endpoint Result Create identity POST /register user profile Obtain token POST /login access_token + user Verify (self) GET /me user profile or 401 End session POST /logout discard-token confirmation Verify (other services) POST /introspect active + user

        Interactive examples are available in the API Reference site (Swagger UI), rendered from docs/api/openapi.json.

        "},{"location":"02_how_to_use/#read-next","title":"\ud83d\udcda Read Next","text":"
        • Centralized Auth \u2014 the identity model and token contract.
        • Platform Integration \u2014 consuming the token in services.
        "},{"location":"03_platform_integration/","title":"\ud83d\udd0c Platform Integration","text":"

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

        "},{"location":"03_platform_integration/#path-1-jwtlib-client-py-jwt","title":"\ud83e\udde9 Path 1: jwtlib client (py-jwt)","text":"

        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\n

        Then verify incoming requests:

        from jwtlib.introspection import authenticate_request\n\nauthorized = await authenticate_request(\n    should_skip_authentication,  # e.g. allow public paths\n    method,\n    path,\n    authorization_token,         # \"Bearer <jwt>\" or None\n)\n

        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 \u2014 see the py-jwt documentation.

        "},{"location":"03_platform_integration/#path-2-openapi-first-generated-dependencies","title":"\ud83d\udee0\ufe0f Path 2: openapi-first generated dependencies","text":"

        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:

        securitySchemes:\n  HTTPBearer:\n    type: http\n    scheme: bearer\n    x-server-url: https://auth.aetoskia.com\n    x-introspect-path: /introspect\n

        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.

        "},{"location":"03_platform_integration/#the-introspect-contract","title":"\ud83d\udccb The /introspect contract","text":"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 \u2014 validity is expressed through active. IntrospectResponse never raises, so the caller can act on the tri-state (valid / invalid / user missing) without exception handling.

        "},{"location":"03_platform_integration/#protecting-endpoints-in-fastapi","title":"\ud83d\udc0d Protecting endpoints in FastAPI","text":"

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

        from fastapi import Depends\nfrom jwtlib import PublicUser\nfrom jwt import get_current_user\n\n@app.get(\"/profile\")\nasync def profile(current_user: PublicUser = Depends(get_current_user)):\n    return current_user\n
        "},{"location":"03_platform_integration/#golden-rules","title":"\u26a0\ufe0f Golden rules","text":"
        1. Never trust an unverified token \u2014 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 \u2014 use a generated dependency or the jwtlib client so revocation and issuer changes stay centralized.
        "},{"location":"03_platform_integration/#read-next","title":"\ud83d\udcda Read Next","text":"
        • How to Use \u2014 the plain HTTP flow.
        • Deployment \u2014 environment, Docker, and CI/CD.
        "},{"location":"04_deployment/","title":"\ud83d\ude80 Deployment","text":"

        How the auth server is configured and shipped.

        "},{"location":"04_deployment/#environment-variables","title":"\u2699\ufe0f Environment variables","text":"Variable Required Default Purpose MONGO_HOST yes \u2014 MongoDB host MONGO_USER no \u2014 MongoDB username MONGO_PASS no \u2014 MongoDB password MONGO_PORT no 27017 MongoDB port MONGO_DB_NAME no auth Database name JWT_SECRET no* superstrongsecretkey Token signing secret (*set in production!)

        Credentials and the token secret live in the environment / Deploy secrets \u2014 see .env.example for the shape. .env is gitignored.

        "},{"location":"04_deployment/#running-locally","title":"\ud83d\udcbb Running locally","text":"
        cp .env.example .env      # fill in MONGO_HOST, JWT_SECRET\nuvicorn main:app --reload --port 8000\n

        The health endpoint is available at GET /health.

        "},{"location":"04_deployment/#container-image","title":"\ud83d\udc33 Container image","text":"

        The Dockerfile is a multi-stage build on python:3.13-slim:

        1. Builder installs requirements.txt from the private pip index using build args PIP_USERNAME, PIP_PASSWORD, PIP_REPO_URL.
        2. Runtime copies Python 3.13 from the builder, installs curl, exposes port 8000, and runs uvicorn main:app. A HEALTHCHECK curls /health.
        "},{"location":"04_deployment/#cicd-drone","title":"\ud83d\udd04 CI/CD (Drone)","text":"

        .drone.yml ships on git tag events (arm64):

        1. Resolve the latest tag.
        2. Skip if the image already exists.
        3. docker build with pip credentials (secrets) \u2192 aetos/auth-server:$TAG and :latest.
        4. Push to $REGISTRY_HOST/aetos/auth-server:*.
        5. Restart the running container auth-server.

        The deployed container runs with --restart always, maps host 9003 \u2192 8000, resolves private-pi to 192.168.1.111 for Mongo, and receives MONGO_* + JWT_SECRET from secrets.

        "},{"location":"04_deployment/#environments","title":"\ud83c\udf0d Environments","text":"Environment Base URL Production https://auth.aetoskia.com Internal staging http://server-pi:9002 Local development http://localhost:8000"},{"location":"04_deployment/#read-next","title":"\ud83d\udcda Read Next","text":"
        • Platform Integration \u2014 the /introspect contract.
        • Development \u2014 local setup, tests, and docs.
        "},{"location":"05_development/","title":"\ud83d\udee0\ufe0f Development","text":"

        Working on the auth server itself.

        "},{"location":"05_development/#repository-layout","title":"\ud83d\udcc2 Repository layout","text":"Path Purpose main.py FastAPI app factory, environment wiring, lifespan, OpenAPI customization jwt/ The auth routes package (router, get_current_user) generate_spec.py Regenerates the committed OpenAPI spec docs/api/ API reference (Swagger UI embed + openapi.json) docs/lib/ Generated library reference (docforge) docs/wiki/ This hand-written wiki tests/ Async route tests against an in-memory Mongo mock"},{"location":"05_development/#setup","title":"\ud83d\udd27 Setup","text":"
        python -m venv .venv\n.venv/Scripts/pip install -r requirements.txt\n

        Dependencies are installed from the private pip index (see requirements.txt and the Dockerfile). Core runtime packages:

        • py-jwt==0.0.4 \u2014 provides jwtlib (applications logic, models, security, introspection)
        • mongo-ops==0.1.3 \u2014 MongoDB persistence layer
        • fastapi, uvicorn, python-jose, passlib, bcrypt, pymongo
        "},{"location":"05_development/#tests","title":"\ud83e\uddea Tests","text":"

        Run the suite (no network or Mongo required \u2014 an in-memory mock is used):

        .venv/Scripts/pytest --asyncio-mode=auto\n

        Coverage spans the full HTTP flow: register \u2192 login \u2192 wrong-password 401 \u2192 /me with and without a token \u2192 stateless logout.

        "},{"location":"05_development/#regenerating-the-openapi-spec","title":"\ud83d\udcdc Regenerating the OpenAPI spec","text":"

        The committed docs/api/openapi.json is produced offline:

        set MONGO_HOST=127.0.0.1\npython generate_spec.py\n

        MONGO_HOST only needs to be set for the import; no connection is opened.

        "},{"location":"05_development/#building-documentation-docforge","title":"\ud83d\udcdd Building documentation (docforge)","text":"

        The site is generated by docforge and served per kind under site/{kind}:

        doc-forge build \\\n  --api --openapi-spec docs/api/openapi.json \\\n  --mkdocs --wiki \\\n  --module jwt \\\n  --site-name \"Aetoskia Auth Server\"\n
        • --api renders openapi.json with Swagger UI.
        • --mkdocs renders the library reference from the jwt package docstrings (nested under docs/lib/jwt/, matching docforge.nav.yml).
        • --wiki builds this wiki.
        • Navigation layout is defined in docforge.nav.yml.

        The jwt module is rendered without --module-is-source so the library output stays nested under docs/lib/jwt/, matching the committed docs/mkdocs.lib.yml nav.

        Preview locally:

        doc-forge serve --api\ndoc-forge serve --lib\ndoc-forge serve --wiki\n
        "},{"location":"05_development/#read-next","title":"\ud83d\udcda Read Next","text":"
        • Deployment \u2014 environment and CI/CD.
        • How to Use \u2014 exercising the service end to end.
        "}]} \ No newline at end of file diff --git a/auth-server/wiki/sitemap.xml.gz b/auth-server/wiki/sitemap.xml.gz index e496a0d39e2d89445c665e87a8c93f68e7f55814..89851db59432aa6d7a5d0fe339808593e07e45ef 100644 GIT binary patch delta 13 Ucmb=gXP58h;9$73aw2;L033S+RR910 delta 13 Ucmb=gXP58h;AnWhbRv5N03V_R+yDRo