Ports the fewo-webapp AuthInterceptor + requireAdmin onto three abstract
interfaces so consumer apps plug in their own user store, public paths,
and runtime config without forking:
auth/AuthPrincipal.hpp library-owned {id, username, role} value
auth/IAuthBackend.hpp resolveBy{Session,ApiKey,Cert}, hasActiveUsers,
deleteExpiredSessions
auth/IAuthPolicy.hpp isPublicPath, adminRoles, readonlyRoles,
setupModeActive (defaults: admin/readonly,
no public paths, setup off)
auth/IRuntimeConfig.hpp bindAddress, isLoopback
auth/AuthInterceptor.hpp intercept() running the same 6-step ladder as
fewo's original (public → setup → cert DN →
session/API key → CSRF → readonly)
auth/RequireRole.hpp requireUser + requireAdmin helpers reading
bundle data (config-driven role sets, not
hard-coded 'admin')
TokenHasher is passed in so the library doesn't prescribe SHA-256 vs.
whatever. Bundle keys match fewo's existing controllers so the consumer
migration in #418 is a straightforward adapter swap.
Smoke-compiled against oatpp 1.3.0 headers.
Closes fewo-webapp#413
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
55 lines
1.7 KiB
C++
55 lines
1.7 KiB
C++
#ifndef OATPP_AUTHKIT_AUTH_REQUIRE_ROLE_HPP
|
|
#define OATPP_AUTHKIT_AUTH_REQUIRE_ROLE_HPP
|
|
|
|
#include <memory>
|
|
#include <string>
|
|
|
|
#include "oatpp/web/protocol/http/Http.hpp"
|
|
#include "oatpp/web/server/api/ApiController.hpp"
|
|
#include "oatpp/core/macro/codegen.hpp"
|
|
|
|
#include "IAuthPolicy.hpp"
|
|
|
|
namespace oatpp_authkit {
|
|
|
|
using IncomingRequest = oatpp::web::protocol::http::incoming::Request;
|
|
using Status = oatpp::web::protocol::http::Status;
|
|
|
|
/**
|
|
* @brief Pull the authenticated user into local scope inside a controller
|
|
* endpoint. Throws 401 when no principal is present in the bundle.
|
|
*
|
|
* Usage inside an ENDPOINT:
|
|
* auto me = oatpp_authkit::requireUser(request);
|
|
* // me.id, me.role, me.username
|
|
*/
|
|
inline AuthPrincipal requireUser(const std::shared_ptr<IncomingRequest>& request) {
|
|
auto id = request->getBundleData<oatpp::String>("auth_user_id");
|
|
auto role = request->getBundleData<oatpp::String>("auth_user_role");
|
|
auto username = request->getBundleData<oatpp::String>("auth_username");
|
|
|
|
OATPP_ASSERT_HTTP(id && role, Status::CODE_401, "Authentication required");
|
|
|
|
AuthPrincipal p;
|
|
p.id = std::stoi(std::string(*id));
|
|
p.role = std::string(*role);
|
|
p.username = username ? std::string(*username) : "";
|
|
return p;
|
|
}
|
|
|
|
/**
|
|
* @brief Reject the request with 403 unless the authenticated user is in
|
|
* the policy's admin role set.
|
|
*/
|
|
inline AuthPrincipal requireAdmin(const std::shared_ptr<IncomingRequest>& request,
|
|
IAuthPolicy& policy)
|
|
{
|
|
auto me = requireUser(request);
|
|
OATPP_ASSERT_HTTP(policy.adminRoles().count(me.role) > 0,
|
|
Status::CODE_403, "Admin required");
|
|
return me;
|
|
}
|
|
|
|
} // namespace oatpp_authkit
|
|
|
|
#endif
|