Skip to content

Commit 5580fc3

Browse files
committed
eli-389 adding middleware to automatically add security headers to our responses
1 parent 6a69c54 commit 5580fc3

File tree

2 files changed

+65
-0
lines changed

2 files changed

+65
-0
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
"""Middleware package for the Eligibility Signposting API."""
2+
3+
from eligibility_signposting_api.middleware.security_headers import SecurityHeadersMiddleware
4+
5+
__all__ = ["SecurityHeadersMiddleware"]
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
"""Security headers middleware for Flask application.
2+
3+
This middleware adds security headers to all responses from the Lambda function.
4+
These headers are applied to successful responses (200, 201, etc.) from the application.
5+
6+
For API Gateway error responses (4xx, 5xx generated by API Gateway itself),
7+
see gateway_responses.tf in the infrastructure configuration.
8+
"""
9+
10+
from typing import ClassVar
11+
12+
from flask import Flask, Response
13+
14+
15+
class SecurityHeadersMiddleware:
16+
"""Middleware to add security headers to all Flask responses."""
17+
18+
# Security headers recommended for NHS APIs
19+
SECURITY_HEADERS: ClassVar[dict[str, str]] = {
20+
"Cache-Control": "no-store, private",
21+
"Strict-Transport-Security": "max-age=31536000; includeSubDomains",
22+
"X-Content-Type-Options": "nosniff",
23+
}
24+
25+
def __init__(self, app: Flask | None = None) -> None:
26+
"""Initialize the middleware.
27+
28+
Args:
29+
app: Flask application instance. Can be provided later via init_app()
30+
"""
31+
if app is not None:
32+
self.init_app(app)
33+
34+
def init_app(self, app: Flask) -> None:
35+
"""Initialize the middleware with a Flask application.
36+
37+
Args:
38+
app: Flask application instance to apply middleware to
39+
"""
40+
app.after_request(self.add_security_headers)
41+
42+
@classmethod
43+
def add_security_headers(cls, response: Response) -> Response:
44+
"""Add security headers to the Flask response.
45+
46+
This is called automatically by Flask after each request.
47+
48+
Args:
49+
response: Flask response object
50+
51+
Returns:
52+
Modified response object with security headers added
53+
"""
54+
for header, value in cls.SECURITY_HEADERS.items():
55+
# Only add header if it doesn't already exist
56+
# This allows specific endpoints to override if needed
57+
if header not in response.headers:
58+
response.headers[header] = value
59+
60+
return response

0 commit comments

Comments
 (0)