Security headers middleware¶
SecurityHeadersMiddleware writes a standard set of browser-side security headers on every response. Each header is opt-out via std::optional<std::string> — set the option to std::nullopt to suppress it, or to an empty string to emit the header with no value.
Enabling it¶
src/main.cpp
#include <Baldr/Baldr.hpp>
int main()
{
auto builder = skr::ApplicationBuilder().WithExtension<BaldrExtension>();
auto app = builder.Build<WebApplication>();
app->Use<SecurityHeadersMiddleware>();
app->MapGet("/", [] { return Payload { .message = "ok" }; });
app->Run();
}
SecurityHeadersMiddleware is defined in src/Baldr/Middleware/SecurityHeaders.hpp. It has no constructor dependencies.
Options¶
SecurityHeadersOptions:
| Field | Default | Header emitted | Notes |
|---|---|---|---|
contentTypeOptions |
"nosniff" |
X-Content-Type-Options |
Disable browser MIME sniffing. |
frameOptions |
"DENY" |
X-Frame-Options |
Set to "SAMEORIGIN" to allow same-origin framing. |
referrerPolicy |
"strict-origin-when-cross-origin" |
Referrer-Policy |
Full Referrer-Policy grammar accepted. |
strictTransportSecurity |
std::nullopt |
Strict-Transport-Security |
Set explicitly in production, e.g. "max-age=31536000; includeSubDomains". |
permissionsPolicy |
std::nullopt |
Permissions-Policy |
E.g. "geolocation=(), microphone=()". |
crossOriginOpenerPolicy |
"same-origin" |
Cross-Origin-Opener-Policy |
|
crossOriginResourcePolicy |
"same-origin" |
Cross-Origin-Resource-Policy |
Set to "cross-origin" for public assets. |
crossOriginEmbedderPolicy |
std::nullopt |
Cross-Origin-Embedder-Policy |
Required by some isolation features. |
Set a field to std::nullopt to not emit that header. Set it to an empty string to emit the header with no value.
Production hardening¶
src/main.cpp
SecurityHeadersMiddleware::SecurityHeadersMiddleware(
SecurityHeadersOptions {
.strictTransportSecurity = "max-age=31536000; includeSubDomains",
.permissionsPolicy = "geolocation=(), microphone=(), camera=()",
.crossOriginEmbedderPolicy = "require-corp",
})
{}
Where to put it¶
Register SecurityHeadersMiddleware before CorsMiddleware so the security headers ride along on preflight OPTIONS responses too:
src/main.cpp
app.Use<RequestIdMiddleware>()
.Use<ExceptionHandlerMiddleware>()
.Use<LoggingMiddleware>()
.Use<CompressionMiddleware>()
.Use<SecurityHeadersMiddleware>()
.Use<CorsMiddleware>()
.Use<RateLimitMiddleware>();