spring-projects / spring-projects/spring-security
InMemoryOAuth2AuthorizationService retains completed authorizations indefinitely and may cause unbounded memory growth
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 9.6k
- Forks
- 6.3k
- Avg merge
- 2d 11h
- Merged PRs (30d)
- 52
Description
Expected Behavior
InMemoryOAuth2AuthorizationService should provide a mechanism to prevent completed OAuth2Authorization instances from being retained indefinitely after all relevant tokens are no longer usable.
This does not necessarily need to be implemented using a background scheduler. Possible approaches could include opportunistic/lazy cleanup, a configurable eviction strategy, a configurable maximum size, or an explicit cleanup API.
Ideally, cleanup should take the lifetime of all relevant tokens into account (for example, a refresh token may still be valid after the access token has expired).
Current Behavior
InMemoryOAuth2AuthorizationService already bounds initialized (incomplete) authorizations:
private int maxInitializedAuthorizations = 100;
private Map<String, OAuth2Authorization> initializedAuthorizations =
Collections.synchronizedMap(
new MaxSizeHashMap<>(this.maxInitializedAuthorizations));
However, completed authorizations are stored in an unbounded ConcurrentHashMap:
private final Map<String, OAuth2Authorization> authorizations =
new ConcurrentHashMap<>();
When an access token is issued, the authorization is stored in this map:
if (isComplete(authorization)) {
this.authorizations.put(authorization.getId(), authorization);
}
There is no automatic eviction when the associated tokens expire. Unless remove is explicitly called, completed authorizations therefore remain strongly referenced for the lifetime of the application.
This creates an asymmetry in the current implementation:
initialized authorizations -> bounded (default 100)
completed authorizations -> unbounded
Context
We encountered this in a long-running authorization server using InMemoryOAuth2AuthorizationService.
Under normal authentication traffic, heap usage continuously increases as completed authorizations accumulate. In our deployment, the JVM eventually exhausts its available heap after approximately 15 days of operation. Restarting the application releases the memory, after which the same growth pattern begins again.
I understand that InMemoryOAuth2AuthorizationService is explicitly documented as intended for development/testing. However, even in-memory development/testing implementations can be used by long-running test, staging, demo, or lightweight deployments, and the unbounded growth is not obvious to users.
We considered periodically clearing the completed authorization map, but unconditional cleanup can break valid refresh tokens, token introspection, revocation, or other flows that still depend on the stored OAuth2Authorization.
We also considered implementing a custom OAuth2AuthorizationService, but it seems that a generic cleanup/eviction mechanism in InMemoryOAuth2AuthorizationService could benefit other users and would make its memory behavior consistent with the existing bounded handling of initialized authorizations.
Would the Spring Security team be open to providing a supported eviction/cleanup mechanism for completed authorizations?
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with InMemoryOAuth2AuthorizationService, focusing on the completed authorizations map, isComplete, and remove handling. Compare the existing bounded initialized-authorization behavior with the requested cleanup approaches, ensuring valid refresh tokens, introspection, revocation, and other token lifetimes remain supported; done means completed authorizations no longer grow without bound.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, spring
- Domain
- backend, security
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100