OpenG2P FastAPI Common
The shared FastAPI framework and utilities that most OpenG2P Python services are built on — app bootstrap, config, data layer, auth, and JWS crypto.
openg2p-fastapi-common is the base framework nearly every OpenG2P Python microservice is built on (g2p-bridge, consent-manager, Partner Management, the registry APIs, the IAM staff-portal API, …). Standardising it means services share one app lifecycle, config convention, data layer, error format, and — importantly for signed inter-service traffic — one JWS crypto implementation.
The repository publishes four installable packages:
openg2p-fastapi-common
Core: app Initializer, BaseController/BaseService, Settings, async SQLAlchemy models, error envelope, JWS crypto
openg2p-fastapi-auth
OIDC/JWT validation dependency (JwtBearerAuth, StaffKeycloakAuth)
openg2p-fastapi-auth-models
Shared auth schemas (AuthCredentials, login providers)
openg2p-fastapi-partner-auth
Partner-request JWS signature validation dependency
What the core provides
App bootstrap (
Initializer) — builds the FastAPI app, wires logging, CORS, security headers, the async SQLAlchemy engine, and the exception handler; exposes a CLI (run,migrate,getOpenAPI). Services subclass it and register their controllers/services.BaseController/BaseService— anAPIRouter-backed controller base and a component-registry service base, so components discover each other as singletons.Settings— Pydantic-settings config with an env prefix per service (e.g.G2P_BRIDGE_*), plus common fields for DB, logging, CORS, and crypto.Data layer — async SQLAlchemy 2.0 base models (
BaseORMModelWithId,BaseORMModelWithTimes) with idempotentcreate_migrate().Error envelope — a
BaseAppExceptionhierarchy that renders the platform standard{code, message}response.
JWS crypto
Services sign their own outbound requests and verify inbound partner-signed requests using a detached JWS (header..signature) over a canonical payload. The behaviour is selected by one setting, crypto_backend:
crypto_backend
Verification key source
Signing
Notes
keymanager (default)
MOSIP Keymanager (remote)
Keymanager
Legacy/HSM path
local
Local partner_keys table, seeded from Helm
Local PKCS#12 keystore
In-process PyJWT; no Keymanager
partner-mgmt
Partner Management service (fetched + cached)
Local PKCS#12 keystore
In-process PyJWT; no local key seeding
Only asymmetric algorithms are accepted (RS256 by default); none and HMAC (HS*) are always rejected.
Local signing key
For the local and partner-mgmt backends, a service that signs loads its own private key from a password-protected PKCS#12 (.p12) keystore (crypto_signing_key_path / crypto_signing_key_password). The kid defaults to the signing certificate's SHA-256 thumbprint. A service that only verifies needs no signing key.
Partner keys — verifying inbound partner signatures
To verify a partner's signature, the service needs that partner's public key. Two sources exist behind the same PartnerKeyStore.get_keys(reference_id) contract (returning {kid, algorithm, public_key_pem} dicts, from which the verifier selects by kid/alg):
local— seeded local table. Partner certs are upserted into the service's ownpartner_keystable at migrate-time fromcrypto_partner_certs(Helm config). Simple, but every service maintains its own copy and there is no runtime admin API.partner-mgmt— fetched from Partner Management. The recommended path. On a cache miss the service doesGET {partner_mgmt_api_url}/keys/{reference_id}against the PM partner-api and caches the result in-process. Partners are onboarded and rotated centrally in Partner Management; consumers hold no partner keys of their own.
Caching (partner-mgmt)
partner-mgmt)To avoid an HTTP call per verification, PartnerMgmtKeyStore caches keys per reference_id in-memory with a small, well-defined policy — the standard JWKS client pattern:
Soft TTL (refresh)
min(300s, PM Cache-Control), floor 30s
Bounds how long a revoked key / disabled partner stays trusted — kept short
Refresh-on-unknown-kid
rate-limited by cooldown
A just-rotated partner's new kid triggers one immediate refresh, so rotation is picked up without waiting for the TTL
Hard TTL (serve-stale)
6h
If PM is unreachable, keep serving last-known-good keys up to this age (logged WARNING), then fail closed
Negative cache
30s
A 404 not available (disabled/unknown partner) is remembered briefly so it doesn't fetch per request; still fails closed
Refresh cooldown
10s
Min interval between fetch attempts per partner (throttles unknown-kid refreshes and outage retries)
Single-flight
—
Concurrent misses for one partner collapse to a single HTTP call
Because unknown-kid refresh makes rotation near-instant, the soft TTL's real job is revocation latency (disable/revoke), which is why it is kept short rather than the multi-hour TTL some JWKS clients use.
Config (env, with the service's own prefix — e.g. G2P_BRIDGE_*)
G2P_BRIDGE_*)Note on the env prefix.
crypto_*settings live on the mainSettings, which each service subclasses with its own prefix (G2P_BRIDGE_,PARTNER_MANAGER_, …). Theopeng2p-fastapi-authsettings are separate and use theCOMMON_prefix. So it's<PREFIX>_CRYPTO_BACKEND, notCOMMON_CRYPTO_BACKEND.
Identity: reference_id vs partner_id
reference_id vs partner_idA verifier derives a reference_id from the inbound request (for the commons partner-auth path, PARTNER_<MNEMONIC> from the JWS sender_app_mnemonic) and fetches /keys/{reference_id}. For the fetch to resolve, the partner must be onboarded in Partner Management under a matching partner_id — i.e. standardise partner_id == PARTNER_<MNEMONIC> for the commons/local-crypto consumers. Services that key on a different attribute (e.g. consent-manager's audience) either onboard under that value or rely on a future PM alias.
Auth
openg2p-fastapi-auth provides JwtBearerAuth (verifies a Keycloak JWT against the issuer's JWKS) and StaffKeycloakAuth (adds staff-realm role checks), used as FastAPI dependencies. Its settings use the COMMON_AUTH_* env prefix.
Versioning
Services install these packages from the develop git ref (pinnable to a tag via each service's FASTAPI_COMMON_REF build-arg). See Versions.
Last updated
Was this helpful?