1
0
mirror of synced 2026-08-05 01:36:56 +00:00

Isolate Jwt Test Support

Isolating Jwt test support inside JwtRequestPostProcessor and
JwtMutator.

Fixes gh-7641
This commit is contained in:
Josh Cummings
2019-11-22 12:38:01 -07:00
parent 8a95e5798d
commit 7cbd1665a6
8 changed files with 107 additions and 136 deletions
@@ -127,42 +127,7 @@ public class SecurityMockServerConfigurers {
* @since 5.2
*/
public static JwtMutator mockJwt() {
return mockJwt(jwt -> {});
}
/**
* Updates the ServerWebExchange to establish a {@link SecurityContext} that has a
* {@link JwtAuthenticationToken} for the
* {@link Authentication} and a {@link Jwt} for the
* {@link Authentication#getPrincipal()}. All details are
* declarative and do not require the JWT to be valid.
*
* @param jwtBuilderConsumer For configuring the underlying {@link Jwt}
* @return the {@link JwtMutator} to further configure or use
* @since 5.2
*/
public static JwtMutator mockJwt(Consumer<Jwt.Builder> jwtBuilderConsumer) {
Jwt.Builder jwtBuilder = Jwt.withTokenValue("token")
.header("alg", "none")
.claim(SUB, "user")
.claim("scope", "read");
jwtBuilderConsumer.accept(jwtBuilder);
return new JwtMutator(jwtBuilder.build());
}
/**
* Updates the ServerWebExchange to establish a {@link SecurityContext} that has a
* {@link JwtAuthenticationToken} for the
* {@link Authentication} and a {@link Jwt} for the
* {@link Authentication#getPrincipal()}. All details are
* declarative and do not require the JWT to be valid.
*
* @param jwt The preliminary constructed {@link Jwt}
* @return the {@link JwtMutator} to further configure or use
* @since 5.2
*/
public static JwtMutator mockJwt(Jwt jwt) {
return new JwtMutator(jwt);
return new JwtMutator();
}
public static CsrfMutator csrf() {
@@ -361,11 +326,45 @@ public class SecurityMockServerConfigurers {
*/
public static class JwtMutator implements WebTestClientConfigurer, MockServerConfigurer {
private Jwt jwt;
private Collection<GrantedAuthority> authorities;
private Converter<Jwt, Collection<GrantedAuthority>> authoritiesConverter =
new JwtGrantedAuthoritiesConverter();
private JwtMutator(Jwt jwt) {
private JwtMutator() {
jwt((jwt) -> {});
}
/**
* Use the given {@link Jwt.Builder} {@link Consumer} to configure the underlying {@link Jwt}
*
* This method first creates a default {@link Jwt.Builder} instance with default values for
* the {@code alg}, {@code sub}, and {@code scope} claims. The {@link Consumer} can then modify
* these or provide additional configuration.
*
* Calling {@link SecurityMockServerConfigurers#mockJwt()} is the equivalent of calling
* {@code SecurityMockMvcRequestPostProcessors.mockJwt().jwt(() -> {})}.
*
* @param jwtBuilderConsumer For configuring the underlying {@link Jwt}
* @return the {@link JwtMutator} for further configuration
*/
public JwtMutator jwt(Consumer<Jwt.Builder> jwtBuilderConsumer) {
Jwt.Builder jwtBuilder = Jwt.withTokenValue("token")
.header("alg", "none")
.claim(SUB, "user")
.claim("scope", "read");
jwtBuilderConsumer.accept(jwtBuilder);
this.jwt = jwtBuilder.build();
return this;
}
/**
* Use the given {@link Jwt}
*
* @param jwt The {@link Jwt} to use
* @return the {@link JwtMutator} for further configuration
*/
public JwtMutator jwt(Jwt jwt) {
this.jwt = jwt;
this.authorities = new JwtGrantedAuthoritiesConverter().convert(jwt);
return this;
}
/**
@@ -375,7 +374,7 @@ public class SecurityMockServerConfigurers {
*/
public JwtMutator authorities(Collection<GrantedAuthority> authorities) {
Assert.notNull(authorities, "authorities cannot be null");
this.authorities = authorities;
this.authoritiesConverter = jwt -> authorities;
return this;
}
@@ -386,7 +385,7 @@ public class SecurityMockServerConfigurers {
*/
public JwtMutator authorities(GrantedAuthority... authorities) {
Assert.notNull(authorities, "authorities cannot be null");
this.authorities = Arrays.asList(authorities);
this.authoritiesConverter = jwt -> Arrays.asList(authorities);
return this;
}
@@ -400,7 +399,7 @@ public class SecurityMockServerConfigurers {
*/
public JwtMutator authorities(Converter<Jwt, Collection<GrantedAuthority>> authoritiesConverter) {
Assert.notNull(authoritiesConverter, "authoritiesConverter cannot be null");
this.authorities = authoritiesConverter.convert(this.jwt);
this.authoritiesConverter = authoritiesConverter;
return this;
}
@@ -427,7 +426,7 @@ public class SecurityMockServerConfigurers {
}
private <T extends WebTestClientConfigurer & MockServerConfigurer> T configurer() {
return mockAuthentication(new JwtAuthenticationToken(this.jwt, this.authorities));
return mockAuthentication(new JwtAuthenticationToken(this.jwt, this.authoritiesConverter.convert(this.jwt)));
}
}
}
@@ -227,70 +227,7 @@ public final class SecurityMockMvcRequestPostProcessors {
* @return the {@link JwtRequestPostProcessor} for additional customization
*/
public static JwtRequestPostProcessor jwt() {
return jwt(jwt -> {});
}
/**
* Establish a {@link SecurityContext} that has a
* {@link JwtAuthenticationToken} for the
* {@link Authentication} and a {@link Jwt} for the
* {@link Authentication#getPrincipal()}. All details are
* declarative and do not require the JWT to be valid.
*
* <p>
* The support works by associating the authentication to the HttpServletRequest. To associate
* the request to the SecurityContextHolder you need to ensure that the
* SecurityContextPersistenceFilter is associated with the MockMvc instance. A few
* ways to do this are:
* </p>
*
* <ul>
* <li>Invoking apply {@link SecurityMockMvcConfigurers#springSecurity()}</li>
* <li>Adding Spring Security's FilterChainProxy to MockMvc</li>
* <li>Manually adding {@link SecurityContextPersistenceFilter} to the MockMvc
* instance may make sense when using MockMvcBuilders standaloneSetup</li>
* </ul>
*
* @param jwtBuilderConsumer For configuring the underlying {@link Jwt}
* @return the {@link JwtRequestPostProcessor} for additional customization
* @since 5.2
*/
public static JwtRequestPostProcessor jwt(Consumer<Jwt.Builder> jwtBuilderConsumer) {
Jwt.Builder jwtBuilder = Jwt.withTokenValue("token")
.header("alg", "none")
.claim(SUB, "user")
.claim("scope", "read");
jwtBuilderConsumer.accept(jwtBuilder);
return new JwtRequestPostProcessor(jwtBuilder.build());
}
/**
* Establish a {@link SecurityContext} that has a
* {@link JwtAuthenticationToken} for the
* {@link Authentication} and a {@link Jwt} for the
* {@link Authentication#getPrincipal()}. All details are
* declarative and do not require the JWT to be valid.
*
* <p>
* The support works by associating the authentication to the HttpServletRequest. To associate
* the request to the SecurityContextHolder you need to ensure that the
* SecurityContextPersistenceFilter is associated with the MockMvc instance. A few
* ways to do this are:
* </p>
*
* <ul>
* <li>Invoking apply {@link SecurityMockMvcConfigurers#springSecurity()}</li>
* <li>Adding Spring Security's FilterChainProxy to MockMvc</li>
* <li>Manually adding {@link SecurityContextPersistenceFilter} to the MockMvc
* instance may make sense when using MockMvcBuilders standaloneSetup</li>
* </ul>
*
* @param jwt The preliminary constructed {@link Jwt}
* @return the {@link JwtRequestPostProcessor} for additional customization
* @since 5.2
*/
public static JwtRequestPostProcessor jwt(Jwt jwt) {
return new JwtRequestPostProcessor(jwt);
return new JwtRequestPostProcessor();
}
/**
@@ -1000,11 +937,45 @@ public final class SecurityMockMvcRequestPostProcessors {
*/
public final static class JwtRequestPostProcessor implements RequestPostProcessor {
private Jwt jwt;
private Collection<? extends GrantedAuthority> authorities;
private Converter<Jwt, Collection<GrantedAuthority>> authoritiesConverter =
new JwtGrantedAuthoritiesConverter();
private JwtRequestPostProcessor(Jwt jwt) {
private JwtRequestPostProcessor() {
this.jwt((jwt) -> {});
}
/**
* Use the given {@link Jwt.Builder} {@link Consumer} to configure the underlying {@link Jwt}
*
* This method first creates a default {@link Jwt.Builder} instance with default values for
* the {@code alg}, {@code sub}, and {@code scope} claims. The {@link Consumer} can then modify
* these or provide additional configuration.
*
* Calling {@link SecurityMockMvcRequestPostProcessors#jwt()} is the equivalent of calling
* {@code SecurityMockMvcRequestPostProcessors.jwt().jwt(() -> {})}.
*
* @param jwtBuilderConsumer For configuring the underlying {@link Jwt}
* @return the {@link JwtRequestPostProcessor} for additional customization
*/
public JwtRequestPostProcessor jwt(Consumer<Jwt.Builder> jwtBuilderConsumer) {
Jwt.Builder jwtBuilder = Jwt.withTokenValue("token")
.header("alg", "none")
.claim(SUB, "user")
.claim("scope", "read");
jwtBuilderConsumer.accept(jwtBuilder);
this.jwt = jwtBuilder.build();
return this;
}
/**
* Use the given {@link Jwt}
*
* @param jwt The {@link Jwt} to use
* @return the {@link JwtRequestPostProcessor} for additional customization
*/
public JwtRequestPostProcessor jwt(Jwt jwt) {
this.jwt = jwt;
this.authorities = new JwtGrantedAuthoritiesConverter().convert(jwt);
return this;
}
/**
@@ -1014,7 +985,7 @@ public final class SecurityMockMvcRequestPostProcessors {
*/
public JwtRequestPostProcessor authorities(Collection<GrantedAuthority> authorities) {
Assert.notNull(authorities, "authorities cannot be null");
this.authorities = authorities;
this.authoritiesConverter = jwt -> authorities;
return this;
}
@@ -1025,7 +996,7 @@ public final class SecurityMockMvcRequestPostProcessors {
*/
public JwtRequestPostProcessor authorities(GrantedAuthority... authorities) {
Assert.notNull(authorities, "authorities cannot be null");
this.authorities = Arrays.asList(authorities);
this.authoritiesConverter = jwt -> Arrays.asList(authorities);
return this;
}
@@ -1039,14 +1010,15 @@ public final class SecurityMockMvcRequestPostProcessors {
*/
public JwtRequestPostProcessor authorities(Converter<Jwt, Collection<GrantedAuthority>> authoritiesConverter) {
Assert.notNull(authoritiesConverter, "authoritiesConverter cannot be null");
this.authorities = authoritiesConverter.convert(this.jwt);
this.authoritiesConverter = authoritiesConverter;
return this;
}
@Override
public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) {
CsrfFilter.skipRequest(request);
JwtAuthenticationToken token = new JwtAuthenticationToken(this.jwt, this.authorities);
JwtAuthenticationToken token = new JwtAuthenticationToken(this.jwt,
this.authoritiesConverter.convert(this.jwt));
return new AuthenticationRequestPostProcessor(token).postProcessRequest(request);
}