package com.example.resourceserver.security; import java.security.Principal; import java.util.Collection; import java.util.Map; import java.util.stream.Collectors; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.security.oauth2.jwt.Jwt; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/api/security/users") public class UserRestController { private UserService userService; public UserRestController(UserService userService) { this.userService = userService; } /** * What is in Principal? * * Note that we are returning the details just for testing (here and in some * other methods below). But what is typically done is not returning such * details but use the details within the method itself to determine who is the * calling user and the roles of that user. * * @param principal * @return */ @GetMapping("/test") public String test(Principal principal) { return principal.toString(); } /** * principal.getName() returns the OAuth2 authenticated user name. Can be * trusted within this method. * * @param principal * @return */ @GetMapping("/test-username") public String testName(Principal principal) { return principal.getName(); } /** * Roles returned by authentication.getAuthorities() may not always have custom * roles. * * @param authentication * @return */ @GetMapping("/test-roles-auth") public Collection getRoles(Authentication authentication) { return authentication.getAuthorities().stream() .map(GrantedAuthority::getAuthority) .collect(Collectors.toList()); } /** * Inspect raw JWT claims directly. * * @param jwt * @return */ @GetMapping("/test-roles-jwt") public Map getClaims(@AuthenticationPrincipal Jwt jwt) { return jwt.getClaims(); // Extract custom JSON fields containing roles } /** * Within a method, use the X-User-Roles HTTP header to determine the user * roles. * * Not very secure because unverifiable headers may be introduced by attackers. * So to trust the roles so received, this service should have been * deployed in an access restricted network environment. */ @GetMapping("/test-roles-headers") public String getRolesFromHeaders(@RequestHeader("X-User-Name") String username, @RequestHeader("X-User-Roles") String roles) { return "Roles: " + roles + ", username: " + username; } }