Skip to content

Introduce DPoPAuthenticationFilter to avoid conflict with other AuthenticationFilter #17186

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

therepanic
Copy link
Contributor

This change will enable us to use multiple AuthenticationFilter.

Fix: #17173

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label May 29, 2025
@jgrandja jgrandja self-assigned this May 29, 2025
@jgrandja jgrandja added type: bug A general bug in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) and removed status: waiting-for-triage An issue we've not yet triaged labels May 29, 2025
@@ -222,4 +223,9 @@ private Authentication attemptAuthentication(HttpServletRequest request, HttpSer
return authenticationResult;
}

@Override
protected String getAlreadyFilteredAttributeName() {
return getClass().getName() + ".FILTERED";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@therepanic This does not solve the issue as 2 instances of AuthenticationFilter in the chain would return the same value from getAlreadyFilteredAttributeName(), resulting in the 2nd AuthenticationFilter never being called.

Please adjust and add a test that demonstrates the fix.

Copy link
Contributor Author

@therepanic therepanic May 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I apologize for not accurately solving the problem. We do want each AuthenticationFilter instance to be honored in the chain. What I did I guess won't work if the filters are the same and added to the chain. Then I guess we need to use something like identityHashCode for getAlreadyFilteredAttributeName()? I just want to make sure it's right for us. Thanks.

@therepanic
Copy link
Contributor Author

therepanic commented May 30, 2025

I made the changes you asked for. Including adding a test.

Before the changes, this test failing because converter2 is not called. With the changes this text runs as it should.

@@ -222,4 +223,9 @@ private Authentication attemptAuthentication(HttpServletRequest request, HttpSer
return authenticationResult;
}

@Override
protected String getAlreadyFilteredAttributeName() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just realized that this is a public API change and therefore cannot be applied in 6.5.1 release. We'll need to address this issue with AuthenticationFilter in a separate issue targeted for 7.0.

For now, we need to address gh-17173 and I think the easiest solution is to define the following in DPoPAuthenticationConfigurer:

private static final class DPoPAuthenticationFilter extends AuthenticationFilter {

	private DPoPAuthenticationFilter(AuthenticationManager authenticationManager, AuthenticationConverter authenticationConverter) {
		super(authenticationManager, authenticationConverter);
	}

}

I think this should solve the bug.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@therepanic Please hold off on the proposed change in my previous comment. The root issue is in AuthenticationFilter and we still need to address it as a bug. We might still be able to get your change into 6.5.1 but let me think about this for a bit.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the advice. You want me to create a separate issue and link the PR to it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@therepanic therepanic changed the title Override OncePerRequestFilter#getAlreadyFilteredAttributeName in AuthenticationFilter Introduce DPoPAuthenticationFilter to avoid conflict with other AuthenticationFilter Jun 3, 2025
…thenticationFilter` (spring-projects#17173)

Signed-off-by: Andrey Litvitski <andrey1010102008@gmail.com>
@therepanic
Copy link
Contributor Author

therepanic commented Jun 3, 2025

I believe that it is #17173 that we have now solved. However I also understand the problem that I solved in the last commit as you said for merge is now unavailable? What should we do about it now?

@therepanic therepanic requested a review from jgrandja June 3, 2025 19:16
@jgrandja
Copy link
Contributor

jgrandja commented Jun 3, 2025

@therepanic Maybe you missed my last comment?

We should fix this in AuthenticationFilter as it's a bug. Please go back to previous commit and override getAlreadyFilteredAttributeName() as follows:

@Override
protected String getAlreadyFilteredAttributeName() {
	String name = getFilterName();
	if (name == null) {
		name = AuthenticationFilter.class.getSimpleName() + "." +
				getAuthenticationConverter().getClass().getSimpleName();
	}
	return name + ALREADY_FILTERED_SUFFIX;
}

We'll need to get this fix into all supported OSS branches so please rebase the fix off of 6.3.x.

@therepanic
Copy link
Contributor Author

I apologize for the misunderstanding. I really didn't see that you asked in the next comment to leave it as is.

You posted how it should be overrided and I have a question. Will this work at all? In my last commit I added a test like this:

@Test
public void filterWhenInFilterChainThenBothAreExecuted() throws Exception {
	MockHttpServletRequest request = new MockHttpServletRequest(“GET”, “/”);
	MockHttpServletResponse response = new MockHttpServletResponse();
	AuthenticationFilter filter1 = new AuthenticationFilter(this.authenticationManager,
			this.authenticationConverter);
	AuthenticationConverter converter2 = mock(AuthenticationConverter.class);
	AuthenticationFilter filter2 = new AuthenticationFilter(this.authenticationManager, converter2);
	FilterChain chain = new MockFilterChain(mock(Servlet.class), filter1, filter2);
	chain.doFilter(request, response);
	verify(this.authenticationConverter).convert(any());
	verify(converter2).convert(any());
}

Tell me if it is incorrect. However, if it is correct, then the test will fail with the solution you submitted.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) type: bug A general bug
Projects
None yet
Development

Successfully merging this pull request may close these issues.

DPoP filter is ignored when another AuthenticationFilter is present
3 participants