10 changed files with 222 additions and 135 deletions
-
52src/AsyncAuthJsonWebHandler.h
-
19src/AsyncJsonWebHandler.h
-
45src/AuthenticationService.cpp
-
30src/AuthenticationService.h
-
120src/SecurityManager.cpp
-
61src/SecurityManager.h
-
4src/SettingsPersistence.h
-
4src/SettingsService.h
-
6src/SimpleService.h
-
12src/main.cpp
@ -0,0 +1,52 @@ |
|||||
|
#ifndef AsyncAuthJsonWebHandler_H_ |
||||
|
#define AsyncAuthJsonWebHandler_H_ |
||||
|
|
||||
|
#include <ESPAsyncWebServer.h> |
||||
|
#include <AsyncJsonWebHandler.h> |
||||
|
#include <ArduinoJson.h> |
||||
|
#include <SecurityManager.h> |
||||
|
|
||||
|
typedef std::function<void(AsyncWebServerRequest *request, JsonDocument &jsonDocument, Authentication &authentication)> AuthenticationJsonRequestCallback; |
||||
|
|
||||
|
/** |
||||
|
* Extends AsyncJsonWebHandler with a wrapper which verifies the user is authenticated. |
||||
|
* |
||||
|
* TODO - Extend with role checking support, possibly with a callback to verify the user. |
||||
|
*/ |
||||
|
class AsyncAuthJsonWebHandler: public AsyncJsonWebHandler { |
||||
|
|
||||
|
private: |
||||
|
SecurityManager *_securityManager; |
||||
|
using AsyncJsonWebHandler::onRequest; |
||||
|
|
||||
|
public: |
||||
|
|
||||
|
AsyncAuthJsonWebHandler() : |
||||
|
AsyncJsonWebHandler(), _securityManager(NULL) {} |
||||
|
|
||||
|
~AsyncAuthJsonWebHandler() {} |
||||
|
|
||||
|
void setSecurityManager(SecurityManager *securityManager) { |
||||
|
_securityManager = securityManager; |
||||
|
} |
||||
|
|
||||
|
void onRequest(AuthenticationJsonRequestCallback callback) { |
||||
|
AsyncJsonWebHandler::onRequest([this, callback](AsyncWebServerRequest *request, JsonDocument &jsonDocument) { |
||||
|
if(!_securityManager) { |
||||
|
Serial.print("Security manager not configured for endpoint: "); |
||||
|
Serial.println(_uri); |
||||
|
request->send(500); |
||||
|
return; |
||||
|
} |
||||
|
Authentication authentication = _securityManager->authenticateRequest(request); |
||||
|
if (!authentication.isAuthenticated()) { |
||||
|
request->send(401); |
||||
|
return; |
||||
|
} |
||||
|
callback(request, jsonDocument, authentication); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
#endif // end AsyncAuthJsonWebHandler_H_ |
@ -0,0 +1,45 @@ |
|||||
|
#include <AuthenticationService.h>
|
||||
|
|
||||
|
AuthenticationService::AuthenticationService(AsyncWebServer* server, SecurityManager* securityManager): |
||||
|
_server(server), _securityManager(securityManager) { |
||||
|
server->on(VERIFY_AUTHORIZATION_PATH, HTTP_GET, std::bind(&AuthenticationService::verifyAuthorization, this, std::placeholders::_1)); |
||||
|
|
||||
|
_signInHandler.setUri(SIGN_IN_PATH); |
||||
|
_signInHandler.setMethod(HTTP_POST); |
||||
|
_signInHandler.setMaxContentLength(MAX_SECURITY_MANAGER_SETTINGS_SIZE); |
||||
|
_signInHandler.onRequest(std::bind(&AuthenticationService::signIn, this, std::placeholders::_1, std::placeholders::_2)); |
||||
|
server->addHandler(&_signInHandler); |
||||
|
} |
||||
|
|
||||
|
AuthenticationService::~AuthenticationService() {} |
||||
|
|
||||
|
/**
|
||||
|
* Verifys that the request supplied a valid JWT. |
||||
|
*/ |
||||
|
void AuthenticationService::verifyAuthorization(AsyncWebServerRequest *request) { |
||||
|
Authentication authentication = _securityManager->authenticateRequest(request); |
||||
|
request->send(authentication.isAuthenticated() ? 200: 401); |
||||
|
} |
||||
|
|
||||
|
/**
|
||||
|
* Signs in a user if the username and password match. Provides a JWT to be used in the Authorization header in subsequent requests. |
||||
|
*/ |
||||
|
void AuthenticationService::signIn(AsyncWebServerRequest *request, JsonDocument &jsonDocument){ |
||||
|
if (jsonDocument.is<JsonObject>()) { |
||||
|
String username = jsonDocument["username"]; |
||||
|
String password = jsonDocument["password"]; |
||||
|
Authentication authentication = _securityManager->authenticate(username, password); |
||||
|
if (authentication.isAuthenticated()) { |
||||
|
User* user = authentication.getUser(); |
||||
|
AsyncJsonResponse * response = new AsyncJsonResponse(MAX_USERS_SIZE); |
||||
|
JsonObject jsonObject = response->getRoot(); |
||||
|
jsonObject["access_token"] = _securityManager->generateJWT(user); |
||||
|
response->setLength(); |
||||
|
request->send(response); |
||||
|
return; |
||||
|
} |
||||
|
} |
||||
|
AsyncWebServerResponse *response = request->beginResponse(401); |
||||
|
request->send(response); |
||||
|
} |
||||
|
|
@ -0,0 +1,30 @@ |
|||||
|
#ifndef AuthenticationService_H_ |
||||
|
#define AuthenticationService_H_ |
||||
|
|
||||
|
#include <SecurityManager.h> |
||||
|
|
||||
|
#define VERIFY_AUTHORIZATION_PATH "/rest/verifyAuthorization" |
||||
|
#define SIGN_IN_PATH "/rest/signIn" |
||||
|
|
||||
|
#define MAX_AUTHENTICATION_SIZE 256 |
||||
|
|
||||
|
class AuthenticationService { |
||||
|
|
||||
|
public: |
||||
|
|
||||
|
AuthenticationService(AsyncWebServer* server, SecurityManager* securityManager) ; |
||||
|
~AuthenticationService(); |
||||
|
|
||||
|
private: |
||||
|
// server instance |
||||
|
AsyncWebServer* _server; |
||||
|
SecurityManager* _securityManager; |
||||
|
AsyncJsonWebHandler _signInHandler; |
||||
|
|
||||
|
// endpoint functions |
||||
|
void signIn(AsyncWebServerRequest *request, JsonDocument &jsonDocument); |
||||
|
void verifyAuthorization(AsyncWebServerRequest *request); |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
#endif // end SecurityManager_h |
Write
Preview
Loading…
Cancel
Save
Reference in new issue