Identity Security / Backend Engineering

Enterprise Identity & Zero Trust Authorization

A multi-tenant IAM reference implementation demonstrating OAuth2/OIDC authentication, JWT-secured APIs, machine identity with mTLS, and fine-grained authorization using OpenFGA and OPA.

JavaSpring BootKeycloakOAuth2/OIDCJWTOpenFGAOPAPostgreSQLmTLS

Published offline reference · 259 recorded passing tests · No production deployment claim

Identity

OAuth2/OIDC + PKCE

Authorization

OpenFGA + OPA

Machine Security

mTLS + JWT

Validation

259 recorded passing tests

System Architecture

One API, distinct human and machine boundaries.

A logical component view of the included source. Nginx hosts the React SPA and proxies human requests. Spring Boot orchestrates PostgreSQL, OpenFGA and OPA checks for resource reads. Machine traffic connects directly to a dedicated TLS listener. This illustration is not evidence of a deployed environment.

Select the illustration to preview it, or open the full-resolution image ↗ to zoom into labels on a smaller screen.

React + Keycloak: browser login through oidc-client-ts, Authorization Code + PKCE S256 and a public OIDC client.

Nginx + Spring Boot: SPA delivery, human API proxying, JWT validation and application-level authorization enforcement.

PostgreSQL: internal principal mapping, active tenant membership, resource ownership and classification.

OpenFGA + OPA: independent API calls for relationship permissions and additional contextual policy, in that order.

Engineering Problem

Identity is the start of the decision.

A valid identity is only the first gate. A multi-tenant API must also establish active membership, resource ownership, relationship permissions and contextual policy before returning data. Human and machine callers need distinct authentication boundaries without bypassing enforcement.

Tenant and resource context comes from server-owned data.

Dependency failures must never become permission grants.

Human and machine traffic share one API process, with separate listeners.

Authentication & Authorization

Three flows, explicit enforcement points.

Human authentication

The SPA uses an OIDC client library; the API independently validates the resulting access token.

  1. Redirect to Keycloak for Authorization Code + PKCE S256; complete the callback and code exchange through oidc-client-ts.
  2. Send the bearer access token through Nginx to the human API listener. OIDC state and user data use sessionStorage.
  3. Validate signature using JWKS, issuer, API audience and timestamps; explicitly require exp. Resolve issuer + subject to an active internal principal.

A valid JWT establishes identity; it does not by itself authorize resource access.

Human resource authorization

Project and document reads pass ordered gates. OPA cannot override a PostgreSQL or OpenFGA denial.

  1. Resolve the principal and load resource metadata from PostgreSQL. Check active identity, tenant membership and resource eligibility.
  2. Ask OpenFGA for can_view using the internal principal and resource IDs. Denial or failure stops the request before OPA.
  3. Only after OpenFGA ALLOW, call OPA with backend-derived context. Return resource metadata only if the policy also allows.

Ineligible cross-tenant reads are concealed with 404; permission denial returns 403, and handled dependency failures return 503.

Machine identity

An external machine client uses OAuth2 Client Credentials and connects directly to the dedicated HTTPS/mTLS listener.

  1. Obtain a machine access token from the configured confidential Keycloak client; present it with a trusted X.509 client certificate.
  2. Validate JWT signature, issuer, dedicated audience, authorized client, service-account subject, time claims and required role.
  3. Require the trusted TLS transport, valid certificate dates and exactly one matching URI SAN associated with the configured JWT identity.

GET /api/machine/policy/health is authenticated liveness only: no PostgreSQL, OpenFGA or OPA calls. Certificate association is not OAuth cnf/thumbprint token binding.

Engineering Decisions

Boundaries with deliberate trade-offs.

Separate identity from permission

Validate JWTs before resolving an internal principal and evaluating resource access.

Additional gates increase request work but prevent a valid token from becoming blanket access.

Inspect implementation ↗

Keep tenant context authoritative

Use PostgreSQL for principal mapping, active memberships and resource metadata.

The database is an availability dependency; database errors do not grant access.

Inspect implementation ↗

Compose relationship and policy checks

Require OpenFGA can_view before a separate OPA evaluation. The API owns sequencing.

Two decision services add latency and operational complexity; both must allow.

Inspect implementation ↗

Isolate machine transport

Use a dedicated mTLS connector and reject routes on the wrong listener, including Nginx machine-route denial.

Connector isolation is not process isolation: both listeners share one Spring Boot application.

Inspect implementation ↗

Security Engineering

Enforce each boundary; fail closed.

  • Least privilege: each resource read needs active eligibility, relationship permission and policy approval.
  • Deny by default: malformed dependency responses, timeouts and invalid configuration never produce an allow.
  • Tenant isolation: derive ownership from the database and conceal resources from ineligible callers.
  • Defense in depth: reject machine routes on human transport and human routes on machine transport; forwarded headers do not establish trusted mTLS.

Recorded Offline Evidence

Security regression results.

259

Total passing tests

187

Java tests

72

Python tests

Recorded offline regression coverage. Native OPA/OpenFGA checks were excluded. These results do not establish production deployment or complete end-to-end integration.

From the IAM repository, with JDK 21, Python 3.9+, Maven and cached dependencies:

python3 infrastructure/testing/security_regression.py

Scope & Limitations

An inspectable reference, with evidence boundaries.

  • Offline-validated reference implementation, not a production deployment.
  • No complete SCIM provisioning or Microsoft Entra ID integration.
  • No trusted live MFA assurance.
  • No complete live end-to-end deployment acceptance.