When creating an entity that contains a linked resource whose repository's find one method is restricted, SDR throws an HttpMessageNotReadable exception during deserialization of the linked resource (so it can't be changed using @ControllerAdvice exception handlers, resulting in the end-user receiving a 400 bad request response on a well-formed and valid request instead of the expected 403 forbidden status one would receive if they failed the global method security on any other kind of request. The following example code demonstrates the behavior by performing a POST to /parents with the body { "id":"1" } and then a POST to /children with the body { "id": "child1", "parent": "/parents/1" }.
Security Configuration: in-memory user user with password password and basic auth configured
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
public UserDetailsService users() {
UserDetails user = User.builder()
.username("user")
.password("{bcrypt}$2a$10$GRLdNijSQMUvl/au9ofL.eDwmoohzzS7.rmNSJZ.0FxO/BTk76klW")
.roles("USER")
.build();
return new InMemoryUserDetailsManager(user);
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeHttpRequests(authorize -> authorize.anyRequest().authenticated());
http.httpBasic(withDefaults());
return http.build();
}
}
Parent domain object
@Entity
@Data
@Table(name = "parent_t")
public class Parent {
@Id
private String id;
@OneToMany
private List<Child> children;
}
@Entity
@Data
@Table(name = "child_t")
public class Child {
@Id
private String id;
@ManyToOne(optional = false)
private Parent parent;
}
Child repository with method security:
public interface ChildRepository extends CrudRepository<Child, String> {
@Override
@PreAuthorize("isAuthenticated()")
<S extends Child> S save(S entity);
}
Authorities utility class referenced in parent repository:
@Component
public class AuthoritiesUtil {
public boolean canViewParent(Optional<Parent> parent) {
return false; //insert logic to allow this in some cases
}
}
Application class
@SpringBootApplication
@EnableMethodSecurity
public class SpringDataDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringDataDemoApplication.class, args);
}
}
In this case, I would expect to receive a 403 forbidden status instead of a 400 bad request with the message JSON parse error: Access Denied because the request is well-formatted and the linked object exists, but the user is forbidden from using it. Please let me know if you have any questions or concerns. Thank you.
When creating an entity that contains a linked resource whose repository's find one method is restricted, SDR throws an
HttpMessageNotReadable
exception during deserialization of the linked resource (so it can't be changed using@ControllerAdvice
exception handlers, resulting in the end-user receiving a 400 bad request response on a well-formed and valid request instead of the expected 403 forbidden status one would receive if they failed the global method security on any other kind of request. The following example code demonstrates the behavior by performing a POST to/parents
with the body{ "id":"1" }
and then a POST to/children
with the body{ "id": "child1", "parent": "/parents/1" }
.Security Configuration: in-memory user
user
with passwordpassword
and basic auth configuredParent domain object
Parent repository with method security
Child domain object
Child repository with method security:
Authorities utility class referenced in parent repository:
Application class
POM
In this case, I would expect to receive a 403 forbidden status instead of a 400 bad request with the message
JSON parse error: Access Denied
because the request is well-formatted and the linked object exists, but the user is forbidden from using it. Please let me know if you have any questions or concerns. Thank you.