diff options
| author | Kamal Wickramanayake <kamal@inbox.lk> | 2026-07-06 06:32:08 +0530 |
|---|---|---|
| committer | Kamal Wickramanayake <kamal@inbox.lk> | 2026-07-06 06:32:08 +0530 |
| commit | 5ca98df7caebf56990e26aa83a1a2b626ba16660 (patch) | |
| tree | e71cd8298a49c95d7a03697ef4324b342b399f3e /microservices/03-resource-server | |
| parent | 504045fb23fa75a520a4d2665aea7d423db1fe14 (diff) | |
Diffstat (limited to 'microservices/03-resource-server')
| -rw-r--r-- | microservices/03-resource-server/README | 23 | ||||
| -rw-r--r-- | microservices/03-resource-server/src/main/java/com/example/resourceserver/security/UserRestController.java | 47 |
2 files changed, 55 insertions, 15 deletions
diff --git a/microservices/03-resource-server/README b/microservices/03-resource-server/README index 095e8c5..9d0fe77 100644 --- a/microservices/03-resource-server/README +++ b/microservices/03-resource-server/README @@ -1,23 +1,30 @@ -This project exposes REST endpoints (accessed by API gateway) and the endpoints are secured by OAuth2. +This project exposes REST endpoints (accessed by API gateway). They are secured by OAuth2. There is one REST endpoint defined in AuthRestController.java that is not secured. This endpoint is used by the API gateway to determine the roles of authenticating users. + +How to determine the user on behalf of whome a request is being made by the API gateway and the roles of that user? + +Since this is secured as an OAuth2 resource server, OAuth2 access token send with HTTP requests can just be used to authenticate the user. + +Assuming that the OAuth2 access token doesn't hold user roles, a different strategy should be used to determine user roles. One is to find user roles within this service itself by using the OAuth2 username (which can be trusted). This may for example involve looking for user roles details in a database accessed by this service. That approach can be trusted always but involves additional steps. Another approach is to just use the incoming HTTP request headers (added to the requests by the API gateway). To trust the role details so sent, this service should have been deployed in an access restricted network. Otherwise, an attacker may send HTTP requests with forged headers to make this service assume false user roles. Look at the UserRestController.java for details. + Some pom.xml dependencies: To make this Spring Boot project an OAuth2 resource server (Allow access from OAuth2 clients): <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-security-oauth2-resource-server</artifactId> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-security-oauth2-resource-server</artifactId> </dependency> To use H2 in-memory database (as configured in main/src/resources/application.yaml file): <dependency> - <groupId>com.h2database</groupId> - <artifactId>h2</artifactId> - <scope>runtime</scope> + <groupId>com.h2database</groupId> + <artifactId>h2</artifactId> + <scope>runtime</scope> </dependency> To use H2 database console accessible via a web browser: <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-h2console</artifactId> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-h2console</artifactId> </dependency> How to access the H2 database console: diff --git a/microservices/03-resource-server/src/main/java/com/example/resourceserver/security/UserRestController.java b/microservices/03-resource-server/src/main/java/com/example/resourceserver/security/UserRestController.java index 1b0598d..c7844a0 100644 --- a/microservices/03-resource-server/src/main/java/com/example/resourceserver/security/UserRestController.java +++ b/microservices/03-resource-server/src/main/java/com/example/resourceserver/security/UserRestController.java @@ -3,11 +3,8 @@ package com.example.resourceserver.security; import java.security.Principal; import java.util.Collection; import java.util.Map; -import java.util.Optional; -import java.util.Set; import java.util.stream.Collectors; -import org.springframework.http.ResponseEntity; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.annotation.AuthenticationPrincipal; @@ -26,17 +23,41 @@ public class UserRestController { 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(); } - // Get roles using the Authentication object + /** + * Roles returned by authentication.getAuthorities() may not always have custom + * roles. + * + * @param authentication + * @return + */ @GetMapping("/test-roles-auth") public Collection<String> getRoles(Authentication authentication) { return authentication.getAuthorities().stream() @@ -44,16 +65,28 @@ public class UserRestController { .collect(Collectors.toList()); } - // Inspect raw JWT claims directly + /** + * Inspect raw JWT claims directly. + * + * @param jwt + * @return + */ @GetMapping("/test-roles-jwt") public Map<String, Object> getClaims(@AuthenticationPrincipal Jwt jwt) { return jwt.getClaims(); // Extract custom JSON fields containing roles } - /* Not very secure because unverifiable headers can be introduced by unwanted parties */ + /** + * 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 ; + return "Roles: " + roles + ", username: " + username; } } |
