Skip to content

Commit cb0ed29

Browse files
committed
test: SecurityIT — end-to-end 200/401/403 + external-auth bypass
1 parent 6ee6910 commit cb0ed29

1 file changed

Lines changed: 147 additions & 0 deletions

File tree

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
package com.retailsvc.http;
2+
3+
import static java.net.http.HttpRequest.BodyPublishers.noBody;
4+
import static java.net.http.HttpResponse.BodyHandlers.ofString;
5+
import static org.assertj.core.api.Assertions.assertThat;
6+
7+
import java.util.Base64;
8+
import java.util.Map;
9+
import java.util.Optional;
10+
import org.junit.jupiter.api.Test;
11+
12+
class SecurityIT extends ServerBaseTest {
13+
14+
@Test
15+
void apiKeyAllowDenyAndMissing() throws Exception {
16+
server =
17+
OpenApiServer.builder()
18+
.spec(spec)
19+
.handlers(defaultHandlers())
20+
.securityValidator(
21+
"apiKeyAuth",
22+
(req, cred) ->
23+
cred instanceof Credential.ApiKeyCredential ak && "good".equals(ak.value())
24+
? Optional.of("api-principal")
25+
: Optional.empty())
26+
.securityValidator("bearerAuth", (req, cred) -> Optional.empty())
27+
.securityValidator("basicAuth", (req, cred) -> Optional.empty())
28+
.port(0)
29+
.build();
30+
31+
var client = httpClient();
32+
33+
var ok =
34+
client.send(
35+
newRequest(server, "/secure/api-key", "GET", noBody(), Map.of("X-API-Key", "good")),
36+
ofString());
37+
assertThat(ok.statusCode()).isEqualTo(200);
38+
39+
var missing =
40+
client.send(newRequest(server, "/secure/api-key", "GET", noBody(), Map.of()), ofString());
41+
assertThat(missing.statusCode()).isEqualTo(401);
42+
assertThat(missing.headers().firstValue("WWW-Authenticate"))
43+
.contains("ApiKey location=header, name=\"X-API-Key\"");
44+
assertThat(missing.body()).contains("\"status\":401");
45+
46+
var denied =
47+
client.send(
48+
newRequest(server, "/secure/api-key", "GET", noBody(), Map.of("X-API-Key", "bad")),
49+
ofString());
50+
assertThat(denied.statusCode()).isEqualTo(403);
51+
assertThat(denied.headers().firstValue("WWW-Authenticate")).isEmpty();
52+
}
53+
54+
@Test
55+
void bearerAllowAndMissing() throws Exception {
56+
server =
57+
OpenApiServer.builder()
58+
.spec(spec)
59+
.handlers(defaultHandlers())
60+
.securityValidator("apiKeyAuth", (req, cred) -> Optional.empty())
61+
.securityValidator(
62+
"bearerAuth",
63+
(req, cred) ->
64+
cred instanceof Credential.BearerCredential bc
65+
&& "good-token".equals(bc.token())
66+
? Optional.of("bearer-principal")
67+
: Optional.empty())
68+
.securityValidator("basicAuth", (req, cred) -> Optional.empty())
69+
.port(0)
70+
.build();
71+
72+
var client = httpClient();
73+
74+
var ok =
75+
client.send(
76+
newRequest(
77+
server,
78+
"/secure/bearer",
79+
"GET",
80+
noBody(),
81+
Map.of("Authorization", "Bearer good-token")),
82+
ofString());
83+
assertThat(ok.statusCode()).isEqualTo(200);
84+
85+
var missing =
86+
client.send(newRequest(server, "/secure/bearer", "GET", noBody(), Map.of()), ofString());
87+
assertThat(missing.statusCode()).isEqualTo(401);
88+
assertThat(missing.headers().firstValue("WWW-Authenticate")).contains("Bearer realm=\"api\"");
89+
}
90+
91+
@Test
92+
void basicAuthAllow() throws Exception {
93+
String creds = Base64.getEncoder().encodeToString("alice:s3cret".getBytes());
94+
server =
95+
OpenApiServer.builder()
96+
.spec(spec)
97+
.handlers(defaultHandlers())
98+
.securityValidator("apiKeyAuth", (req, cred) -> Optional.empty())
99+
.securityValidator("bearerAuth", (req, cred) -> Optional.empty())
100+
.securityValidator(
101+
"basicAuth",
102+
(req, cred) ->
103+
cred instanceof Credential.BasicCredential bc
104+
&& "alice".equals(bc.username())
105+
&& "s3cret".equals(bc.password())
106+
? Optional.of("basic-principal")
107+
: Optional.empty())
108+
.port(0)
109+
.build();
110+
111+
var ok =
112+
httpClient()
113+
.send(
114+
newRequest(
115+
server,
116+
"/secure/basic",
117+
"GET",
118+
noBody(),
119+
Map.of("Authorization", "Basic " + creds)),
120+
ofString());
121+
assertThat(ok.statusCode()).isEqualTo(200);
122+
}
123+
124+
@Test
125+
void externalAuthBypassesAllChecks() throws Exception {
126+
server =
127+
OpenApiServer.builder()
128+
.spec(spec)
129+
.handlers(defaultHandlers())
130+
.useExternalAuthentication()
131+
.port(0)
132+
.build();
133+
134+
var r =
135+
httpClient()
136+
.send(newRequest(server, "/secure/api-key", "GET", noBody(), Map.of()), ofString());
137+
assertThat(r.statusCode()).isEqualTo(200);
138+
}
139+
140+
private static Map<String, RequestHandler> defaultHandlers() {
141+
return Map.of(
142+
"secureApiKey", req -> Response.ok("{\"ok\":true}"),
143+
"secureBearer", req -> Response.ok("{\"ok\":true}"),
144+
"secureBasic", req -> Response.ok("{\"ok\":true}"),
145+
"secureOpen", req -> Response.ok("{\"ok\":true}"));
146+
}
147+
}

0 commit comments

Comments
 (0)