Fork of the excellent esp8266-react - https://github.com/rjwats/esp8266-react
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

140 lines
5.0 KiB

  1. #include <SecuritySettingsService.h>
  2. #if FT_ENABLED(FT_SECURITY)
  3. SecuritySettingsService::SecuritySettingsService(AsyncWebServer* server, FS* fs) :
  4. _httpEndpoint(SecuritySettings::read, SecuritySettings::update, this, server, SECURITY_SETTINGS_PATH, this),
  5. _fsPersistence(SecuritySettings::read, SecuritySettings::update, this, fs, SECURITY_SETTINGS_FILE),
  6. _jwtHandler(FACTORY_JWT_SECRET) {
  7. addUpdateHandler([&](const String& originId) { configureJWTHandler(); }, false);
  8. }
  9. void SecuritySettingsService::begin() {
  10. _fsPersistence.readFromFS();
  11. configureJWTHandler();
  12. }
  13. Authentication SecuritySettingsService::authenticateRequest(AsyncWebServerRequest* request) {
  14. AsyncWebHeader* authorizationHeader = request->getHeader(AUTHORIZATION_HEADER);
  15. if (authorizationHeader) {
  16. String value = authorizationHeader->value();
  17. if (value.startsWith(AUTHORIZATION_HEADER_PREFIX)) {
  18. value = value.substring(AUTHORIZATION_HEADER_PREFIX_LEN);
  19. return authenticateJWT(value);
  20. }
  21. } else if (request->hasParam(ACCESS_TOKEN_PARAMATER)) {
  22. AsyncWebParameter* tokenParamater = request->getParam(ACCESS_TOKEN_PARAMATER);
  23. String value = tokenParamater->value();
  24. return authenticateJWT(value);
  25. }
  26. return Authentication();
  27. }
  28. void SecuritySettingsService::configureJWTHandler() {
  29. _jwtHandler.setSecret(_state.jwtSecret);
  30. }
  31. Authentication SecuritySettingsService::authenticateJWT(String& jwt) {
  32. DynamicJsonDocument payloadDocument(MAX_JWT_SIZE);
  33. _jwtHandler.parseJWT(jwt, payloadDocument);
  34. if (payloadDocument.is<JsonObject>()) {
  35. JsonObject parsedPayload = payloadDocument.as<JsonObject>();
  36. String username = parsedPayload["username"];
  37. for (User _user : _state.users) {
  38. if (_user.username == username && validatePayload(parsedPayload, &_user)) {
  39. return Authentication(_user);
  40. }
  41. }
  42. }
  43. return Authentication();
  44. }
  45. Authentication SecuritySettingsService::authenticate(const String& username, const String& password) {
  46. for (User _user : _state.users) {
  47. if (_user.username == username && _user.password == password) {
  48. return Authentication(_user);
  49. }
  50. }
  51. return Authentication();
  52. }
  53. inline void populateJWTPayload(JsonObject& payload, User* user) {
  54. payload["username"] = user->username;
  55. payload["admin"] = user->admin;
  56. }
  57. boolean SecuritySettingsService::validatePayload(JsonObject& parsedPayload, User* user) {
  58. DynamicJsonDocument jsonDocument(MAX_JWT_SIZE);
  59. JsonObject payload = jsonDocument.to<JsonObject>();
  60. populateJWTPayload(payload, user);
  61. return payload == parsedPayload;
  62. }
  63. String SecuritySettingsService::generateJWT(User* user) {
  64. DynamicJsonDocument jsonDocument(MAX_JWT_SIZE);
  65. JsonObject payload = jsonDocument.to<JsonObject>();
  66. populateJWTPayload(payload, user);
  67. return _jwtHandler.buildJWT(payload);
  68. }
  69. ArRequestFilterFunction SecuritySettingsService::filterRequest(AuthenticationPredicate predicate) {
  70. return [this, predicate](AsyncWebServerRequest* request) {
  71. Authentication authentication = authenticateRequest(request);
  72. return predicate(authentication);
  73. };
  74. }
  75. ArRequestHandlerFunction SecuritySettingsService::wrapRequest(ArRequestHandlerFunction onRequest,
  76. AuthenticationPredicate predicate) {
  77. return [this, onRequest, predicate](AsyncWebServerRequest* request) {
  78. Authentication authentication = authenticateRequest(request);
  79. if (!predicate(authentication)) {
  80. request->send(401);
  81. return;
  82. }
  83. onRequest(request);
  84. };
  85. }
  86. ArJsonRequestHandlerFunction SecuritySettingsService::wrapCallback(ArJsonRequestHandlerFunction onRequest,
  87. AuthenticationPredicate predicate) {
  88. return [this, onRequest, predicate](AsyncWebServerRequest* request, JsonVariant& json) {
  89. Authentication authentication = authenticateRequest(request);
  90. if (!predicate(authentication)) {
  91. request->send(401);
  92. return;
  93. }
  94. onRequest(request, json);
  95. };
  96. }
  97. #else
  98. User ADMIN_USER = User(FACTORY_ADMIN_USERNAME, FACTORY_ADMIN_PASSWORD, true);
  99. SecuritySettingsService::SecuritySettingsService(AsyncWebServer* server, FS* fs) : SecurityManager() {
  100. }
  101. SecuritySettingsService::~SecuritySettingsService() {
  102. }
  103. ArRequestFilterFunction SecuritySettingsService::filterRequest(AuthenticationPredicate predicate) {
  104. return [this, predicate](AsyncWebServerRequest* request) { return true; };
  105. }
  106. // Return the admin user on all request - disabling security features
  107. Authentication SecuritySettingsService::authenticateRequest(AsyncWebServerRequest* request) {
  108. return Authentication(ADMIN_USER);
  109. }
  110. // Return the function unwrapped
  111. ArRequestHandlerFunction SecuritySettingsService::wrapRequest(ArRequestHandlerFunction onRequest,
  112. AuthenticationPredicate predicate) {
  113. return onRequest;
  114. }
  115. ArJsonRequestHandlerFunction SecuritySettingsService::wrapCallback(ArJsonRequestHandlerFunction onRequest,
  116. AuthenticationPredicate predicate) {
  117. return onRequest;
  118. }
  119. #endif