Skip to content

Commit 5fa252b

Browse files
committed
SEC-2078: AbstractPreAuthenticatedProcessingFilter requriesAuthentication support for non-String Principals
Previously, if the Principal returned by getPreAuthenticatedPrincipal was not a String, it prevented requiresAuthentication from detecting when the Principal was the same. This caused the need to authenticate the user for every request even when the Principal did not change. Now requiresAuthentication will check to see if the result of getPreAuthenticatedPrincipal is equal to the current Authentication.getPrincipal().
1 parent 87c3c7e commit 5fa252b

File tree

2 files changed

+152
-4
lines changed

2 files changed

+152
-4
lines changed

web/src/main/java/org/springframework/security/web/authentication/preauth/AbstractPreAuthenticatedProcessingFilter.java

+18-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
/*
2+
* Copyright 2002-2012 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*/
113
package org.springframework.security.web.authentication.preauth;
214

315
import java.io.IOException;
@@ -50,6 +62,7 @@
5062
*
5163
* @author Luke Taylor
5264
* @author Ruud Senden
65+
* @author Rob Winch
5366
* @since 2.0
5467
*/
5568
public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFilterBean implements
@@ -142,7 +155,11 @@ private boolean requiresAuthentication(HttpServletRequest request) {
142155

143156
Object principal = getPreAuthenticatedPrincipal(request);
144157

145-
if (currentUser.getName().equals(principal)) {
158+
if ((principal instanceof String) && currentUser.getName().equals(principal)) {
159+
return false;
160+
}
161+
162+
if(principal != null && principal.equals(currentUser.getPrincipal())) {
146163
return false;
147164
}
148165

web/src/test/java/org/springframework/security/web/authentication/preauth/AbstractPreAuthenticatedProcessingFilterTests.java

+134-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,26 @@
1+
/*
2+
* Copyright 2002-2012 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*/
113
package org.springframework.security.web.authentication.preauth;
214

3-
import static org.junit.Assert.*;
15+
import static org.junit.Assert.assertEquals;
16+
import static org.junit.Assert.assertNull;
17+
import static org.junit.Assert.assertTrue;
18+
import static org.junit.Assert.fail;
419
import static org.mockito.Matchers.any;
5-
import static org.mockito.Mockito.*;
20+
import static org.mockito.Mockito.mock;
21+
import static org.mockito.Mockito.verify;
22+
import static org.mockito.Mockito.verifyZeroInteractions;
23+
import static org.mockito.Mockito.when;
624

725
import javax.servlet.FilterChain;
826
import javax.servlet.ServletException;
@@ -19,9 +37,17 @@
1937
import org.springframework.security.authentication.AuthenticationManager;
2038
import org.springframework.security.authentication.BadCredentialsException;
2139
import org.springframework.security.authentication.TestingAuthenticationToken;
40+
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
2241
import org.springframework.security.core.Authentication;
42+
import org.springframework.security.core.authority.AuthorityUtils;
2343
import org.springframework.security.core.context.SecurityContextHolder;
44+
import org.springframework.security.core.userdetails.User;
2445

46+
/**
47+
*
48+
* @author Rob Winch
49+
*
50+
*/
2551
public class AbstractPreAuthenticatedProcessingFilterTests {
2652
private AbstractPreAuthenticatedProcessingFilter filter;
2753

@@ -123,6 +149,111 @@ public void nullPreAuthenticationPerservesPreviousUserCheckPrincipalChangesFalse
123149
assertEquals(authentication, SecurityContextHolder.getContext().getAuthentication());
124150
}
125151

152+
@Test
153+
public void requiresAuthenticationFalsePrincipalString() throws Exception {
154+
Object principal = "sameprincipal";
155+
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken(principal, "something", "ROLE_USER"));
156+
MockHttpServletRequest request = new MockHttpServletRequest();
157+
MockHttpServletResponse response = new MockHttpServletResponse();
158+
MockFilterChain chain = new MockFilterChain();
159+
160+
ConcretePreAuthenticatedProcessingFilter filter = new ConcretePreAuthenticatedProcessingFilter();
161+
filter.setCheckForPrincipalChanges(true);
162+
filter.principal = principal;
163+
AuthenticationManager am = mock(AuthenticationManager.class);
164+
filter.setAuthenticationManager(am);
165+
filter.afterPropertiesSet();
166+
167+
filter.doFilter(request, response, chain);
168+
169+
verifyZeroInteractions(am);
170+
}
171+
172+
@Test
173+
public void requiresAuthenticationTruePrincipalString() throws Exception {
174+
Object currentPrincipal = "currentUser";
175+
TestingAuthenticationToken authRequest = new TestingAuthenticationToken(currentPrincipal, "something", "ROLE_USER");
176+
SecurityContextHolder.getContext().setAuthentication(authRequest);
177+
MockHttpServletRequest request = new MockHttpServletRequest();
178+
MockHttpServletResponse response = new MockHttpServletResponse();
179+
MockFilterChain chain = new MockFilterChain();
180+
181+
ConcretePreAuthenticatedProcessingFilter filter = new ConcretePreAuthenticatedProcessingFilter();
182+
filter.setCheckForPrincipalChanges(true);
183+
filter.principal = "newUser";
184+
AuthenticationManager am = mock(AuthenticationManager.class);
185+
filter.setAuthenticationManager(am);
186+
filter.afterPropertiesSet();
187+
188+
filter.doFilter(request, response, chain);
189+
190+
verify(am).authenticate(any(PreAuthenticatedAuthenticationToken.class));
191+
}
192+
193+
// SEC-2078
194+
@Test
195+
public void requiresAuthenticationFalsePrincipalNotString() throws Exception {
196+
Object principal = new Object();
197+
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken(principal, "something", "ROLE_USER"));
198+
MockHttpServletRequest request = new MockHttpServletRequest();
199+
MockHttpServletResponse response = new MockHttpServletResponse();
200+
MockFilterChain chain = new MockFilterChain();
201+
202+
ConcretePreAuthenticatedProcessingFilter filter = new ConcretePreAuthenticatedProcessingFilter();
203+
filter.setCheckForPrincipalChanges(true);
204+
filter.principal = principal;
205+
AuthenticationManager am = mock(AuthenticationManager.class);
206+
filter.setAuthenticationManager(am);
207+
filter.afterPropertiesSet();
208+
209+
filter.doFilter(request, response, chain);
210+
211+
verifyZeroInteractions(am);
212+
}
213+
214+
@Test
215+
public void requiresAuthenticationFalsePrincipalUser() throws Exception {
216+
User currentPrincipal = new User("user","password", AuthorityUtils.createAuthorityList("ROLE_USER"));
217+
UsernamePasswordAuthenticationToken currentAuthentication = new UsernamePasswordAuthenticationToken(
218+
currentPrincipal, currentPrincipal.getPassword(), currentPrincipal.getAuthorities());
219+
SecurityContextHolder.getContext().setAuthentication(currentAuthentication);
220+
MockHttpServletRequest request = new MockHttpServletRequest();
221+
MockHttpServletResponse response = new MockHttpServletResponse();
222+
MockFilterChain chain = new MockFilterChain();
223+
224+
ConcretePreAuthenticatedProcessingFilter filter = new ConcretePreAuthenticatedProcessingFilter();
225+
filter.setCheckForPrincipalChanges(true);
226+
filter.principal = new User(currentPrincipal.getUsername(), currentPrincipal.getPassword(), AuthorityUtils.NO_AUTHORITIES);
227+
AuthenticationManager am = mock(AuthenticationManager.class);
228+
filter.setAuthenticationManager(am);
229+
filter.afterPropertiesSet();
230+
231+
filter.doFilter(request, response, chain);
232+
233+
verifyZeroInteractions(am);
234+
}
235+
236+
@Test
237+
public void requiresAuthenticationTruePrincipalNotString() throws Exception {
238+
Object currentPrincipal = new Object();
239+
TestingAuthenticationToken authRequest = new TestingAuthenticationToken(currentPrincipal, "something", "ROLE_USER");
240+
SecurityContextHolder.getContext().setAuthentication(authRequest);
241+
MockHttpServletRequest request = new MockHttpServletRequest();
242+
MockHttpServletResponse response = new MockHttpServletResponse();
243+
MockFilterChain chain = new MockFilterChain();
244+
245+
ConcretePreAuthenticatedProcessingFilter filter = new ConcretePreAuthenticatedProcessingFilter();
246+
filter.setCheckForPrincipalChanges(true);
247+
filter.principal = new Object();
248+
AuthenticationManager am = mock(AuthenticationManager.class);
249+
filter.setAuthenticationManager(am);
250+
filter.afterPropertiesSet();
251+
252+
filter.doFilter(request, response, chain);
253+
254+
verify(am).authenticate(any(PreAuthenticatedAuthenticationToken.class));
255+
}
256+
126257
private void testDoFilter(boolean grantAccess) throws Exception {
127258
MockHttpServletRequest req = new MockHttpServletRequest();
128259
MockHttpServletResponse res = new MockHttpServletResponse();
@@ -150,7 +281,7 @@ public Authentication answer(InvocationOnMock invocation) throws Throwable {
150281
}
151282

152283
private static class ConcretePreAuthenticatedProcessingFilter extends AbstractPreAuthenticatedProcessingFilter {
153-
private String principal = "testPrincipal";
284+
private Object principal = "testPrincipal";
154285
private boolean initFilterBeanInvoked;
155286
protected Object getPreAuthenticatedPrincipal(HttpServletRequest httpRequest) {
156287
return principal;

0 commit comments

Comments
 (0)