Skip to content

Commit 1a4b550

Browse files
topiamjzheaux
authored andcommitted
Add setRequestMatcher to PublicKeyCredentialCreationOptionsFilter
Closes gh-16517 Signed-off-by: smallbun <[email protected]>
1 parent eb5252c commit 1a4b550

File tree

6 files changed

+135
-1
lines changed

6 files changed

+135
-1
lines changed

web/src/main/java/org/springframework/security/web/webauthn/authentication/PublicKeyCredentialRequestOptionsFilter.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,17 @@ public PublicKeyCredentialRequestOptionsFilter(WebAuthnRelyingPartyOperations rp
7575
this.rpOptions = rpOptions;
7676
}
7777

78+
/**
79+
* Sets the {@link RequestMatcher} used to trigger this filter. By default, the
80+
* {@link RequestMatcher} is {@code POST /webauthn/authenticate/options}.
81+
* @param requestMatcher the {@link RequestMatcher} to use
82+
* @since 6.5
83+
*/
84+
public void setRequestMatcher(RequestMatcher requestMatcher) {
85+
Assert.notNull(requestMatcher, "requestMatcher cannot be null");
86+
this.matcher = requestMatcher;
87+
}
88+
7889
@Override
7990
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
8091
throws ServletException, IOException {

web/src/main/java/org/springframework/security/web/webauthn/registration/PublicKeyCredentialCreationOptionsFilter.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,18 @@ public PublicKeyCredentialCreationOptionsFilter(WebAuthnRelyingPartyOperations r
8282
this.rpOperations = rpOperations;
8383
}
8484

85+
/**
86+
* Sets the {@link RequestMatcher} used to trigger this filter.
87+
* <p>
88+
* By default, the {@link RequestMatcher} is {@code POST /webauthn/register/options}.
89+
* @param requestMatcher the {@link RequestMatcher} to use
90+
* @since 6.5
91+
*/
92+
public void setRequestMatcher(RequestMatcher requestMatcher) {
93+
Assert.notNull(requestMatcher, "requestMatcher cannot be null");
94+
this.matcher = requestMatcher;
95+
}
96+
8597
@Override
8698
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
8799
throws ServletException, IOException {

web/src/main/java/org/springframework/security/web/webauthn/registration/WebAuthnRegistrationFilter.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,32 @@ public WebAuthnRegistrationFilter(UserCredentialRepository userCredentials,
105105
this.rpOptions = rpOptions;
106106
}
107107

108+
/**
109+
* Sets the {@link RequestMatcher} to trigger this filter's the credential
110+
* registration operation .
111+
* <p/>
112+
* By default, the {@link RequestMatcher} is {@code POST /webauthn/register}.
113+
* @param registerCredentialMatcher the {@link RequestMatcher} to use
114+
* @since 6.5
115+
*/
116+
public void setRegisterCredentialMatcher(RequestMatcher registerCredentialMatcher) {
117+
Assert.notNull(registerCredentialMatcher, "registerCredentialMatcher cannot be null");
118+
this.registerCredentialMatcher = registerCredentialMatcher;
119+
}
120+
121+
/**
122+
* Sets the {@link RequestMatcher} to trigger this filter's the credential removal
123+
* operation .
124+
* <p/>
125+
* By default, the {@link RequestMatcher} is {@code DELETE /webauthn/register/{id}}.
126+
* @param removeCredentialMatcher the {@link RequestMatcher} to use
127+
* @since 6.5
128+
*/
129+
public void setRemoveCredentialMatcher(RequestMatcher removeCredentialMatcher) {
130+
Assert.notNull(removeCredentialMatcher, "removeCredentialMatcher cannot be null");
131+
this.removeCredentialMatcher = removeCredentialMatcher;
132+
}
133+
108134
@Override
109135
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
110136
throws ServletException, IOException {

web/src/test/java/org/springframework/security/web/webauthn/authentication/PublicKeyCredentialRequestOptionsFilterTests.java

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

1919
import java.nio.charset.StandardCharsets;
2020

21+
import jakarta.servlet.FilterChain;
2122
import org.junit.jupiter.api.AfterEach;
2223
import org.junit.jupiter.api.BeforeEach;
2324
import org.junit.jupiter.api.Test;
@@ -30,10 +31,13 @@
3031

3132
import org.springframework.http.converter.HttpMessageConverter;
3233
import org.springframework.http.server.ServletServerHttpResponse;
34+
import org.springframework.mock.web.MockHttpServletRequest;
35+
import org.springframework.mock.web.MockHttpServletResponse;
3336
import org.springframework.security.authentication.TestingAuthenticationToken;
3437
import org.springframework.security.core.context.SecurityContextHolder;
3538
import org.springframework.security.core.context.SecurityContextHolderStrategy;
3639
import org.springframework.security.core.context.SecurityContextImpl;
40+
import org.springframework.security.web.util.matcher.RequestMatcher;
3741
import org.springframework.security.web.webauthn.api.PublicKeyCredentialCreationOptions;
3842
import org.springframework.security.web.webauthn.api.PublicKeyCredentialRequestOptions;
3943
import org.springframework.security.web.webauthn.api.TestPublicKeyCredentialRequestOptions;
@@ -48,6 +52,7 @@
4852
import static org.mockito.BDDMockito.given;
4953
import static org.mockito.BDDMockito.verifyNoInteractions;
5054
import static org.mockito.BDDMockito.willAnswer;
55+
import static org.mockito.Mockito.*;
5156
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
5257
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
5358
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@@ -75,20 +80,35 @@ class PublicKeyCredentialRequestOptionsFilterTests {
7580

7681
private PublicKeyCredentialRequestOptionsFilter filter;
7782

83+
private MockHttpServletRequest request;
84+
85+
private MockHttpServletResponse response;
86+
7887
private MockMvc mockMvc;
7988

8089
@BeforeEach
8190
void setup() {
8291
this.filter = new PublicKeyCredentialRequestOptionsFilter(this.relyingPartyOperations);
8392
this.filter.setRequestOptionsRepository(this.requestOptionsRepository);
8493
this.mockMvc = MockMvcBuilders.standaloneSetup().addFilter(this.filter).build();
94+
this.request = new MockHttpServletRequest();
95+
this.response = new MockHttpServletResponse();
8596
}
8697

8798
@AfterEach
8899
void cleanup() {
89100
SecurityContextHolder.clearContext();
90101
}
91102

103+
@Test
104+
public void doFilterWhenCustomRequestMatcherThenUses() throws Exception {
105+
RequestMatcher requestMatcher = mock(RequestMatcher.class);
106+
this.filter.setRequestMatcher(requestMatcher);
107+
FilterChain mock = mock(FilterChain.class);
108+
this.filter.doFilter(request, response, mock);
109+
verify(requestMatcher).matches(any());
110+
}
111+
92112
@Test
93113
void constructorWhenNull() {
94114
assertThatExceptionOfType(IllegalArgumentException.class)

web/src/test/java/org/springframework/security/web/webauthn/registration/PublicKeyCredentialCreationOptionsFilterTests.java

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@
1818

1919
import java.util.Arrays;
2020

21+
import jakarta.servlet.FilterChain;
2122
import org.junit.jupiter.api.AfterEach;
23+
import org.junit.jupiter.api.BeforeEach;
2224
import org.junit.jupiter.api.Test;
2325
import org.junit.jupiter.api.extension.ExtendWith;
2426
import org.mockito.Mock;
@@ -27,12 +29,14 @@
2729
import org.springframework.http.HttpHeaders;
2830
import org.springframework.http.HttpStatus;
2931
import org.springframework.http.MediaType;
32+
import org.springframework.mock.web.MockHttpServletRequest;
3033
import org.springframework.mock.web.MockHttpServletResponse;
3134
import org.springframework.security.authentication.AnonymousAuthenticationToken;
3235
import org.springframework.security.authentication.TestingAuthenticationToken;
3336
import org.springframework.security.core.authority.AuthorityUtils;
3437
import org.springframework.security.core.context.SecurityContextHolder;
3538
import org.springframework.security.core.context.SecurityContextImpl;
39+
import org.springframework.security.web.util.matcher.RequestMatcher;
3640
import org.springframework.security.web.webauthn.api.AuthenticatorTransport;
3741
import org.springframework.security.web.webauthn.api.Bytes;
3842
import org.springframework.security.web.webauthn.api.PublicKeyCredentialCreationOptions;
@@ -47,7 +51,7 @@
4751
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
4852
import static org.mockito.ArgumentMatchers.any;
4953
import static org.mockito.BDDMockito.given;
50-
import static org.mockito.Mockito.verifyNoInteractions;
54+
import static org.mockito.Mockito.*;
5155
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
5256
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
5357
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
@@ -68,11 +72,38 @@ class PublicKeyCredentialCreationOptionsFilterTests {
6872
@Mock
6973
private WebAuthnRelyingPartyOperations rpOperations;
7074

75+
private PublicKeyCredentialCreationOptionsFilter filter;
76+
77+
private MockHttpServletRequest request;
78+
79+
private MockHttpServletResponse response;
80+
81+
@BeforeEach
82+
public void setup() {
83+
this.filter = new PublicKeyCredentialCreationOptionsFilter(this.rpOperations);
84+
this.request = new MockHttpServletRequest();
85+
this.response = new MockHttpServletResponse();
86+
}
87+
7188
@AfterEach
7289
void clear() {
7390
SecurityContextHolder.clearContext();
7491
}
7592

93+
@Test
94+
public void doFilterWhenCustomRequestMatcherThenUses() throws Exception {
95+
RequestMatcher requestMatcher = mock(RequestMatcher.class);
96+
this.filter.setRequestMatcher(requestMatcher);
97+
FilterChain mock = mock(FilterChain.class);
98+
this.filter.doFilter(request, response, mock);
99+
verify(requestMatcher).matches(any());
100+
}
101+
102+
@Test
103+
public void setRequestMatcherWhenNullThenIllegalArgument() {
104+
assertThatIllegalArgumentException().isThrownBy(() -> this.filter.setRequestMatcher(null));
105+
}
106+
76107
@Test
77108
void constructorWhenRpOperationsIsNullThenIllegalArgumentException() {
78109
assertThatIllegalArgumentException().isThrownBy(() -> new PublicKeyCredentialCreationOptionsFilter(null))

web/src/test/java/org/springframework/security/web/webauthn/registration/WebAuthnRegistrationFilterTests.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.springframework.mock.web.MockHttpServletRequest;
3131
import org.springframework.mock.web.MockHttpServletResponse;
3232
import org.springframework.mock.web.MockServletContext;
33+
import org.springframework.security.web.util.matcher.RequestMatcher;
3334
import org.springframework.security.web.webauthn.api.ImmutableCredentialRecord;
3435
import org.springframework.security.web.webauthn.api.PublicKeyCredentialCreationOptions;
3536
import org.springframework.security.web.webauthn.api.TestCredentialRecord;
@@ -100,9 +101,42 @@ class WebAuthnRegistrationFilterTests {
100101

101102
private WebAuthnRegistrationFilter filter;
102103

104+
private MockHttpServletRequest request;
105+
103106
@BeforeEach
104107
void setup() {
105108
this.filter = new WebAuthnRegistrationFilter(this.userCredentials, this.operations);
109+
this.request = new MockHttpServletRequest();
110+
this.response = new MockHttpServletResponse();
111+
this.chain = mock(FilterChain.class);
112+
}
113+
114+
@Test
115+
public void doFilterWhenCustomRequestRegisterCredentialMatcherThenUses() throws Exception {
116+
RequestMatcher requestMatcher = mock(RequestMatcher.class);
117+
this.filter.setRegisterCredentialMatcher(requestMatcher);
118+
FilterChain mock = mock(FilterChain.class);
119+
this.filter.doFilter(request, response, mock);
120+
verify(requestMatcher).matches(any());
121+
}
122+
123+
@Test
124+
public void doFilterWhenCustomRequestRemoveCredentialMatcherThenUses() throws Exception {
125+
RequestMatcher requestMatcher = mock(RequestMatcher.class);
126+
this.filter.setRemoveCredentialMatcher(requestMatcher);
127+
FilterChain mock = mock(FilterChain.class);
128+
this.filter.doFilter(request, response, mock);
129+
verify(requestMatcher).matches(any());
130+
}
131+
132+
@Test
133+
public void setRequestRegisterCredentialWhenNullThenIllegalArgument() {
134+
assertThatIllegalArgumentException().isThrownBy(() -> this.filter.setRegisterCredentialMatcher(null));
135+
}
136+
137+
@Test
138+
public void setRequestRemoveCredentialWhenNullThenIllegalArgument() {
139+
assertThatIllegalArgumentException().isThrownBy(() -> this.filter.setRemoveCredentialMatcher(null));
106140
}
107141

108142
@Test

0 commit comments

Comments
 (0)