Skip to content

Commit 750cb30

Browse files
rwinchmarcusdacoregio
authored andcommitted
Add AuthenticationTrustResolver.isAuthenticated
1 parent 3093908 commit 750cb30

File tree

16 files changed

+123
-26
lines changed

16 files changed

+123
-26
lines changed

cas/src/main/java/org/springframework/security/cas/web/CasAuthenticationFilter.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,9 @@
2727
import org.apereo.cas.client.validation.TicketValidator;
2828

2929
import org.springframework.core.log.LogMessage;
30-
import org.springframework.security.authentication.AnonymousAuthenticationToken;
3130
import org.springframework.security.authentication.AuthenticationDetailsSource;
31+
import org.springframework.security.authentication.AuthenticationTrustResolver;
32+
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
3233
import org.springframework.security.authentication.event.InteractiveAuthenticationSuccessEvent;
3334
import org.springframework.security.cas.ServiceProperties;
3435
import org.springframework.security.cas.authentication.CasServiceTicketAuthenticationToken;
@@ -195,6 +196,8 @@ public class CasAuthenticationFilter extends AbstractAuthenticationProcessingFil
195196

196197
private SecurityContextRepository securityContextRepository = new HttpSessionSecurityContextRepository();
197198

199+
private final AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
200+
198201
public CasAuthenticationFilter() {
199202
super("/login/cas");
200203
setAuthenticationFailureHandler(new SimpleUrlAuthenticationFailureHandler());
@@ -337,8 +340,7 @@ private boolean proxyTicketRequest(boolean serviceTicketRequest, HttpServletRequ
337340
*/
338341
private boolean authenticated() {
339342
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
340-
return authentication != null && authentication.isAuthenticated()
341-
&& !(authentication instanceof AnonymousAuthenticationToken);
343+
return this.trustResolver.isAuthenticated(authentication);
342344
}
343345

344346
/**

config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerTests.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import jakarta.servlet.http.HttpSession;
3030
import org.junit.jupiter.api.Test;
3131
import org.junit.jupiter.api.extension.ExtendWith;
32+
import org.mockito.Answers;
3233

3334
import org.springframework.beans.factory.annotation.Autowired;
3435
import org.springframework.context.annotation.Bean;
@@ -82,6 +83,7 @@
8283
import static org.mockito.Mockito.spy;
8384
import static org.mockito.Mockito.verify;
8485
import static org.mockito.Mockito.verifyNoInteractions;
86+
import static org.mockito.Mockito.withSettings;
8587
import static org.springframework.security.config.Customizer.withDefaults;
8688
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
8789
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic;
@@ -304,7 +306,8 @@ public void configureWhenRegisteringObjectPostProcessorThenInvokedOnChangeSessio
304306
@Test
305307
public void getWhenAnonymousRequestAndTrustResolverSharedObjectReturnsAnonymousFalseThenSessionIsSaved()
306308
throws Exception {
307-
SharedTrustResolverConfig.TR = mock(AuthenticationTrustResolver.class);
309+
SharedTrustResolverConfig.TR = mock(AuthenticationTrustResolver.class,
310+
withSettings().defaultAnswer(Answers.CALLS_REAL_METHODS));
308311
given(SharedTrustResolverConfig.TR.isAnonymous(any())).willReturn(false);
309312
this.spring.register(SharedTrustResolverConfig.class).autowire();
310313
MvcResult mvcResult = this.mvc.perform(get("/")).andReturn();

config/src/test/kotlin/org/springframework/security/config/annotation/web/SessionManagementDslTests.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import org.springframework.beans.factory.annotation.Autowired
2828
import org.springframework.context.annotation.Bean
2929
import org.springframework.context.annotation.Configuration
3030
import org.springframework.mock.web.MockHttpSession
31+
import org.springframework.security.authentication.TestingAuthenticationToken
3132
import org.springframework.security.config.annotation.web.builders.HttpSecurity
3233
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
3334
import org.springframework.security.config.http.SessionCreationPolicy
@@ -118,7 +119,7 @@ class SessionManagementDslTests {
118119
@Test
119120
fun `session management when session authentication error url then redirected to url`() {
120121
this.spring.register(SessionAuthenticationErrorUrlConfig::class.java).autowire()
121-
val authentication: Authentication = mockk()
122+
val authentication: Authentication = TestingAuthenticationToken("user", "password", "ROLE_USER")
122123
val session: MockHttpSession = mockk(relaxed = true)
123124
every { session.changeSessionId() } throws SessionAuthenticationException("any SessionAuthenticationException")
124125
every<Any?> { session.getAttribute(any()) } returns null
@@ -150,7 +151,7 @@ class SessionManagementDslTests {
150151
@Test
151152
fun `session management when session authentication failure handler then handler used`() {
152153
this.spring.register(SessionAuthenticationFailureHandlerConfig::class.java).autowire()
153-
val authentication: Authentication = mockk()
154+
val authentication: Authentication = TestingAuthenticationToken("user", "password", "ROLE_USER")
154155
val session: MockHttpSession = mockk(relaxed = true)
155156
every { session.changeSessionId() } throws SessionAuthenticationException("any SessionAuthenticationException")
156157
every<Any?> { session.getAttribute(any()) } returns null
@@ -210,7 +211,7 @@ class SessionManagementDslTests {
210211
fun `session management when session authentication strategy then strategy used`() {
211212
this.spring.register(SessionAuthenticationStrategyConfig::class.java).autowire()
212213
mockkObject(SessionAuthenticationStrategyConfig.STRATEGY)
213-
val authentication: Authentication = mockk(relaxed = true)
214+
val authentication: Authentication = TestingAuthenticationToken("user", "password", "ROLE_USER")
214215
val session: MockHttpSession = mockk(relaxed = true)
215216
every { session.changeSessionId() } throws SessionAuthenticationException("any SessionAuthenticationException")
216217
every<Any?> { session.getAttribute(any()) } returns null

core/src/main/java/org/springframework/security/access/expression/SecurityExpressionRoot.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ public final boolean isAnonymous() {
147147

148148
@Override
149149
public final boolean isAuthenticated() {
150-
return !isAnonymous();
150+
return this.trustResolver.isAuthenticated(getAuthentication());
151151
}
152152

153153
@Override

core/src/main/java/org/springframework/security/authentication/AuthenticationTrustResolver.java

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,25 @@ public interface AuthenticationTrustResolver {
6161
* <p>
6262
* @param authentication to test (may be <code>null</code> in which case the method
6363
* will always return <code>false</code>)
64-
* @return <code>true</code> the passed authentication token represented an anonymous
65-
* principal and is authenticated using a remember-me token, <code>false</code>
66-
* otherwise
64+
* @return <code>true</code> the passed authentication token represented an
65+
* authenticated user ({@link #isAuthenticated(Authentication)} and not
66+
* {@link #isRememberMe(Authentication)}, <code>false</code> otherwise
6767
* @since 6.1
6868
*/
6969
default boolean isFullyAuthenticated(Authentication authentication) {
70-
return !isAnonymous(authentication) && !isRememberMe(authentication);
70+
return isAuthenticated(authentication) && !isRememberMe(authentication);
71+
}
72+
73+
/**
74+
* Checks if the {@link Authentication} is not null, authenticated, and not anonymous.
75+
* @param authentication the {@link Authentication} to check.
76+
* @return true if the {@link Authentication} is not null,
77+
* {@link #isAnonymous(Authentication)} returns false, &
78+
* {@link Authentication#isAuthenticated()} is true.
79+
* @since 6.1.7
80+
*/
81+
default boolean isAuthenticated(Authentication authentication) {
82+
return authentication != null && authentication.isAuthenticated() && !isAnonymous(authentication);
7183
}
7284

7385
}

core/src/main/java/org/springframework/security/authorization/AuthenticatedAuthorizationManager.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,7 @@ private static class AuthenticatedAuthorizationStrategy extends AbstractAuthoriz
133133

134134
@Override
135135
boolean isGranted(Authentication authentication) {
136-
return authentication != null && !this.trustResolver.isAnonymous(authentication)
137-
&& authentication.isAuthenticated();
136+
return this.trustResolver.isAuthenticated(authentication);
138137
}
139138

140139
}
@@ -143,7 +142,7 @@ private static final class FullyAuthenticatedAuthorizationStrategy extends Authe
143142

144143
@Override
145144
boolean isGranted(Authentication authentication) {
146-
return authentication != null && this.trustResolver.isFullyAuthenticated(authentication);
145+
return this.trustResolver.isFullyAuthenticated(authentication);
147146
}
148147

149148
}

core/src/test/java/org/springframework/security/access/expression/SecurityExpressionRootTests.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.springframework.security.core.authority.AuthorityUtils;
2626

2727
import static org.assertj.core.api.Assertions.assertThat;
28+
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
2829
import static org.mockito.BDDMockito.given;
2930
import static org.mockito.Mockito.mock;
3031

@@ -134,4 +135,27 @@ public void hasAuthorityDoesNotAddDefaultPrefix() {
134135
assertThat(this.root.hasAnyAuthority("ROLE_A", "NOT")).isTrue();
135136
}
136137

138+
@Test
139+
void isAuthenticatedWhenAuthenticatedNullThenException() {
140+
this.root = new SecurityExpressionRoot((Authentication) null) {
141+
};
142+
assertThatIllegalArgumentException().isThrownBy(() -> this.root.isAuthenticated());
143+
}
144+
145+
@Test
146+
void isAuthenticatedWhenTrustResolverFalseThenFalse() {
147+
AuthenticationTrustResolver atr = mock(AuthenticationTrustResolver.class);
148+
given(atr.isAuthenticated(JOE)).willReturn(false);
149+
this.root.setTrustResolver(atr);
150+
assertThat(this.root.isAuthenticated()).isFalse();
151+
}
152+
153+
@Test
154+
void isAuthenticatedWhenTrustResolverTrueThenTrue() {
155+
AuthenticationTrustResolver atr = mock(AuthenticationTrustResolver.class);
156+
given(atr.isAuthenticated(JOE)).willReturn(true);
157+
this.root.setTrustResolver(atr);
158+
assertThat(this.root.isAuthenticated()).isTrue();
159+
}
160+
137161
}

core/src/test/java/org/springframework/security/authentication/AuthenticationTrustResolverImplTests.java

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import org.junit.jupiter.api.Test;
2020

21+
import org.springframework.security.core.Authentication;
2122
import org.springframework.security.core.authority.AuthorityUtils;
2223

2324
import static org.assertj.core.api.Assertions.assertThat;
@@ -63,4 +64,56 @@ public void testGettersSetters() {
6364
assertThat(trustResolver.getRememberMeClass()).isEqualTo(TestingAuthenticationToken.class);
6465
}
6566

67+
@Test
68+
void isAuthenticatedWhenAuthenticationNullThenFalse() {
69+
AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
70+
Authentication authentication = null;
71+
assertThat(trustResolver.isAuthenticated(authentication)).isFalse();
72+
}
73+
74+
@Test
75+
void isAuthenticatedWhenAuthenticationNotAuthenticatedThenFalse() {
76+
AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
77+
TestingAuthenticationToken authentication = new TestingAuthenticationToken("user", "password");
78+
assertThat(trustResolver.isAuthenticated(authentication)).isFalse();
79+
}
80+
81+
@Test
82+
void isAuthenticatedWhenAnonymousThenFalse() {
83+
AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
84+
AnonymousAuthenticationToken authentication = new AnonymousAuthenticationToken("key", "principal",
85+
AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"));
86+
assertThat(trustResolver.isAuthenticated(authentication)).isFalse();
87+
}
88+
89+
@Test
90+
void isFullyAuthenticatedWhenAuthenticationNullThenFalse() {
91+
AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
92+
Authentication authentication = null;
93+
assertThat(trustResolver.isFullyAuthenticated(authentication)).isFalse();
94+
}
95+
96+
@Test
97+
void isFullyAuthenticatedWhenAuthenticationNotAuthenticatedThenFalse() {
98+
AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
99+
TestingAuthenticationToken authentication = new TestingAuthenticationToken("user", "password");
100+
assertThat(trustResolver.isFullyAuthenticated(authentication)).isFalse();
101+
}
102+
103+
@Test
104+
void isFullyAuthenticatedWhenAnonymousThenFalse() {
105+
AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
106+
AnonymousAuthenticationToken authentication = new AnonymousAuthenticationToken("key", "principal",
107+
AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"));
108+
assertThat(trustResolver.isFullyAuthenticated(authentication)).isFalse();
109+
}
110+
111+
@Test
112+
void isFullyAuthenticatedWhenRememberMeThenFalse() {
113+
AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
114+
RememberMeAuthenticationToken authentication = new RememberMeAuthenticationToken("key", "user",
115+
AuthorityUtils.createAuthorityList("ROLE_USER"));
116+
assertThat(trustResolver.isFullyAuthenticated(authentication)).isFalse();
117+
}
118+
66119
}

messaging/src/test/java/org/springframework/security/messaging/access/expression/DefaultMessageSecurityExpressionHandlerTests.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.junit.jupiter.api.BeforeEach;
2323
import org.junit.jupiter.api.Test;
2424
import org.junit.jupiter.api.extension.ExtendWith;
25+
import org.mockito.Answers;
2526
import org.mockito.Mock;
2627
import org.mockito.junit.jupiter.MockitoExtension;
2728

@@ -50,7 +51,7 @@
5051
@ExtendWith(MockitoExtension.class)
5152
public class DefaultMessageSecurityExpressionHandlerTests {
5253

53-
@Mock
54+
@Mock(answer = Answers.CALLS_REAL_METHODS)
5455
AuthenticationTrustResolver trustResolver;
5556

5657
@Mock

oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/AuthenticatedPrincipalOAuth2AuthorizedClientRepository.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,7 @@ public void removeAuthorizedClient(String clientRegistrationId, Authentication p
107107
}
108108

109109
private boolean isPrincipalAuthenticated(Authentication authentication) {
110-
return authentication != null && !this.authenticationTrustResolver.isAnonymous(authentication)
111-
&& authentication.isAuthenticated();
110+
return this.authenticationTrustResolver.isAuthenticated(authentication);
112111
}
113112

114113
}

oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,7 @@ public Mono<Void> removeAuthorizedClient(String clientRegistrationId, Authentica
106106
}
107107

108108
private boolean isPrincipalAuthenticated(Authentication authentication) {
109-
return authentication != null && !this.authenticationTrustResolver.isAnonymous(authentication)
110-
&& authentication.isAuthenticated();
109+
return this.authenticationTrustResolver.isAuthenticated(authentication);
111110
}
112111

113112
}

web/src/main/java/org/springframework/security/web/server/authorization/ExceptionTranslationWebFilter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
5252
return chain.filter(exchange)
5353
.onErrorResume(AccessDeniedException.class, (denied) -> exchange.getPrincipal()
5454
.filter((principal) -> (!(principal instanceof Authentication) || (principal instanceof Authentication
55-
&& !(this.authenticationTrustResolver.isAnonymous((Authentication) principal)))))
55+
&& (this.authenticationTrustResolver.isAuthenticated((Authentication) principal)))))
5656
.switchIfEmpty(commenceAuthentication(exchange,
5757
new InsufficientAuthenticationException(
5858
"Full authentication is required to access this resource")))

web/src/main/java/org/springframework/security/web/servletapi/SecurityContextHolderAwareRequestWrapper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ public SecurityContextHolderAwareRequestWrapper(HttpServletRequest request,
9393
*/
9494
private Authentication getAuthentication() {
9595
Authentication auth = this.securityContextHolderStrategy.getContext().getAuthentication();
96-
return (!this.trustResolver.isAnonymous(auth)) ? auth : null;
96+
return (this.trustResolver.isAuthenticated(auth)) ? auth : null;
9797
}
9898

9999
/**

web/src/main/java/org/springframework/security/web/session/SessionManagementFilter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ private void doFilter(HttpServletRequest request, HttpServletResponse response,
9494
request.setAttribute(FILTER_APPLIED, Boolean.TRUE);
9595
if (!this.securityContextRepository.containsContext(request)) {
9696
Authentication authentication = this.securityContextHolderStrategy.getContext().getAuthentication();
97-
if (authentication != null && !this.trustResolver.isAnonymous(authentication)) {
97+
if (this.trustResolver.isAuthenticated(authentication)) {
9898
// The user has been authenticated during the current request, so call the
9999
// session strategy
100100
try {

web/src/test/java/org/springframework/security/web/servletapi/SecurityContextHolderAwareRequestWrapperTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ public void testGetRemoteUserStringWithAuthenticatedPrincipal() {
140140
String username = "authPrincipalUsername";
141141
AuthenticatedPrincipal principal = mock(AuthenticatedPrincipal.class);
142142
given(principal.getName()).willReturn(username);
143-
Authentication auth = new TestingAuthenticationToken(principal, "user");
143+
Authentication auth = new TestingAuthenticationToken(principal, "user", "ROLE_USER");
144144
SecurityContextHolder.getContext().setAuthentication(auth);
145145
MockHttpServletRequest request = new MockHttpServletRequest();
146146
request.setRequestURI("/");

web/src/test/java/org/springframework/security/web/session/SessionManagementFilterTests.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import jakarta.servlet.http.HttpServletResponse;
2222
import org.junit.jupiter.api.AfterEach;
2323
import org.junit.jupiter.api.Test;
24+
import org.mockito.Answers;
2425

2526
import org.springframework.mock.web.MockFilterChain;
2627
import org.springframework.mock.web.MockHttpServletRequest;
@@ -42,6 +43,7 @@
4243
import static org.mockito.Mockito.mock;
4344
import static org.mockito.Mockito.verify;
4445
import static org.mockito.Mockito.verifyNoMoreInteractions;
46+
import static org.mockito.Mockito.withSettings;
4547

4648
/**
4749
* @author Luke Taylor
@@ -176,7 +178,8 @@ public void responseIsRedirectedToRequestedUrlIfSetAndSessionIsInvalid() throws
176178

177179
@Test
178180
public void customAuthenticationTrustResolver() throws Exception {
179-
AuthenticationTrustResolver trustResolver = mock(AuthenticationTrustResolver.class);
181+
AuthenticationTrustResolver trustResolver = mock(AuthenticationTrustResolver.class,
182+
withSettings().defaultAnswer(Answers.CALLS_REAL_METHODS));
180183
SecurityContextRepository repo = mock(SecurityContextRepository.class);
181184
SessionManagementFilter filter = new SessionManagementFilter(repo);
182185
filter.setTrustResolver(trustResolver);
@@ -194,7 +197,8 @@ public void setTrustResolverNull() {
194197
}
195198

196199
private void authenticateUser() {
197-
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "pass"));
200+
SecurityContextHolder.getContext()
201+
.setAuthentication(new TestingAuthenticationToken("user", "pass", "ROLE_USER"));
198202
}
199203

200204
}

0 commit comments

Comments
 (0)