|
@@ -17,7 +17,9 @@
|
|
|
package org.springframework.security.web.authentication;
|
|
|
|
|
|
import java.io.IOException;
|
|
|
+import java.util.ArrayList;
|
|
|
import java.util.Collections;
|
|
|
+import java.util.List;
|
|
|
|
|
|
import jakarta.servlet.FilterChain;
|
|
|
import jakarta.servlet.ServletException;
|
|
@@ -27,9 +29,15 @@ import org.springframework.mock.web.MockHttpServletRequest;
|
|
|
import org.springframework.mock.web.MockHttpServletResponse;
|
|
|
import org.springframework.security.authentication.BadCredentialsException;
|
|
|
import org.springframework.security.authentication.TestAuthentication;
|
|
|
+import org.springframework.security.authorization.AuthorizationDeniedException;
|
|
|
+import org.springframework.security.authorization.FactorAuthorizationDecision;
|
|
|
+import org.springframework.security.authorization.RequiredFactor;
|
|
|
+import org.springframework.security.authorization.RequiredFactorError;
|
|
|
+import org.springframework.security.core.GrantedAuthorities;
|
|
|
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
|
|
import org.springframework.security.core.context.SecurityContextImpl;
|
|
|
import org.springframework.security.web.WebAttributes;
|
|
|
+import org.springframework.security.web.access.DelegatingMissingAuthorityAccessDeniedHandler;
|
|
|
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
|
|
|
import org.springframework.security.web.servlet.TestMockHttpServletRequests;
|
|
|
|
|
@@ -204,8 +212,9 @@ public class DefaultLoginPageGeneratingFilterTests {
|
|
|
filter.setOneTimeTokenEnabled(true);
|
|
|
filter.setOneTimeTokenGenerationUrl("/ott/authenticate");
|
|
|
MockHttpServletResponse response = new MockHttpServletResponse();
|
|
|
- filter.doFilter(TestMockHttpServletRequests.get("/login?factor.type=ott&factor.reason=missing").build(),
|
|
|
- response, this.chain);
|
|
|
+ MockHttpServletRequest loginRequest = createLoginRequestFromMissingAuthority(
|
|
|
+ GrantedAuthorities.FACTOR_OTT_AUTHORITY);
|
|
|
+ filter.doFilter(loginRequest, response, this.chain);
|
|
|
assertThat(response.getContentAsString()).contains("Request a One-Time Token");
|
|
|
assertThat(response.getContentAsString()).contains("""
|
|
|
<form id="ott-form" class="login-form" method="post" action="/ott/authenticate">
|
|
@@ -251,6 +260,24 @@ public class DefaultLoginPageGeneratingFilterTests {
|
|
|
assertThat(response.getContentAsString()).contains("Password");
|
|
|
}
|
|
|
|
|
|
+ private MockHttpServletRequest createLoginRequestFromMissingAuthority(String factorAuthority)
|
|
|
+ throws ServletException, IOException {
|
|
|
+ LoginUrlAuthenticationEntryPoint entryPoint = new LoginUrlAuthenticationEntryPoint("/login");
|
|
|
+ List<RequiredFactorError> factorErrors = new ArrayList<>();
|
|
|
+ DelegatingMissingAuthorityAccessDeniedHandler.Builder handlerBldr = DelegatingMissingAuthorityAccessDeniedHandler
|
|
|
+ .builder();
|
|
|
+ handlerBldr.addEntryPointFor(entryPoint, factorAuthority);
|
|
|
+ RequiredFactor requiredFactor = RequiredFactor.withAuthority(factorAuthority).build();
|
|
|
+ RequiredFactorError factorError = RequiredFactorError.createMissing(requiredFactor);
|
|
|
+ factorErrors.add(factorError);
|
|
|
+ DelegatingMissingAuthorityAccessDeniedHandler handler = handlerBldr.build();
|
|
|
+ MockHttpServletRequest request = new MockHttpServletRequest();
|
|
|
+ MockHttpServletResponse response = new MockHttpServletResponse();
|
|
|
+ FactorAuthorizationDecision decision = new FactorAuthorizationDecision(factorErrors);
|
|
|
+ handler.handle(request, response, new AuthorizationDeniedException("", decision));
|
|
|
+ return TestMockHttpServletRequests.get(response.getRedirectedUrl()).build();
|
|
|
+ }
|
|
|
+
|
|
|
@Test
|
|
|
public void generateWhenAuthenticatedThenReadOnlyUsername() throws Exception {
|
|
|
SecurityContextHolderStrategy strategy = mock(SecurityContextHolderStrategy.class);
|