67 lines
2.7 KiB
Java
67 lines
2.7 KiB
Java
package com.example.keycloakpattern;
|
|
|
|
import java.util.Collections;
|
|
import java.util.LinkedHashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
|
|
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.RequestMapping;
|
|
import org.springframework.web.bind.annotation.RestController;
|
|
|
|
import jakarta.servlet.http.HttpServletRequest;
|
|
|
|
@RestController
|
|
@RequestMapping("/api")
|
|
public class ApiController {
|
|
|
|
@GetMapping("/public")
|
|
public Map<String, String> publicEndpoint() {
|
|
return Map.of("status", "ok", "service", "keycloak-pattern-api");
|
|
}
|
|
|
|
/**
|
|
* Reflects what actually reached the application after the proxy chain.
|
|
*
|
|
* <p>The reverse proxy contract is defined in {@code docs/reverse-proxy-headers.md}
|
|
* for a single nginx hop. The lab runs {@code nginx -> Traefik -> pod}, so this
|
|
* endpoint exists to measure the two-hop result instead of assuming it.
|
|
*
|
|
* <p>{@code scheme}, {@code secure} and {@code requestUrl} are the values Keycloak
|
|
* uses to build the {@code iss} claim and redirect URLs. If forwarded headers are
|
|
* lost or rewritten, the mismatch shows up here first.
|
|
*/
|
|
@GetMapping("/echo")
|
|
public Map<String, Object> echo(HttpServletRequest request) {
|
|
Map<String, List<String>> headers = new LinkedHashMap<>();
|
|
for (String name : Collections.list(request.getHeaderNames())) {
|
|
headers.put(name.toLowerCase(), Collections.list(request.getHeaders(name)));
|
|
}
|
|
|
|
Map<String, Object> response = new LinkedHashMap<>();
|
|
response.put("headers", headers);
|
|
response.put("remoteAddr", request.getRemoteAddr());
|
|
// Pod IP. Identifies which replica answered, which is what makes the
|
|
// host nginx upstream distribution and the sticky-session switch observable.
|
|
response.put("localAddr", request.getLocalAddr());
|
|
response.put("scheme", request.getScheme());
|
|
response.put("secure", request.isSecure());
|
|
response.put("serverName", request.getServerName());
|
|
response.put("serverPort", request.getServerPort());
|
|
response.put("requestUrl", request.getRequestURL().toString());
|
|
return response;
|
|
}
|
|
|
|
@GetMapping("/me")
|
|
public Map<String, Object> currentUser(@AuthenticationPrincipal Jwt jwt) {
|
|
Map<String, Object> response = new LinkedHashMap<>();
|
|
response.put("subject", jwt.getSubject());
|
|
response.put("username", jwt.getClaimAsString("preferred_username"));
|
|
response.put("issuer", jwt.getIssuer());
|
|
response.put("audience", jwt.getAudience());
|
|
return response;
|
|
}
|
|
}
|