Short answer: validate gateway tokens with public JWKS keys, keep a bounded refresh path for rotation, and fail closed for signup traffic when key retrieval cannot be trusted. Treat CAPTCHA verification as a separate, auditable state transition rather than a reason to weaken token checks.
In an e-commerce gateway, a bot can hit the registration endpoint long before a human sees the CAPTCHA widget. The gateway therefore has two jobs: prove who signed the token, then decide whether that request is allowed to create an account. Those are different decisions. Mixing them produces logs that are hard to explain and retry behavior that is harder to contain.
The constraint that changed the design
Private keys should stay with the issuer. Copying one into every microservice turns a rotation into a coordinated outage risk. A gateway only needs the public key set (JWKS) to verify a signature, and it can keep that set in memory with an expiry and a refresh lock.
The cache is not a permanent answer. A valid token can reference a newly rotated kid while every gateway process still holds yesterday's set. Conversely, refreshing on every request makes the identity provider a dependency of your signup latency. I use a stale-while-refresh window: serve a known-good key set during its normal TTL, refresh once when a key id is missing, and put a hard ceiling on how long stale data may be used.






