Update to version 3.9.6

This commit is contained in:
2026-02-10 12:34:12 +01:00
parent 2617252395
commit c98a476228
94 changed files with 4593 additions and 1434 deletions

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// Copyright 2016-2025 Hristo Gochkov, Mathieu Carbou, Emil Muratov
// Copyright 2016-2026 Hristo Gochkov, Mathieu Carbou, Emil Muratov, Will Miles
//
// Authentication and authorization middlewares
@@ -29,30 +29,36 @@ static AsyncAuthenticationMiddleware basicAuthHash;
static AsyncAuthenticationMiddleware digestAuth;
static AsyncAuthenticationMiddleware digestAuthHash;
static AsyncAuthenticationMiddleware bearerAuthSharedKey;
static AsyncAuthenticationMiddleware bearerAuthJWT;
// complex authentication which adds request attributes for the next middlewares and handler
static AsyncMiddlewareFunction complexAuth([](AsyncWebServerRequest *request, ArMiddlewareNext next) {
if (!request->authenticate("user", "password")) {
if (request->authenticate("Mathieu", "password")) {
request->setAttribute("user", "Mathieu");
} else if (request->authenticate("Bob", "password")) {
request->setAttribute("user", "Bob");
} else {
return request->requestAuthentication();
}
// add attributes to the request for the next middlewares and handler
request->setAttribute("user", "Mathieu");
request->setAttribute("role", "staff");
if (request->hasParam("token")) {
request->setAttribute("token", request->getParam("token")->value().c_str());
if (request->getAttribute("user") == "Mathieu") {
request->setAttribute("role", "staff");
} else {
request->setAttribute("role", "user");
}
next();
});
static AsyncAuthorizationMiddleware authz([](AsyncWebServerRequest *request) {
return request->getAttribute("token") == "123";
return request->getAttribute("role") == "staff";
});
void setup() {
Serial.begin(115200);
#if SOC_WIFI_SUPPORTED || CONFIG_ESP_WIFI_REMOTE_ENABLED || LT_ARD_HAS_WIFI
#if ASYNCWEBSERVER_WIFI_SUPPORTED
WiFi.mode(WIFI_AP);
WiFi.softAP("esp-captive");
#endif
@@ -87,6 +93,36 @@ void setup() {
digestAuthHash.setAuthFailureMessage("Authentication failed");
digestAuthHash.setAuthType(AsyncAuthType::AUTH_DIGEST);
// bearer authentication with shared key
bearerAuthSharedKey.setAuthType(AsyncAuthType::AUTH_BEARER);
bearerAuthSharedKey.setToken("shared-secret-key");
// bearer authentication with a JWT token
bearerAuthJWT.setAuthType(AsyncAuthType::AUTH_BEARER);
bearerAuthJWT.setAuthentificationFunction([](AsyncWebServerRequest *request) {
const String &token = request->authChallenge();
// 1. decode base64 token
// 2. decrypt token
const String &decrypted = "..."; // TODO
// 3. validate token (check signature, expiration, etc)
bool valid = token == "<token>" || token == "<another token>";
if (!valid) {
return false;
}
// 4. extract user info from token and set request attributes
if (token == "<token>") {
request->setAttribute("user", "Mathieu");
request->setAttribute("role", "staff");
return true; // return true if token is valid, false otherwise
}
if (token == "<another token>") {
request->setAttribute("user", "Bob");
request->setAttribute("role", "user");
return true; // return true if token is valid, false otherwise
}
return false;
});
// basic authentication method
// curl -v -u admin:admin http://192.168.4.1/auth-basic
server
@@ -132,9 +168,9 @@ void setup() {
.addMiddleware(&digestAuthHash);
// test digest auth custom authorization middleware
// curl -v --digest -u user:password http://192.168.4.1/auth-custom?token=123 => OK
// curl -v --digest -u user:password http://192.168.4.1/auth-custom?token=456 => 403
// curl -v --digest -u user:FAILED http://192.168.4.1/auth-custom?token=456 => 401
// curl -v --digest -u Mathieu:password http://192.168.4.1/auth-custom => OK
// curl -v --digest -u Bob:password http://192.168.4.1/auth-custom => 403
// curl -v --digest -u any:password http://192.168.4.1/auth-custom => 401
server
.on(
"/auth-custom", HTTP_GET,
@@ -148,6 +184,32 @@ void setup() {
)
.addMiddlewares({&complexAuth, &authz});
// Bearer authentication with a shared key
// curl -v -H "Authorization: Bearer shared-secret-key" http://192.168.4.1/auth-bearer-shared-key => OK
server
.on(
"/auth-bearer-shared-key", HTTP_GET,
[](AsyncWebServerRequest *request) {
request->send(200, "text/plain", "Hello, world!");
}
)
.addMiddleware(&bearerAuthSharedKey);
// Bearer authentication with a JWT token
// curl -v -H "Authorization: Bearer <token>" http://192.168.4.1/auth-bearer-jwt => OK
// curl -v -H "Authorization: Bearer <another token>" http://192.168.4.1/auth-bearer-jwt => 403 Forbidden
// curl -v -H "Authorization: Bearer invalid-token" http://192.168.4.1/auth-bearer-jwt => 401 Unauthorized
server
.on(
"/auth-bearer-jwt", HTTP_GET,
[](AsyncWebServerRequest *request) {
Serial.println("User: " + request->getAttribute("user"));
Serial.println("Role: " + request->getAttribute("role"));
request->send(200, "text/plain", "Hello, world!");
}
)
.addMiddlewares({&bearerAuthJWT, &authz});
server.begin();
}