parent
a907026eae
commit
ca1252be94
|
@ -2,7 +2,7 @@ buildscript {
|
|||
dependencies {
|
||||
classpath 'io.spring.gradle:spring-build-conventions:0.0.32.RELEASE'
|
||||
classpath "org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion"
|
||||
classpath 'io.spring.nohttp:nohttp-gradle:0.0.2.RELEASE'
|
||||
classpath 'io.spring.nohttp:nohttp-gradle:0.0.5.RELEASE'
|
||||
classpath "io.freefair.gradle:aspectj-plugin:5.0.1"
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
|
||||
}
|
||||
|
@ -39,3 +39,7 @@ subprojects {
|
|||
options.encoding = "UTF-8"
|
||||
}
|
||||
}
|
||||
|
||||
nohttp {
|
||||
allowlistFile = project.file("etc/nohttp/allowlist.lines")
|
||||
}
|
||||
|
|
|
@ -90,7 +90,7 @@ public final class SecurityJackson2Modules {
|
|||
if (mapper != null) {
|
||||
TypeResolverBuilder<?> typeBuilder = mapper.getDeserializationConfig().getDefaultTyper(null);
|
||||
if (typeBuilder == null) {
|
||||
mapper.setDefaultTyping(createWhitelistedDefaultTyping());
|
||||
mapper.setDefaultTyping(createAllowlistedDefaultTyping());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -148,11 +148,11 @@ public final class SecurityJackson2Modules {
|
|||
}
|
||||
|
||||
/**
|
||||
* Creates a TypeResolverBuilder that performs whitelisting.
|
||||
* @return a TypeResolverBuilder that performs whitelisting.
|
||||
* Creates a TypeResolverBuilder that restricts allowed types.
|
||||
* @return a TypeResolverBuilder that restricts allowed types.
|
||||
*/
|
||||
private static TypeResolverBuilder<? extends TypeResolverBuilder> createWhitelistedDefaultTyping() {
|
||||
TypeResolverBuilder<? extends TypeResolverBuilder> result = new WhitelistTypeResolverBuilder(ObjectMapper.DefaultTyping.NON_FINAL);
|
||||
private static TypeResolverBuilder<? extends TypeResolverBuilder> createAllowlistedDefaultTyping() {
|
||||
TypeResolverBuilder<? extends TypeResolverBuilder> result = new AllowlistTypeResolverBuilder(ObjectMapper.DefaultTyping.NON_FINAL);
|
||||
result = result.init(JsonTypeInfo.Id.CLASS, null);
|
||||
result = result.inclusion(JsonTypeInfo.As.PROPERTY);
|
||||
return result;
|
||||
|
@ -164,9 +164,9 @@ public final class SecurityJackson2Modules {
|
|||
* and overrides the {@code TypeIdResolver}
|
||||
* @author Rob Winch
|
||||
*/
|
||||
static class WhitelistTypeResolverBuilder extends ObjectMapper.DefaultTypeResolverBuilder {
|
||||
static class AllowlistTypeResolverBuilder extends ObjectMapper.DefaultTypeResolverBuilder {
|
||||
|
||||
WhitelistTypeResolverBuilder(ObjectMapper.DefaultTyping defaultTyping) {
|
||||
AllowlistTypeResolverBuilder(ObjectMapper.DefaultTyping defaultTyping) {
|
||||
super(
|
||||
defaultTyping,
|
||||
//we do explicit validation in the TypeIdResolver
|
||||
|
@ -182,17 +182,17 @@ public final class SecurityJackson2Modules {
|
|||
PolymorphicTypeValidator subtypeValidator,
|
||||
Collection<NamedType> subtypes, boolean forSer, boolean forDeser) {
|
||||
TypeIdResolver result = super.idResolver(config, baseType, subtypeValidator, subtypes, forSer, forDeser);
|
||||
return new WhitelistTypeIdResolver(result);
|
||||
return new AllowlistTypeIdResolver(result);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link TypeIdResolver} that delegates to an existing implementation and throws an IllegalStateException if the
|
||||
* class being looked up is not whitelisted, does not provide an explicit mixin, and is not annotated with Jackson
|
||||
* class being looked up is not in the allowlist, does not provide an explicit mixin, and is not annotated with Jackson
|
||||
* mappings. See https://github.com/spring-projects/spring-security/issues/4370
|
||||
*/
|
||||
static class WhitelistTypeIdResolver implements TypeIdResolver {
|
||||
private static final Set<String> WHITELIST_CLASS_NAMES = Collections.unmodifiableSet(new HashSet(Arrays.asList(
|
||||
static class AllowlistTypeIdResolver implements TypeIdResolver {
|
||||
private static final Set<String> ALLOWLIST_CLASS_NAMES = Collections.unmodifiableSet(new HashSet(Arrays.asList(
|
||||
"java.util.ArrayList",
|
||||
"java.util.Collections$EmptyList",
|
||||
"java.util.Collections$EmptyMap",
|
||||
|
@ -209,7 +209,7 @@ public final class SecurityJackson2Modules {
|
|||
|
||||
private final TypeIdResolver delegate;
|
||||
|
||||
WhitelistTypeIdResolver(TypeIdResolver delegate) {
|
||||
AllowlistTypeIdResolver(TypeIdResolver delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
|
@ -238,7 +238,7 @@ public final class SecurityJackson2Modules {
|
|||
DeserializationConfig config = (DeserializationConfig) context.getConfig();
|
||||
JavaType result = delegate.typeFromId(context, id);
|
||||
String className = result.getRawClass().getName();
|
||||
if (isWhitelisted(className)) {
|
||||
if (isInAllowlist(className)) {
|
||||
return result;
|
||||
}
|
||||
boolean isExplicitMixin = config.findMixInClassFor(result.getRawClass()) != null;
|
||||
|
@ -249,14 +249,14 @@ public final class SecurityJackson2Modules {
|
|||
if (jacksonAnnotation != null) {
|
||||
return result;
|
||||
}
|
||||
throw new IllegalArgumentException("The class with " + id + " and name of " + className + " is not whitelisted. " +
|
||||
throw new IllegalArgumentException("The class with " + id + " and name of " + className + " is not in the allowlist. " +
|
||||
"If you believe this class is safe to deserialize, please provide an explicit mapping using Jackson annotations or by providing a Mixin. " +
|
||||
"If the serialization is only done by a trusted source, you can also enable default typing. " +
|
||||
"See https://github.com/spring-projects/spring-security/issues/4370 for details");
|
||||
}
|
||||
|
||||
private boolean isWhitelisted(String id) {
|
||||
return WHITELIST_CLASS_NAMES.contains(id);
|
||||
private boolean isInAllowlist(String id) {
|
||||
return ALLOWLIST_CLASS_NAMES.contains(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -44,20 +44,20 @@ public class SecurityJackson2ModulesTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void readValueWhenNotWhitelistedOrMappedThenThrowsException() {
|
||||
String content = "{\"@class\":\"org.springframework.security.jackson2.SecurityJackson2ModulesTests$NotWhitelisted\",\"property\":\"bar\"}";
|
||||
public void readValueWhenNotAllowedOrMappedThenThrowsException() {
|
||||
String content = "{\"@class\":\"org.springframework.security.jackson2.SecurityJackson2ModulesTests$NotAllowlisted\",\"property\":\"bar\"}";
|
||||
assertThatThrownBy(() -> {
|
||||
mapper.readValue(content, Object.class);
|
||||
}
|
||||
).hasStackTraceContaining("whitelisted");
|
||||
).hasStackTraceContaining("allowlist");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readValueWhenExplicitDefaultTypingAfterSecuritySetupThenReadsAsSpecificType() throws Exception {
|
||||
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
|
||||
String content = "{\"@class\":\"org.springframework.security.jackson2.SecurityJackson2ModulesTests$NotWhitelisted\",\"property\":\"bar\"}";
|
||||
String content = "{\"@class\":\"org.springframework.security.jackson2.SecurityJackson2ModulesTests$NotAllowlisted\",\"property\":\"bar\"}";
|
||||
|
||||
assertThat(mapper.readValue(content, Object.class)).isInstanceOf(NotWhitelisted.class);
|
||||
assertThat(mapper.readValue(content, Object.class)).isInstanceOf(NotAllowlisted.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -65,29 +65,29 @@ public class SecurityJackson2ModulesTests {
|
|||
mapper = new ObjectMapper();
|
||||
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
|
||||
SecurityJackson2Modules.enableDefaultTyping(mapper);
|
||||
String content = "{\"@class\":\"org.springframework.security.jackson2.SecurityJackson2ModulesTests$NotWhitelisted\",\"property\":\"bar\"}";
|
||||
String content = "{\"@class\":\"org.springframework.security.jackson2.SecurityJackson2ModulesTests$NotAllowlisted\",\"property\":\"bar\"}";
|
||||
|
||||
assertThat(mapper.readValue(content, Object.class)).isInstanceOf(NotWhitelisted.class);
|
||||
assertThat(mapper.readValue(content, Object.class)).isInstanceOf(NotAllowlisted.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readValueWhenAnnotatedThenReadsAsSpecificType() throws Exception {
|
||||
String content = "{\"@class\":\"org.springframework.security.jackson2.SecurityJackson2ModulesTests$NotWhitelistedButAnnotated\",\"property\":\"bar\"}";
|
||||
String content = "{\"@class\":\"org.springframework.security.jackson2.SecurityJackson2ModulesTests$NotAllowlistedButAnnotated\",\"property\":\"bar\"}";
|
||||
|
||||
assertThat(mapper.readValue(content, Object.class)).isInstanceOf(NotWhitelistedButAnnotated.class);
|
||||
assertThat(mapper.readValue(content, Object.class)).isInstanceOf(NotAllowlistedButAnnotated.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readValueWhenMixinProvidedThenReadsAsSpecificType() throws Exception {
|
||||
mapper.addMixIn(NotWhitelisted.class, NotWhitelistedMixin.class);
|
||||
String content = "{\"@class\":\"org.springframework.security.jackson2.SecurityJackson2ModulesTests$NotWhitelisted\",\"property\":\"bar\"}";
|
||||
mapper.addMixIn(NotAllowlisted.class, NotAllowlistedMixin.class);
|
||||
String content = "{\"@class\":\"org.springframework.security.jackson2.SecurityJackson2ModulesTests$NotAllowlisted\",\"property\":\"bar\"}";
|
||||
|
||||
assertThat(mapper.readValue(content, Object.class)).isInstanceOf(NotWhitelisted.class);
|
||||
assertThat(mapper.readValue(content, Object.class)).isInstanceOf(NotAllowlisted.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readValueWhenHashMapThenReadsAsSpecificType() throws Exception {
|
||||
mapper.addMixIn(NotWhitelisted.class, NotWhitelistedMixin.class);
|
||||
mapper.addMixIn(NotAllowlisted.class, NotAllowlistedMixin.class);
|
||||
String content = "{\"@class\":\"java.util.HashMap\"}";
|
||||
|
||||
assertThat(mapper.readValue(content, Object.class)).isInstanceOf(HashMap.class);
|
||||
|
@ -99,7 +99,7 @@ public class SecurityJackson2ModulesTests {
|
|||
public @interface NotJacksonAnnotation {}
|
||||
|
||||
@NotJacksonAnnotation
|
||||
static class NotWhitelisted {
|
||||
static class NotAllowlisted {
|
||||
private String property = "bar";
|
||||
|
||||
public String getProperty() {
|
||||
|
@ -111,7 +111,7 @@ public class SecurityJackson2ModulesTests {
|
|||
}
|
||||
|
||||
@JsonIgnoreType(false)
|
||||
static class NotWhitelistedButAnnotated {
|
||||
static class NotAllowlistedButAnnotated {
|
||||
private String property = "bar";
|
||||
|
||||
public String getProperty() {
|
||||
|
@ -126,7 +126,7 @@ public class SecurityJackson2ModulesTests {
|
|||
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
|
||||
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
abstract class NotWhitelistedMixin {
|
||||
abstract class NotAllowlistedMixin {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1082,7 +1082,7 @@ In this case, you construct `JwtIssuerReactiveAuthenticationManagerResolver` wit
|
|||
This approach allows us to add and remove elements from the repository (shown as a `Map` in the snippet) at runtime.
|
||||
|
||||
NOTE: It would be unsafe to simply take any issuer and construct an `ReactiveAuthenticationManager` from it.
|
||||
The issuer should be one that the code can verify from a trusted source like a whitelist.
|
||||
The issuer should be one that the code can verify from a trusted source like an allowed list of issuers.
|
||||
|
||||
[[webflux-oauth2resourceserver-bearertoken-resolver]]
|
||||
== Bearer Token Resolution
|
||||
|
|
|
@ -1857,7 +1857,7 @@ In this case, you construct `JwtIssuerAuthenticationManagerResolver` with a stra
|
|||
This approach allows us to add and remove elements from the repository (shown as a `Map` in the snippet) at runtime.
|
||||
|
||||
NOTE: It would be unsafe to simply take any issuer and construct an `AuthenticationManager` from it.
|
||||
The issuer should be one that the code can verify from a trusted source like a whitelist.
|
||||
The issuer should be one that the code can verify from a trusted source like a list of allowed issuers.
|
||||
|
||||
===== Parsing the Claim Only Once
|
||||
|
||||
|
@ -1907,7 +1907,7 @@ public class TenantJWSKeySelector
|
|||
----
|
||||
<1> A hypothetical source for tenant information
|
||||
<2> A cache for `JWKKeySelector`s, keyed by tenant identifier
|
||||
<3> Looking up the tenant is more secure than simply calculating the JWK Set endpoint on the fly - the lookup acts as a tenant whitelist
|
||||
<3> Looking up the tenant is more secure than simply calculating the JWK Set endpoint on the fly - the lookup acts as a list of allowed tenants
|
||||
<4> Create a `JWSKeySelector` via the types of keys that come back from the JWK Set endpoint - the lazy lookup here means that you don't need to configure all tenants at startup
|
||||
|
||||
The above key selector is a composition of many key selectors.
|
||||
|
|
|
@ -45,7 +45,7 @@ import org.springframework.util.Assert;
|
|||
*
|
||||
* To use, this class must be able to determine whether or not the `iss` claim is trusted. Recall that
|
||||
* anyone can stand up an authorization server and issue valid tokens to a resource server. The simplest way
|
||||
* to achieve this is to supply a whitelist of trusted issuers in the constructor.
|
||||
* to achieve this is to supply a list of trusted issuers in the constructor.
|
||||
*
|
||||
* This class derives the Issuer from the `iss` claim found in the {@link HttpServletRequest}'s
|
||||
* <a href="https://tools.ietf.org/html/rfc6750#section-1.2" target="_blank">Bearer Token</a>.
|
||||
|
@ -60,7 +60,7 @@ public final class JwtIssuerAuthenticationManagerResolver implements Authenticat
|
|||
/**
|
||||
* Construct a {@link JwtIssuerAuthenticationManagerResolver} using the provided parameters
|
||||
*
|
||||
* @param trustedIssuers a whitelist of trusted issuers
|
||||
* @param trustedIssuers a list of trusted issuers
|
||||
*/
|
||||
public JwtIssuerAuthenticationManagerResolver(String... trustedIssuers) {
|
||||
this(Arrays.asList(trustedIssuers));
|
||||
|
@ -69,7 +69,7 @@ public final class JwtIssuerAuthenticationManagerResolver implements Authenticat
|
|||
/**
|
||||
* Construct a {@link JwtIssuerAuthenticationManagerResolver} using the provided parameters
|
||||
*
|
||||
* @param trustedIssuers a whitelist of trusted issuers
|
||||
* @param trustedIssuers a list of trusted issuers
|
||||
*/
|
||||
public JwtIssuerAuthenticationManagerResolver(Collection<String> trustedIssuers) {
|
||||
Assert.notEmpty(trustedIssuers, "trustedIssuers cannot be empty");
|
||||
|
@ -82,7 +82,7 @@ public final class JwtIssuerAuthenticationManagerResolver implements Authenticat
|
|||
* Construct a {@link JwtIssuerAuthenticationManagerResolver} using the provided parameters
|
||||
*
|
||||
* Note that the {@link AuthenticationManagerResolver} provided in this constructor will need to
|
||||
* verify that the issuer is trusted. This should be done via a whitelist.
|
||||
* verify that the issuer is trusted. This should be done via an allowlist.
|
||||
*
|
||||
* One way to achieve this is with a {@link Map} where the keys are the known issuers:
|
||||
* <pre>
|
||||
|
@ -93,7 +93,7 @@ public final class JwtIssuerAuthenticationManagerResolver implements Authenticat
|
|||
* (authenticationManagers::get);
|
||||
* </pre>
|
||||
*
|
||||
* The keys in the {@link Map} are the whitelist.
|
||||
* The keys in the {@link Map} are the allowed issuers.
|
||||
*
|
||||
* @param issuerAuthenticationManagerResolver a strategy for resolving the {@link AuthenticationManager} by the issuer
|
||||
*/
|
||||
|
|
|
@ -48,7 +48,7 @@ import org.springframework.web.server.ServerWebExchange;
|
|||
*
|
||||
* To use, this class must be able to determine whether or not the `iss` claim is trusted. Recall that
|
||||
* anyone can stand up an authorization server and issue valid tokens to a resource server. The simplest way
|
||||
* to achieve this is to supply a whitelist of trusted issuers in the constructor.
|
||||
* to achieve this is to supply a list of trusted issuers in the constructor.
|
||||
*
|
||||
* This class derives the Issuer from the `iss` claim found in the {@link ServerWebExchange}'s
|
||||
* <a href="https://tools.ietf.org/html/rfc6750#section-1.2" target="_blank">Bearer Token</a>.
|
||||
|
@ -66,7 +66,7 @@ public final class JwtIssuerReactiveAuthenticationManagerResolver
|
|||
/**
|
||||
* Construct a {@link JwtIssuerReactiveAuthenticationManagerResolver} using the provided parameters
|
||||
*
|
||||
* @param trustedIssuers a whitelist of trusted issuers
|
||||
* @param trustedIssuers a list of trusted issuers
|
||||
*/
|
||||
public JwtIssuerReactiveAuthenticationManagerResolver(String... trustedIssuers) {
|
||||
this(Arrays.asList(trustedIssuers));
|
||||
|
@ -75,7 +75,7 @@ public final class JwtIssuerReactiveAuthenticationManagerResolver
|
|||
/**
|
||||
* Construct a {@link JwtIssuerReactiveAuthenticationManagerResolver} using the provided parameters
|
||||
*
|
||||
* @param trustedIssuers a whitelist of trusted issuers
|
||||
* @param trustedIssuers a collection of trusted issuers
|
||||
*/
|
||||
public JwtIssuerReactiveAuthenticationManagerResolver(Collection<String> trustedIssuers) {
|
||||
Assert.notEmpty(trustedIssuers, "trustedIssuers cannot be empty");
|
||||
|
@ -87,7 +87,7 @@ public final class JwtIssuerReactiveAuthenticationManagerResolver
|
|||
* Construct a {@link JwtIssuerReactiveAuthenticationManagerResolver} using the provided parameters
|
||||
*
|
||||
* Note that the {@link ReactiveAuthenticationManagerResolver} provided in this constructor will need to
|
||||
* verify that the issuer is trusted. This should be done via a whitelist.
|
||||
* verify that the issuer is trusted. This should be done via an allowed list of issuers.
|
||||
*
|
||||
* One way to achieve this is with a {@link Map} where the keys are the known issuers:
|
||||
* <pre>
|
||||
|
@ -98,7 +98,7 @@ public final class JwtIssuerReactiveAuthenticationManagerResolver
|
|||
* (issuer -> Mono.justOrEmpty(authenticationManagers.get(issuer));
|
||||
* </pre>
|
||||
*
|
||||
* The keys in the {@link Map} are the whitelist.
|
||||
* The keys in the {@link Map} are the trusted issuers.
|
||||
*
|
||||
* @param issuerAuthenticationManagerResolver a strategy for resolving the {@link ReactiveAuthenticationManager}
|
||||
* by the issuer
|
||||
|
|
|
@ -358,7 +358,7 @@ public class StrictHttpFirewall implements HttpFirewall {
|
|||
if (!this.allowedHttpMethods.contains(request.getMethod())) {
|
||||
throw new RequestRejectedException("The request was rejected because the HTTP method \"" +
|
||||
request.getMethod() +
|
||||
"\" was not included within the whitelist " +
|
||||
"\" was not included within the list of allowed HTTP methods " +
|
||||
this.allowedHttpMethods);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue