I'm working on a Spring Boot service that has both a REST controller and a Netflix DGS GraphQL component. REST methods are protected with Spring Security, and whenever the current username is required, I add a method argument using the @AuthenticationPrincipal
annotation, which gives me access to the authenticated user info:
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.userdetails.UserDetails;
@RestController
public class ActionController {
@GetMapping("/getActions")
public List<ActionResponse> getActions(@AuthenticationPrincipal UserDetails userDetails) {
return actionService.getActions(userDetails.getUsername());
}
}
Now I want the same functionality for GraphQL methods implemented through Netflix DGS. But when I try to use the @AuthenticationPrincipal
argument (like in the first example) it always equals null
. The workaround I found is to manually assign the userDetails from the SecurityContextHolder:
import com.netflix.graphql.dgs.DgsComponent;
import com.netflix.graphql.dgs.DgsQuery;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.userdetails.UserDetails;
@DgsComponent
public class ActionDatafetcher {
@DgsQuery
public List<Map<String, Object>> actions(@AuthenticationPrincipal UserDetails userDetails) {
// The following line works well:
// userDetails = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String username = userDetails.getUsername(); // ===> NullPointerException here
return actionService.getActionsMap(username);
}
}
How can I get @AuthenticationPrincipal to work in a DgsComponent?