#ifndef SecuritySettingsService_h #define SecuritySettingsService_h #include #include #include #include #ifndef FACTORY_ADMIN_USERNAME #define FACTORY_ADMIN_USERNAME "admin" #endif #ifndef FACTORY_ADMIN_PASSWORD #define FACTORY_ADMIN_PASSWORD "admin" #endif #ifndef FACTORY_GUEST_USERNAME #define FACTORY_GUEST_USERNAME "guest" #endif #ifndef FACTORY_GUEST_PASSWORD #define FACTORY_GUEST_PASSWORD "guest" #endif #define SECURITY_SETTINGS_FILE "/config/securitySettings.json" #define SECURITY_SETTINGS_PATH "/rest/securitySettings" #define GENERATE_TOKEN_SIZE 512 #define GENERATE_TOKEN_PATH "/rest/generateToken" class SecuritySettings { public: String jwtSecret; std::list users; static void read(SecuritySettings & settings, JsonObject & root) { // secret root["jwt_secret"] = settings.jwtSecret; // users JsonArray users = root.createNestedArray("users"); for (User user : settings.users) { JsonObject userRoot = users.createNestedObject(); userRoot["username"] = user.username; userRoot["password"] = user.password; userRoot["admin"] = user.admin; } } static StateUpdateResult update(JsonObject & root, SecuritySettings & settings) { // secret settings.jwtSecret = root["jwt_secret"] | FACTORY_JWT_SECRET; // users settings.users.clear(); if (root["users"].is()) { for (JsonVariant user : root["users"].as()) { settings.users.push_back(User(user["username"], user["password"], user["admin"])); } } else { settings.users.push_back(User(FACTORY_ADMIN_USERNAME, FACTORY_ADMIN_PASSWORD, true)); settings.users.push_back(User(FACTORY_GUEST_USERNAME, FACTORY_GUEST_PASSWORD, false)); } return StateUpdateResult::CHANGED; } }; class SecuritySettingsService : public StatefulService, public SecurityManager { public: SecuritySettingsService(PsychicHttpServer * server, FS * fs); void begin(); void registerURI(); // Functions to implement SecurityManager Authentication authenticate(const String & username, const String & password); Authentication authenticateRequest(PsychicRequest * request); String generateJWT(User * user); PsychicRequestFilterFunction filterRequest(AuthenticationPredicate predicate); PsychicHttpRequestCallback wrapRequest(PsychicHttpRequestCallback onRequest, AuthenticationPredicate predicate); PsychicJsonRequestCallback wrapCallback(PsychicJsonRequestCallback onRequest, AuthenticationPredicate predicate); private: PsychicHttpServer * _server; HttpEndpoint _httpEndpoint; FSPersistence _fsPersistence; // ArduinoJsonJWT _jwtHandler; esp_err_t generateToken(PsychicRequest * request); void configureJWTHandler(); Authentication authenticateJWT(String & jwt); // Lookup the user by JWT boolean validatePayload(JsonObject & parsedPayload, User * user); // Verify the payload is correct }; #endif