Search⌘ K
AI Features

Conditional Links Based on Authorization

Explore how to implement conditional links in Spring Boot using Spring Security. Learn to restrict operations and dynamically show links based on user roles to enhance application security and user navigation. Understand the use of Reactor Mono.zip() and testing with WebTestClient for hypermedia APIs.

The first rule in security is to not allow people to execute operations for which they lack the proper authority. We’ve just done that. Only users with ROLE_INVENTORY will be allowed to alter the system’s inventory.

The second rule in security, though arguably just as important as the first, is to not show a user anything that will cause them to run into the first rule. From a hypermedia perspective, don’t include links they can’t navigate.

To exercise this, let’s examine that findOne operation meant to show a hypermedia record and see if we can conditionalize some of its links:

Java
private static final SimpleGrantedAuthority ROLE_INVENTORY =
new SimpleGrantedAuthority("ROLE_" + INVENTORY);
@GetMapping("/api/items/{id}")
Mono<EntityModel<Item>> findOne(@PathVariable String id, Authentication auth) {
ApiItemController controller = methodOn(ApiItemController.class);
Mono<Link> selfLink = linkTo(controller.findOne(id, auth))
.withSelfRel().toMono();
Mono<Link> aggregateLink = linkTo(controller.findAll(auth))
.withRel(IanaLinkRelations.ITEM).toMono();
Mono<Links> allLinks; // 1
if (auth.getAuthorities().contains(ROLE_INVENTORY)) { // 2
Mono<Link> deleteLink = linkTo(controller.deleteItem(id))
.withRel("delete").toMono();
allLinks = Mono.zip(selfLink, aggregateLink, deleteLink)
.map(links -> Links.of(links.getT1(), links.getT2(), links.getT3()));
} else { // 3
allLinks = Mono.zip(selfLink, aggregateLink)
.map(links -> Links.of(links.getT1(), links.getT2()));
}
return this.repository.findById(id)
.zipWith(allLinks) // 4
.map(o -> EntityModel.of(o.getT1(), o.getT2()));
}
Conditional links based on authorization

This method contains quite a bit. If you glossed over the “Building APIs with Spring Boot” chapter, feel free to pause here and revisit it to refresh your memory. For now, let’s take a peek at the security-specific parts.

Here’s a breakdown of the code above:

  1. In line 14, we try to assemble a Mono<Links>, a Reactor-wrapped collection of Spring HATEOAS’ aggregate type, Links.

  2. In line 16, we check that the user ...