🍗 PCK ZRA Middleware Wiki

Security

The middleware handles fiscally sensitive data and credentials for multiple stores. Security is layered: transport, authentication per channel, per-store credential isolation, and a complete audit trail.

Security channels at a glance

ChannelAuthenticationSession model
POS API (/api/taxint/**)Bearer JWT (Oracle IDM)Stateless
Store & Reports APIs (/api/stores/**, /api/reports/**)Spring SecurityStateless
Admin web portalEmail + password, then WhatsApp OTPHTTP session
Chrilan Smart API (outbound)Per-store API key (x-api-key header)
Oracle STS (outbound)OAuth2 authorization code + PKCECached id_token
Whapi (outbound)Bearer token

POS API: JWT validation

POS terminals obtain a JWT from Oracle Restaurant IDM. The middleware validates it by:

  1. Extracting the kid (key ID) from the JWT header
  2. Fetching the public key from Oracle IDM's JWKS endpoint (/oauth2/jwks)
  3. Verifying the signature, issuer and expiration
ParameterValue
JWKS URLhttps://ors-idm.msaf.oraclerestaurants.com/oauth2/jwks
Expected issuerhttps://ors-idm.msaf.oraclerestaurants.com
Clock skew tolerance300 seconds
JWKS cache duration3600 seconds (per key)
Current toggle state JWT validation is controlled by auth.jwt.validation-enabled and is currently disabled for UAT (the filter only checks the Bearer prefix). Enable it before enforcing production trust. Even when disabled, the store lookup and per-store API key checks still apply — an unregistered store cannot submit regardless of token state.

Per-store API keys: no fallbacks

Chrilan API keys live in the store_registrations table, one per store. There is no default or fallback key anywhere in configuration. Consequences by design:

Admin portal: two-factor with WhatsApp OTP

Web and transport hardening

Secrets handling

Audit as a security control

Every inbound request is logged before the security chain (RequestResponseLoggingFilter), so even rejected requests leave evidence: source, payload, status and timing. Combined with conversion logs and fiscal invoice persistence, any receipt or rejection can be reconstructed after the fact. See Audit Logging.

Operational security checklist

  1. Enable auth.jwt.validation-enabled=true when moving beyond UAT.
  2. Rotate the default Spring Security admin credentials on any new deployment.
  3. Keep WhatsApp OTP enabled (whapi.api.enabled=true) in production.
  4. Review failed transactions weekly for probing patterns (repeated 401/403).
  5. Deactivate stores immediately when a location closes or a device is decommissioned.