Skip to content

Commit

Permalink
Add setRequestMatcher to PublicKeyCredentialCreationOptionsFilter
Browse files Browse the repository at this point in the history
Closes spring-projectsgh-16517

Signed-off-by: smallbun <[email protected]>
  • Loading branch information
topiam authored and jzheaux committed Feb 25, 2025
1 parent eb5252c commit 1a4b550
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,17 @@ public PublicKeyCredentialRequestOptionsFilter(WebAuthnRelyingPartyOperations rp
this.rpOptions = rpOptions;
}

/**
* Sets the {@link RequestMatcher} used to trigger this filter. By default, the
* {@link RequestMatcher} is {@code POST /webauthn/authenticate/options}.
* @param requestMatcher the {@link RequestMatcher} to use
* @since 6.5
*/
public void setRequestMatcher(RequestMatcher requestMatcher) {
Assert.notNull(requestMatcher, "requestMatcher cannot be null");
this.matcher = requestMatcher;
}

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,18 @@ public PublicKeyCredentialCreationOptionsFilter(WebAuthnRelyingPartyOperations r
this.rpOperations = rpOperations;
}

/**
* Sets the {@link RequestMatcher} used to trigger this filter.
* <p>
* By default, the {@link RequestMatcher} is {@code POST /webauthn/register/options}.
* @param requestMatcher the {@link RequestMatcher} to use
* @since 6.5
*/
public void setRequestMatcher(RequestMatcher requestMatcher) {
Assert.notNull(requestMatcher, "requestMatcher cannot be null");
this.matcher = requestMatcher;
}

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,32 @@ public WebAuthnRegistrationFilter(UserCredentialRepository userCredentials,
this.rpOptions = rpOptions;
}

/**
* Sets the {@link RequestMatcher} to trigger this filter's the credential
* registration operation .
* <p/>
* By default, the {@link RequestMatcher} is {@code POST /webauthn/register}.
* @param registerCredentialMatcher the {@link RequestMatcher} to use
* @since 6.5
*/
public void setRegisterCredentialMatcher(RequestMatcher registerCredentialMatcher) {
Assert.notNull(registerCredentialMatcher, "registerCredentialMatcher cannot be null");
this.registerCredentialMatcher = registerCredentialMatcher;
}

/**
* Sets the {@link RequestMatcher} to trigger this filter's the credential removal
* operation .
* <p/>
* By default, the {@link RequestMatcher} is {@code DELETE /webauthn/register/{id}}.
* @param removeCredentialMatcher the {@link RequestMatcher} to use
* @since 6.5
*/
public void setRemoveCredentialMatcher(RequestMatcher removeCredentialMatcher) {
Assert.notNull(removeCredentialMatcher, "removeCredentialMatcher cannot be null");
this.removeCredentialMatcher = removeCredentialMatcher;
}

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import java.nio.charset.StandardCharsets;

import jakarta.servlet.FilterChain;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
Expand All @@ -30,10 +31,13 @@

import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.security.web.webauthn.api.PublicKeyCredentialCreationOptions;
import org.springframework.security.web.webauthn.api.PublicKeyCredentialRequestOptions;
import org.springframework.security.web.webauthn.api.TestPublicKeyCredentialRequestOptions;
Expand All @@ -48,6 +52,7 @@
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.verifyNoInteractions;
import static org.mockito.BDDMockito.willAnswer;
import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
Expand Down Expand Up @@ -75,20 +80,35 @@ class PublicKeyCredentialRequestOptionsFilterTests {

private PublicKeyCredentialRequestOptionsFilter filter;

private MockHttpServletRequest request;

private MockHttpServletResponse response;

private MockMvc mockMvc;

@BeforeEach
void setup() {
this.filter = new PublicKeyCredentialRequestOptionsFilter(this.relyingPartyOperations);
this.filter.setRequestOptionsRepository(this.requestOptionsRepository);
this.mockMvc = MockMvcBuilders.standaloneSetup().addFilter(this.filter).build();
this.request = new MockHttpServletRequest();
this.response = new MockHttpServletResponse();
}

@AfterEach
void cleanup() {
SecurityContextHolder.clearContext();
}

@Test
public void doFilterWhenCustomRequestMatcherThenUses() throws Exception {
RequestMatcher requestMatcher = mock(RequestMatcher.class);
this.filter.setRequestMatcher(requestMatcher);
FilterChain mock = mock(FilterChain.class);
this.filter.doFilter(request, response, mock);
verify(requestMatcher).matches(any());
}

@Test
void constructorWhenNull() {
assertThatExceptionOfType(IllegalArgumentException.class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@

import java.util.Arrays;

import jakarta.servlet.FilterChain;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
Expand All @@ -27,12 +29,14 @@
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.security.web.webauthn.api.AuthenticatorTransport;
import org.springframework.security.web.webauthn.api.Bytes;
import org.springframework.security.web.webauthn.api.PublicKeyCredentialCreationOptions;
Expand All @@ -47,7 +51,7 @@
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
Expand All @@ -68,11 +72,38 @@ class PublicKeyCredentialCreationOptionsFilterTests {
@Mock
private WebAuthnRelyingPartyOperations rpOperations;

private PublicKeyCredentialCreationOptionsFilter filter;

private MockHttpServletRequest request;

private MockHttpServletResponse response;

@BeforeEach
public void setup() {
this.filter = new PublicKeyCredentialCreationOptionsFilter(this.rpOperations);
this.request = new MockHttpServletRequest();
this.response = new MockHttpServletResponse();
}

@AfterEach
void clear() {
SecurityContextHolder.clearContext();
}

@Test
public void doFilterWhenCustomRequestMatcherThenUses() throws Exception {
RequestMatcher requestMatcher = mock(RequestMatcher.class);
this.filter.setRequestMatcher(requestMatcher);
FilterChain mock = mock(FilterChain.class);
this.filter.doFilter(request, response, mock);
verify(requestMatcher).matches(any());
}

@Test
public void setRequestMatcherWhenNullThenIllegalArgument() {
assertThatIllegalArgumentException().isThrownBy(() -> this.filter.setRequestMatcher(null));
}

@Test
void constructorWhenRpOperationsIsNullThenIllegalArgumentException() {
assertThatIllegalArgumentException().isThrownBy(() -> new PublicKeyCredentialCreationOptionsFilter(null))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockServletContext;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.security.web.webauthn.api.ImmutableCredentialRecord;
import org.springframework.security.web.webauthn.api.PublicKeyCredentialCreationOptions;
import org.springframework.security.web.webauthn.api.TestCredentialRecord;
Expand Down Expand Up @@ -100,9 +101,42 @@ class WebAuthnRegistrationFilterTests {

private WebAuthnRegistrationFilter filter;

private MockHttpServletRequest request;

@BeforeEach
void setup() {
this.filter = new WebAuthnRegistrationFilter(this.userCredentials, this.operations);
this.request = new MockHttpServletRequest();
this.response = new MockHttpServletResponse();
this.chain = mock(FilterChain.class);
}

@Test
public void doFilterWhenCustomRequestRegisterCredentialMatcherThenUses() throws Exception {
RequestMatcher requestMatcher = mock(RequestMatcher.class);
this.filter.setRegisterCredentialMatcher(requestMatcher);
FilterChain mock = mock(FilterChain.class);
this.filter.doFilter(request, response, mock);
verify(requestMatcher).matches(any());
}

@Test
public void doFilterWhenCustomRequestRemoveCredentialMatcherThenUses() throws Exception {
RequestMatcher requestMatcher = mock(RequestMatcher.class);
this.filter.setRemoveCredentialMatcher(requestMatcher);
FilterChain mock = mock(FilterChain.class);
this.filter.doFilter(request, response, mock);
verify(requestMatcher).matches(any());
}

@Test
public void setRequestRegisterCredentialWhenNullThenIllegalArgument() {
assertThatIllegalArgumentException().isThrownBy(() -> this.filter.setRegisterCredentialMatcher(null));
}

@Test
public void setRequestRemoveCredentialWhenNullThenIllegalArgument() {
assertThatIllegalArgumentException().isThrownBy(() -> this.filter.setRemoveCredentialMatcher(null));
}

@Test
Expand Down

0 comments on commit 1a4b550

Please sign in to comment.