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.

107 lines
3.9 KiB

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