package com.example.keycloakpattern; import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.jwt; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.web.servlet.MockMvc; @SpringBootTest(properties = "edge.internal-auth-token=test-internal-edge-token") @AutoConfigureMockMvc class ApiSecurityTest { @Autowired private MockMvc mockMvc; @Test void publicEndpointDoesNotRequireAuthentication() throws Exception { mockMvc.perform(get("/api/public")) .andExpect(status().isOk()) .andExpect(jsonPath("$.status").value("ok")); } @Test void protectedEndpointRejectsAnonymousRequests() throws Exception { mockMvc.perform(get("/api/me")) .andExpect(status().isUnauthorized()); } @Test void protectedEndpointAcceptsJwtAuthentication() throws Exception { mockMvc.perform(get("/api/me").with(jwt().jwt(token -> token .subject("test-subject") .claim("preferred_username", "regular-user")))) .andExpect(status().isOk()) .andExpect(jsonPath("$.subject").value("test-subject")) .andExpect(jsonPath("$.username").value("regular-user")); } @Test void edgeEndpointRejectsMissingTrustedHeaders() throws Exception { mockMvc.perform(get("/edge/me")) .andExpect(status().isUnauthorized()); } @Test void edgeEndpointRejectsForgedIdentityWithoutInternalToken() throws Exception { mockMvc.perform(get("/edge/me") .header("X-Auth-Request-User", "spoofed-admin")) .andExpect(status().isUnauthorized()); } @Test void edgeEndpointRejectsWrongInternalToken() throws Exception { mockMvc.perform(get("/edge/me") .header("X-Auth-Request-User", "spoofed-admin") .header("X-Internal-Auth-Token", "wrong-token")) .andExpect(status().isUnauthorized()); } @Test void edgeEndpointAcceptsIdentityFromTrustedEdge() throws Exception { mockMvc.perform(get("/edge/me") .header("X-Auth-Request-User", "regular-user") .header("X-Auth-Request-Email", "regular-user@example.test") .header("X-Internal-Auth-Token", "test-internal-edge-token")) .andExpect(status().isOk()) .andExpect(jsonPath("$.user").value("regular-user")) .andExpect(jsonPath("$.identityHeader").value("X-Auth-Request-User")); } }