Skip to content

Commit 4ff0d5c

Browse files
authored
Remove SSR no-origin allowance and add .dockerignore (#9)
1 parent 051fca6 commit 4ff0d5c

5 files changed

Lines changed: 96 additions & 66 deletions

File tree

.dockerignore

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Git
2+
.git
3+
.gitignore
4+
.gitattributes
5+
6+
# Documentation
7+
*.md
8+
README.md
9+
HOSTING_OPTIONS.md
10+
RAILWAY_DEPLOYMENT.md
11+
12+
# IDE
13+
.idea
14+
.vscode
15+
*.iml
16+
*.ipr
17+
*.iws
18+
.settings
19+
.project
20+
.classpath
21+
22+
# Build outputs (will be built in container)
23+
build/
24+
out/
25+
target/
26+
dist/
27+
.gradle/
28+
29+
# Test files
30+
src/test/
31+
test/
32+
*.test.*
33+
34+
# Logs
35+
*.log
36+
logs/
37+
38+
# Environment files
39+
.env
40+
.env.*
41+
*.env
42+
*.env.local
43+
*.env.*.local
44+
45+
# OS files
46+
.DS_Store
47+
Thumbs.db
48+
*.swp
49+
*.swo
50+
*.bak
51+
52+
# Node (if any)
53+
node_modules/
54+
npm-debug.log
55+
yarn-error.log
56+
57+
# Coverage reports
58+
coverage/
59+
.nyc_output/
60+
test-results/
61+
62+
# Temporary files
63+
*.tmp
64+
*.temp
65+
.cache/
66+
67+
# Railway specific (if any)
68+
railway.json
69+
.railway/
70+
71+
# Docker
72+
Dockerfile*
73+
docker-compose*.yml
74+
.dockerignore

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
version=1.11.1
1+
version=1.11.2

src/main/java/com/kapil/personalwebsite/config/OriginVerificationFilter.java

Lines changed: 5 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -35,21 +35,18 @@ public class OriginVerificationFilter implements Filter {
3535
private static final Logger LOGGER = LoggerFactory.getLogger(OriginVerificationFilter.class);
3636

3737
private final String serverApiKey;
38-
private final boolean allowNoOriginForSSR;
3938
private final Set<String> allowedOriginsSet;
4039

4140
public OriginVerificationFilter(@Value("${api.server-key}") String serverApiKey,
42-
@Value("${cors.allowed-origins}") String allowedOrigins,
43-
@Value("${ssr.allow-no-origin}") boolean allowNoOriginForSSR) {
41+
@Value("${cors.allowed-origins}") String allowedOrigins) {
4442
this.serverApiKey = serverApiKey;
45-
this.allowNoOriginForSSR = allowNoOriginForSSR;
4643
if (StringUtils.hasText(allowedOrigins)) {
4744
this.allowedOriginsSet = Arrays.stream(allowedOrigins.split(","))
4845
.map(String::trim)
4946
.filter(StringUtils::hasText)
5047
.collect(Collectors.toSet());
51-
LOGGER.info("OriginVerificationFilter initialized with {} allowed origins, SSR allowed: {}",
52-
allowedOriginsSet.size(), allowNoOriginForSSR);
48+
LOGGER.info("OriginVerificationFilter initialized with {} allowed origins",
49+
allowedOriginsSet.size());
5350
} else {
5451
this.allowedOriginsSet = Collections.emptySet();
5552
LOGGER.warn("No allowed origins configured for OriginVerificationFilter. All non-API key requests will be blocked.");
@@ -125,7 +122,7 @@ private boolean isRequestAuthorized(HttpServletRequest request) {
125122
}
126123

127124
/**
128-
* Authorize non-blog endpoints based on user authentication, API key, Origin, Referer headers, or SSR allowance.
125+
* Authorize non-blog endpoints based on user authentication, API key, Origin, or Referer headers.
129126
*
130127
* @param request the HTTP servlet request
131128
* @return true if authorized, false otherwise
@@ -141,13 +138,7 @@ private boolean authorizeOtherEndpoint(HttpServletRequest request) {
141138
String referer = request.getHeader(AppConstants.REFERER_HEADER);
142139
if (StringUtils.hasText(referer)) {
143140
String refererOrigin = extractOriginFromReferer(referer);
144-
if (refererOrigin != null && isAllowedOrigin(refererOrigin)) {
145-
return true;
146-
}
147-
}
148-
if (allowNoOriginForSSR && isLikelySSRRequest(request)) {
149-
LOGGER.debug("Allowing SSR request without Origin header from: {}", request.getRemoteAddr());
150-
return true;
141+
return refererOrigin != null && isAllowedOrigin(refererOrigin);
151142
}
152143
return false;
153144
}
@@ -177,22 +168,6 @@ private boolean isBlogEndpoint(String servletPath) {
177168
return AppConstants.PUBLIC_BLOG_PATHS.stream().anyMatch(servletPath::startsWith);
178169
}
179170

180-
/**
181-
* Determine if the request is likely an SSR/server request based on absence of Origin header.
182-
*
183-
* @param request the HTTP servlet request
184-
* @return true if this appears to be an SSR/server request
185-
*/
186-
private boolean isLikelySSRRequest(HttpServletRequest request) {
187-
String origin = request.getHeader(AppConstants.ORIGIN_HEADER);
188-
if (!StringUtils.hasText(origin)) {
189-
LOGGER.debug("Detected server-to-server request (no Origin header) from: {}",
190-
request.getRemoteAddr());
191-
return true;
192-
}
193-
return false;
194-
}
195-
196171
/**
197172
* Check if the given origin is in the list of allowed origins.
198173
*

src/main/resources/application.properties

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,6 @@ logging.level.org.springframework.data.mongodb=${MONGO_LOG_LEVEL:WARN}
4141
# API Server Key (required for SSR/server-to-server requests)
4242
api.server-key=${API_SERVER_KEY:}
4343

44-
# SSR Configuration to allow requests without Origin header (for SSR/server-to-server)
45-
ssr.allow-no-origin=${SSR_ALLOW_NO_ORIGIN:false}
46-
4744
# Email Configuration
4845
email.provider=${EMAIL_PROVIDER:}
4946
email.http-api.api-key=${EMAIL_HTTP_API_KEY:}

src/test/java/com/kapil/personalwebsite/config/OriginVerificationFilterTest.java

Lines changed: 16 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,8 @@ void setUp() throws IOException {
4949
when(response.getWriter()).thenReturn(new PrintWriter(responseWriter));
5050
}
5151

52-
private void initFilter(String allowedOrigins, String serverApiKey, boolean allowNoOriginForSSR) {
53-
filter = new OriginVerificationFilter(serverApiKey, allowedOrigins, allowNoOriginForSSR);
54-
}
55-
5652
private void initFilter(String allowedOrigins, String serverApiKey) {
57-
initFilter(allowedOrigins, serverApiKey, true);
53+
filter = new OriginVerificationFilter(serverApiKey, allowedOrigins);
5854
}
5955

6056
@Nested
@@ -82,13 +78,13 @@ void testInitialize_WithEmptyOrigins_ShouldHandleGracefully() {
8278
class NonProtectedEndpointTests {
8379

8480
@Test
85-
@DisplayName("Should allow requests to non-protected endpoints")
86-
void testDoFilter_NonProtectedEndpoint_ShouldAllow() throws Exception {
81+
@DisplayName("Should block requests to non-excluded endpoints without authorization")
82+
void testDoFilter_NonProtectedEndpoint_ShouldBlock() throws Exception {
8783
initFilter("https://example.com", "test-key");
8884
when(request.getRequestURI()).thenReturn("/api/health");
8985
filter.doFilter(request, response, filterChain);
90-
verify(filterChain).doFilter(request, response);
91-
verify(response, never()).setStatus(anyInt());
86+
verify(filterChain, never()).doFilter(request, response);
87+
verify(response).setStatus(HttpStatus.FORBIDDEN.value());
9288
}
9389

9490
@Test
@@ -152,9 +148,9 @@ void testDoFilter_WithValidApiKey_ShouldAllow() throws Exception {
152148
}
153149

154150
@Test
155-
@DisplayName("Should block invalid API key when SSR is disabled")
151+
@DisplayName("Should block invalid API key")
156152
void testDoFilter_WithInvalidApiKey_SSRDisabled_ShouldBlock() throws Exception {
157-
initFilter("https://example.com", "test-secret-key", false);
153+
initFilter("https://example.com", "test-secret-key");
158154
when(request.getRequestURI()).thenReturn("/blogs/published");
159155
when(request.getMethod()).thenReturn("GET");
160156
when(request.getHeader("X-API-Key")).thenReturn("wrong-key");
@@ -195,9 +191,9 @@ void testDoFilter_WithValidReferer_ShouldAllow() throws Exception {
195191
}
196192

197193
@Test
198-
@DisplayName("Should block invalid referer when SSR is disabled")
194+
@DisplayName("Should block invalid referer")
199195
void testDoFilter_WithInvalidReferer_SSRDisabled_ShouldBlock() throws Exception {
200-
initFilter("https://example.com", "test-key", false);
196+
initFilter("https://example.com", "test-key");
201197
when(request.getRequestURI()).thenReturn("/blogs/published");
202198
when(request.getMethod()).thenReturn("GET");
203199
when(request.getHeader("Referer")).thenReturn("https://malicious.com/hack");
@@ -234,25 +230,13 @@ void testDoFilter_OriginPrecedence_ShouldUseOrigin() throws Exception {
234230
}
235231

236232
@Nested
237-
@DisplayName("SSR Detection Tests")
238-
class SSRDetectionTests {
239-
240-
@Test
241-
@DisplayName("Should allow SSR requests (no Origin) when SSR is enabled")
242-
void testDoFilter_NoOrigin_SSREnabled_ShouldAllow() throws Exception {
243-
initFilter("https://example.com", "test-key", true);
244-
when(request.getRequestURI()).thenReturn("/blogs/published");
245-
when(request.getMethod()).thenReturn("GET");
246-
when(request.getRemoteAddr()).thenReturn("127.0.0.1");
247-
filter.doFilter(request, response, filterChain);
248-
verify(filterChain).doFilter(request, response);
249-
verify(response, never()).setStatus(anyInt());
250-
}
233+
@DisplayName("Missing Origin Header Tests")
234+
class MissingOriginHeaderTests {
251235

252236
@Test
253-
@DisplayName("Should block requests without Origin when SSR is disabled")
254-
void testDoFilter_NoOrigin_SSRDisabled_ShouldBlock() throws Exception {
255-
initFilter("https://example.com", "test-key", false);
237+
@DisplayName("Should block requests without Origin header")
238+
void testDoFilter_NoOriginHeader_ShouldBlock() throws Exception {
239+
initFilter("https://example.com", "test-key");
256240
when(request.getRequestURI()).thenReturn("/blogs/published");
257241
when(request.getMethod()).thenReturn("GET");
258242
filter.doFilter(request, response, filterChain);
@@ -261,9 +245,9 @@ void testDoFilter_NoOrigin_SSRDisabled_ShouldBlock() throws Exception {
261245
}
262246

263247
@Test
264-
@DisplayName("Browser request with invalid Origin should still be blocked even with SSR enabled")
248+
@DisplayName("Should block requests with invalid Origin header")
265249
void testDoFilter_BrowserWithInvalidOrigin_SSREnabled_ShouldBlock() throws Exception {
266-
initFilter("https://example.com", "test-key", true);
250+
initFilter("https://example.com", "test-key");
267251
when(request.getRequestURI()).thenReturn("/blogs/published");
268252
when(request.getMethod()).thenReturn("GET");
269253
when(request.getHeader("Origin")).thenReturn("https://malicious.com");

0 commit comments

Comments
 (0)