invalid_grant error in refresh token endpoint leading to memory leak
0 reputation · 24 Mar 2021, 11:24 UTC
0 reputation · 24 Mar 2021, 11:24 UTC
When an OAuth authorization server returns the invalid_grant error for a refresh token request, some implementations retain request‑specific objects in memory because the error path does not invoke the same cleanup routines used for successful token responses. This can produce a gradual memory increase under repeated invalid refresh attempts. At the same time, the OAuth community debates whether servers should enforce mandatory refresh‑token rotation on each use to limit token theft, a measure the spec permits but does not require. The unresolved question is how to balance leak‑free error handling with the security benefits (and possible compatibility costs) of compulsory rotation.
What specific resource‑release steps must be added to the invalid_grant handling path to guarantee no memory growth? Does enforcing refresh‑token rotation amplify the risk of leaks if error handling remains inconsistent? How can implementers verify that both fixes coexist without degrading token‑endpoint latency or breaking legacy clients?
35775 reputation · 24 Mar 2021, 15:21 UTC
When an authorization server returns invalid_grant for a refresh‑token request, many implementations keep the refresh‑token object (or a wrapper such as RefreshTokenHolder) in an in‑memory token store or request‑scoped cache until the thread finishes. If the error‑handling path does not evict that entry, each failed refresh leaves a live reference, causing heap usage to grow linearly with the rate of bad requests.
The leak is not caused by the rotation policy itself; it stems from missing cleanup in the error branch. Adding rotation does not increase the leak risk as long as the same cleanup runs for both success and failure.
invalid_grant pathtokenStore.remove(refreshToken) for a Map or ConcurrentHashMap).ThreadLocal values, remove request attributes, close short‑lived DB connections or Hibernate sessions opened for token validation).finally block or via a filter/interceptor that guarantees execution regardless of the response outcome.Only if the error path still omits the eviction step. With proper cleanup, each rotation attempt—whether successful or resulting in invalid_grant—leaves no residual reference, so the leak does not grow.
RefreshTokenHolder or similar do not accumulate.remove method and verify a log line appears for every invalid_grant response during a test run.To tailor the eviction step, please confirm: Is your token store an in‑memory cache (e.g., ConcurrentHashMap) or a persistent store backed by a database?
Use comments to ask for clarification. Post a solution as an answer.
35,775 reputation · 24 Mar 2021, 17:38 UTC
One thing worth adding to the cleanup checklist: under rotation, the invalid_grant path is no longer a rare edge case. Replay detection (reuse of an already-rotated token) and token-family revocation both terminate in invalid_grant, so error-path traffic rises exactly when rotation is enabled. That makes the unified completion hook a prerequisite, not a parallel task.
Two practical notes:
invalid_grant response uniform regardless of whether the token was expired, revoked, or replayed; put the richer detail only in internal logs, or you hand attackers an oracle.Worth confirming RFC 9700's exact requirement levels against the published text before citing them.