diff --git a/config/src/main/kotlin/org/springframework/security/config/annotation/web/AuthorizeHttpRequestsDsl.kt b/config/src/main/kotlin/org/springframework/security/config/annotation/web/AuthorizeHttpRequestsDsl.kt index 64249d7c80a..0133670a18f 100644 --- a/config/src/main/kotlin/org/springframework/security/config/annotation/web/AuthorizeHttpRequestsDsl.kt +++ b/config/src/main/kotlin/org/springframework/security/config/annotation/web/AuthorizeHttpRequestsDsl.kt @@ -275,6 +275,13 @@ class AuthorizeHttpRequestsDsl : AbstractRequestMatcherDsl { val authenticated: AuthorizationManager = AuthenticatedAuthorizationManager.authenticated() + /** + * Specify that URLs are allowed by users who have authenticated and were not "remembered". + * @since 6.5 + */ + val fullyAuthenticated: AuthorizationManager = + AuthenticatedAuthorizationManager.fullyAuthenticated() + internal fun get(): (AuthorizeHttpRequestsConfigurer.AuthorizationManagerRequestMatcherRegistry) -> Unit { return { requests -> authorizationRules.forEach { rule -> diff --git a/config/src/test/kotlin/org/springframework/security/config/annotation/web/AuthorizeHttpRequestsDslTests.kt b/config/src/test/kotlin/org/springframework/security/config/annotation/web/AuthorizeHttpRequestsDslTests.kt index 5a124b2f973..f103344bcf6 100644 --- a/config/src/test/kotlin/org/springframework/security/config/annotation/web/AuthorizeHttpRequestsDslTests.kt +++ b/config/src/test/kotlin/org/springframework/security/config/annotation/web/AuthorizeHttpRequestsDslTests.kt @@ -27,6 +27,8 @@ import org.springframework.context.annotation.Configuration import org.springframework.http.HttpMethod import org.springframework.security.access.hierarchicalroles.RoleHierarchy import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl +import org.springframework.security.authentication.RememberMeAuthenticationToken +import org.springframework.security.authentication.TestAuthentication import org.springframework.security.authorization.AuthorizationDecision import org.springframework.security.authorization.AuthorizationManager import org.springframework.security.config.annotation.web.builders.HttpSecurity @@ -35,11 +37,12 @@ import org.springframework.security.config.core.GrantedAuthorityDefaults import org.springframework.security.config.test.SpringTestContext import org.springframework.security.config.test.SpringTestContextExtension import org.springframework.security.core.Authentication +import org.springframework.security.core.authority.AuthorityUtils import org.springframework.security.core.userdetails.User import org.springframework.security.core.userdetails.UserDetailsService import org.springframework.security.provisioning.InMemoryUserDetailsManager -import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf -import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic +import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors +import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.* import org.springframework.security.web.SecurityFilterChain import org.springframework.security.web.access.intercept.RequestAuthorizationContext import org.springframework.security.web.util.matcher.RegexRequestMatcher @@ -961,4 +964,63 @@ class AuthorizeHttpRequestsDslTests { } } + + @Test + fun `request when fully authenticated configured then responds ok`() { + this.spring.register(FullyAuthenticatedConfig::class.java).autowire() + + this.mockMvc.post("/path") { + with(SecurityMockMvcRequestPostProcessors.user("user").roles("USER")) + with(csrf()) + }.andExpect { + status { + isOk() + } + } + } + + @Test + fun `request when fully authenticated configured and remember-me token then responds unauthorized`() { + this.spring.register(FullyAuthenticatedConfig::class.java).autowire() + val rememberMe = RememberMeAuthenticationToken("key", "user", + AuthorityUtils.createAuthorityList("ROLE_USER")) + + this.mockMvc.post("/path") { + with(SecurityMockMvcRequestPostProcessors.user("user").roles("USER")) + with(csrf()) + with(authentication(rememberMe)) + }.andExpect { + status { + isUnauthorized() + } + } + } + + @Configuration + @EnableWebSecurity + @EnableWebMvc + open class FullyAuthenticatedConfig { + @Bean + open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain { + http { + authorizeHttpRequests { + authorize("/path", fullyAuthenticated) + } + httpBasic { } + rememberMe { } + } + return http.build() + } + + @Bean + open fun userDetailsService(): UserDetailsService = InMemoryUserDetailsManager(TestAuthentication.user()) + + @RestController + internal class PathController { + @RequestMapping("/path") + fun path(): String { + return "ok" + } + } + } }