Body-bearing methods (POST/PUT/PATCH) now reject: - missing Content-Length → 411 - malformed Content-Length → 400 - non-identity Transfer-Encoding (chunked, etc.) → 411 - declared length > maxBytes → 413 (unchanged) GET/HEAD/DELETE/OPTIONS/TRACE pass through unchanged. Consumers needing the legacy fail-open behaviour pass `requireContentLength = false`. Bump to 0.3.3 (behaviour tightening — consumers on default ctor see new 411/400 responses on requests that previously sailed through). Closes #4 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| cmake | ||
| docs | ||
| include/oatpp-authkit | ||
| test | ||
| .gitignore | ||
| CMakeLists.txt | ||
| README.md | ||
oatpp-authkit
Header-only C++ library distilled from fewo-webapp's hardened auth / security stack. Header-only, oatpp 1.3+, C++17.
What's in v0.1 (the clean-lift set)
| Header | Purpose |
|---|---|
interceptor/SecurityHeadersInterceptor.hpp |
CSP, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy. Strict defaults. |
interceptor/BodySizeLimitInterceptor.hpp |
Reject request bodies above a configurable limit with 413 before they hit your handlers. |
handler/JsonErrorHandler.hpp |
Normalises thrown exceptions into {status, message} JSON so controllers never leak raw HTML error pages. |
util/RateLimiter.hpp |
In-memory token-bucket keyed on an arbitrary string (typically the client IP from clientIpTrusted). |
util/TokenExtract.hpp |
extractToken (Cookie/Bearer), isValidIp (IPv4/IPv6 via inet_pton), clientIpTrusted (loopback-gated XFF). |
startup/RequireEncryptionKey.hpp |
requireEncryptionKey(envVarName, encryptionEnabled, allowPlaintext) — refuse startup without a symmetric key unless a dev flag overrides. |
Consume via CMake
# FetchContent (pin to a tag):
include(FetchContent)
FetchContent_Declare(oatpp-authkit
GIT_REPOSITORY https://git.uwe-schuster.info/uwe.admin/oatpp-authkit.git
GIT_TAG v0.1.0)
FetchContent_MakeAvailable(oatpp-authkit)
target_link_libraries(app PRIVATE oatpp::authkit)
Or after cmake --install:
find_package(oatpp-authkit 0.1 REQUIRED)
target_link_libraries(app PRIVATE oatpp::authkit)
Browser-friendly 401/403
By default AuthInterceptor returns application/json for every rejection,
which is correct for /api/* callers but breaks browser navigation: a user
following a stale link or an expired password-reset URL sees a raw
{"status":"Unauthorized"} instead of a real page.
Override IAuthPolicy::unauthenticatedRedirect(path) to redirect browser
navigations to a login or landing page while keeping JSON responses for
fetch/axios callers (detected via path prefix /api/,
X-Requested-With: XMLHttpRequest, or an Accept header that prefers
application/json):
class AppAuthPolicy : public oatpp_authkit::IAuthPolicy {
public:
std::optional<std::string>
unauthenticatedRedirect(const std::string& path) override {
return "/?next=" + oatpp_authkit::AuthInterceptor::urlEncode(path);
}
};
Returning std::nullopt (the default) preserves the legacy JSON behaviour
for all responses.
Tests
cmake -B build -DOATPP_AUTHKIT_BUILD_TESTS=ON
cmake --build build
ctest --test-dir build --output-on-failure
Tests are off by default so consumers pulling the library in via
FetchContent don't pay the cost.
Roadmap
- v0.2 —
AuthInterceptor+requireAdminported onto three seams (IAuthBackend,IAuthPolicy,IRuntimeConfig) so consumers plug in their own user store, public-path list, and admin role set without forking the interceptor. - Later — session cookie helpers, API-key rotation, re-encryption migration.
See docs/security-baseline.md for language-neutral CSP / rate-limit / body-size
constants that non-C++ consumers can re-implement directly.