spring-projects / spring-projects/spring-security

AuthenticationWebFilter executes filter chain twice per request

Open
#16,553 7 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

status: waiting-for-triage
Dominant language
Java
Stars
9.6k
Forks
6.3k
Avg merge
2d 11h
Merged PRs (30d)
52

Description

I've noticed this for some time in my application logs and thought I was just misconfiguring Spring Security WebFlux somehow. But upon closer examination, I think there's a bug in AuthenticationWebFilter that causes this behavior:

https://github.com/spring-projects/spring-security/blob/8e2a4bf3562133c78230ec5a96ec993c5c92374b/web/src/main/java/org/springframework/security/web/server/authentication/AuthenticationWebFilter.java#L114

        @Override
	public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
		return this.requiresAuthenticationMatcher.matches(exchange)
			.filter((matchResult) -> matchResult.isMatch())
			.flatMap((matchResult) -> this.authenticationConverter.convert(exchange))
			.switchIfEmpty(chain.filter(exchange).then(Mono.empty()))
			.flatMap((token) -> authenticate(exchange, chain, token))
			.onErrorResume(AuthenticationException.class, (ex) -> this.authenticationFailureHandler
				.onAuthenticationFailure(new WebFilterExchange(exchange, chain), ex));
	}

The .switchIfEmpty() here is actually subscribing to the filter chain on downstream subscription, rather than deferring it until it is needed. Shouldn't that line be more like:

.switchIfEmpy(Mono.defer(() -> chain.filter(exchange).then(Mono.empty()))

And, in fact, the method directly below this one uses Mono.defer() for error cases.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in web/src/main/java/org/springframework/security/web/server/authentication/AuthenticationWebFilter.java around the filter method at the referenced line, then compare it with the method below that uses Mono.defer(). Reproduce the request flow and verify that the downstream WebFilterChain is subscribed only when authentication conversion is empty, so the chain executes once per request.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring
Domain
backend, security
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.