diff --git a/src/AutoConnect.cpp b/src/AutoConnect.cpp index 79de6f9..207d52a 100644 --- a/src/AutoConnect.cpp +++ b/src/AutoConnect.cpp @@ -2,8 +2,8 @@ * AutoConnect class implementation. * @file AutoConnect.cpp * @author hieromon@gmail.com - * @version 1.1.5 - * @date 2020-04-15 + * @version 1.2.0 + * @date 2020-04-17 * @copyright MIT license. */ @@ -167,7 +167,7 @@ bool AutoConnect::begin(const char* ssid, const char* passphrase, unsigned long if (_update) _update->enable(); } - // Rushing into the portal. + // Rushing into the portal. else { // The captive portal is effective at the autoRise is valid only. if (_apConfig.autoRise) { @@ -609,6 +609,7 @@ void AutoConnect::handleRequest(void) { if (!_ota) { _ota.reset(new AutoConnectOTA()); _ota->attach(*this); + _ota->authentication(_apConfig.auth); _ota->setTicker(_apConfig.tickerPort, _apConfig.tickerOn); } } diff --git a/src/AutoConnect.h b/src/AutoConnect.h index c3f6462..62c6ba8 100644 --- a/src/AutoConnect.h +++ b/src/AutoConnect.h @@ -2,8 +2,8 @@ * Declaration of AutoConnect class and accompanying AutoConnectConfig class. * @file AutoConnect.h * @author hieromon@gmail.com - * @version 1.1.5 - * @date 2020-04-01 + * @version 1.2.0 + * @date 2020-04-17 * @copyright MIT license. */ @@ -33,6 +33,7 @@ using WebServerClass = WebServer; #include "AutoConnectCredential.h" #include "AutoConnectTicker.h" #include "AutoConnectAux.h" +#include "AutoConnectTypes.h" // The realization of AutoConnectOTA is effective only by the explicit #include "AutoConnectOTA.h" @@ -43,42 +44,6 @@ class AutoConnectOTA; // Reference to avoid circular #include "AutoConnectUpdate.h" class AutoConnectUpdate; // Reference to avoid circular -/**< A type to save established credential at WiFi.begin automatically. */ -typedef enum AC_SAVECREDENTIAL { - AC_SAVECREDENTIAL_NEVER, - AC_SAVECREDENTIAL_AUTO -} AC_SAVECREDENTIAL_t; - -/**< URI that can be specified to AutoConnectConfig::bootUri. */ -typedef enum AC_ONBOOTURI { - AC_ONBOOTURI_ROOT, - AC_ONBOOTURI_HOME -} AC_ONBOOTURI_t; - -/** WiFi connection principle, it specifies the order of WiFi connecting with saved credentials. */ -typedef enum AC_PRINCIPLE { - AC_PRINCIPLE_RECENT, - AC_PRINCIPLE_RSSI -} AC_PRINCIPLE_t; - -/**< An enumerated type of the designated menu items. */ -typedef enum AC_MENUITEM { - AC_MENUITEM_NONE = 0x0000, - AC_MENUITEM_CONFIGNEW = 0x0001, - AC_MENUITEM_OPENSSIDS = 0x0002, - AC_MENUITEM_DISCONNECT = 0x0004, - AC_MENUITEM_RESET = 0x0008, - AC_MENUITEM_HOME = 0x0010, - AC_MENUITEM_UPDATE = 0x0020, - AC_MENUITEM_DEVINFO = 0x0040 -} AC_MENUITEM_t; - -/**< Specifier for using built-in OTA */ -typedef enum AC_OTA { - AC_OTA_EXTRA, - AC_OTA_BUILTIN -} AC_OTA_t; - class AutoConnectConfig { public: /** @@ -90,8 +55,8 @@ class AutoConnectConfig { apip(AUTOCONNECT_AP_IP), gateway(AUTOCONNECT_AP_GW), netmask(AUTOCONNECT_AP_NM), - apid(String(AUTOCONNECT_APID)), - psk(String(AUTOCONNECT_PSK)), + apid(String(F(AUTOCONNECT_APID))), + psk(String(F(AUTOCONNECT_PSK))), channel(AUTOCONNECT_AP_CH), hidden(0), minRSSI(AUTOCONNECT_MIN_RSSI), @@ -111,6 +76,10 @@ class AutoConnectConfig { tickerPort(AUTOCONNECT_TICKER_PORT), tickerOn(LOW), ota(AC_OTA_EXTRA), + auth(AC_AUTH_NONE), + authScope(AC_AUTHSCOPE_AUX), + username(String(F(AUTOCONNECT_APID))), + password(String(F(AUTOCONNECT_PSK))), hostName(String("")), homeUri(AUTOCONNECT_HOMEURI), title(AUTOCONNECT_MENU_TITLE), @@ -147,6 +116,10 @@ class AutoConnectConfig { tickerPort(AUTOCONNECT_TICKER_PORT), tickerOn(LOW), ota(AC_OTA_EXTRA), + auth(AC_AUTH_NONE), + authScope(AC_AUTHSCOPE_AUX), + username(String(F(AUTOCONNECT_APID))), + password(String(F(AUTOCONNECT_PSK))), hostName(String("")), homeUri(AUTOCONNECT_HOMEURI), title(AUTOCONNECT_MENU_TITLE), @@ -183,6 +156,10 @@ class AutoConnectConfig { tickerPort = o.tickerPort; tickerOn = o.tickerOn; ota = o.ota; + auth = o.auth; + authScope = o.authScope; + username = o.username; + password = o.password; hostName = o.hostName; homeUri = o.homeUri; title = o.title; @@ -219,6 +196,10 @@ class AutoConnectConfig { uint8_t tickerPort; /**< GPIO for flicker */ uint8_t tickerOn; /**< A signal for flicker turn on */ AC_OTA_t ota; /**< Attach built-in OTA */ + AC_AUTH_t auth; /**< Enable authentication */ + AC_AUTHSCOPE_t authScope; /**< certification scope */ + String username; /**< User name for authentication */ + String password; /**< Authentication password */ String hostName; /**< host name */ String homeUri; /**< A URI of user site */ String title; /**< Menu title */ diff --git a/src/AutoConnectAux.cpp b/src/AutoConnectAux.cpp index 7f9db61..0fecd01 100644 --- a/src/AutoConnectAux.cpp +++ b/src/AutoConnectAux.cpp @@ -1,9 +1,9 @@ /** * Implementation of AutoConnectAux class. - * @file AutoConnectAuxBasisImpl.h + * @file AutoConnectAux.cpp * @author hieromon@gmail.com - * @version 1.1.1 - * @date 2019-10-17 + * @version 1.2.0 + * @date 2020-04-17 * @copyright MIT license. */ #include @@ -513,6 +513,42 @@ PageElement* AutoConnectAux::_setupPage(const String& uri) { elm->addToken(String(FPSTR("AUX_ELEMENT")), std::bind(&AutoConnectAux::_insertElement, this, std::placeholders::_1)); // Restore transfer mode by each page mother->_responsePage->chunked(chunk); + + // Register authentication method + // HTTP authentication works only when connected to WiFi + if (WiFi.status() == WL_CONNECTED) { + // Determine the necessity of authentication from the conditions of + // AutoConnectConfig::authScope and derive the method. + const char* authUser = nullptr; + const char* authPass = nullptr; + HTTPAuthMethod method = DIGEST_AUTH; + bool authCond = false; + if (mother->_apConfig.authScope == AC_AUTHSCOPE_PARTIAL) { + if (_httpAuth != AC_AUTH_NONE) { + authCond = true; + if (_httpAuth == AC_AUTH_BASIC) + method = BASIC_AUTH; + } + } + else { + if (mother->_apConfig.auth != AC_AUTH_NONE) { + authCond = true; + if (mother->_apConfig.auth == AC_AUTH_BASIC) + method = BASIC_AUTH; + } + } + if (authCond) { + authUser = mother->_apConfig.username.c_str(); + authPass = mother->_apConfig.password.c_str(); + } + + // It entrusts authentication to PageBuilder. + // If WiFi is not connected, authUser will be null, and an authentication will not be issued. + String failsContent = String(FPSTR(AutoConnect::_ELM_HTML_HEAD)) + String(F("" AUTOCONNECT_TEXT_AUTHFAILED "")); + mother->_responsePage->authentication(authUser, authPass, method, AUTOCONNECT_AUTH_REALM, failsContent); + if (authUser) + AC_DBG_DUMB(",%s+%s/%s", method == BASIC_AUTH ? "BASIC" : "DIGEST", authUser, authPass); + } } } return elm; @@ -756,6 +792,13 @@ bool AutoConnectAux::_load(JsonObject& jb) { _uriStr = jb[F(AUTOCONNECT_JSON_KEY_URI)].as(); _uri = _uriStr.c_str(); _menu = jb[F(AUTOCONNECT_JSON_KEY_MENU)].as(); + String auth = jb[F(AUTOCONNECT_JSON_KEY_AUTH)].as(); + if (auth.equalsIgnoreCase(F(AUTOCONNECT_JSON_VALUE_BASIC))) + _httpAuth = AC_AUTH_BASIC; + else if (auth.equalsIgnoreCase(F(AUTOCONNECT_JSON_VALUE_DIGEST))) + _httpAuth = AC_AUTH_DIGEST; + if (auth.equalsIgnoreCase(F(AUTOCONNECT_JSON_VALUE_NONE))) + _httpAuth = AC_AUTH_NONE; JsonVariant elements = jb[F(AUTOCONNECT_JSON_KEY_ELEMENT)]; (void)_loadElement(elements, ""); return true; @@ -882,7 +925,7 @@ size_t AutoConnectAux::saveElement(Stream& out, std::vector const& names // Calculate JSON buffer size if (amount == 0) { bufferSize += JSON_OBJECT_SIZE(4); - bufferSize += sizeof(AUTOCONNECT_JSON_KEY_TITLE) + _title.length() + 1 + sizeof(AUTOCONNECT_JSON_KEY_URI) + _uriStr.length() + 1 + sizeof(AUTOCONNECT_JSON_KEY_MENU) + sizeof(AUTOCONNECT_JSON_KEY_ELEMENT); + bufferSize += sizeof(AUTOCONNECT_JSON_KEY_TITLE) + _title.length() + 1 + sizeof(AUTOCONNECT_JSON_KEY_URI) + _uriStr.length() + 1 + sizeof(AUTOCONNECT_JSON_KEY_MENU) + sizeof(AUTOCONNECT_JSON_KEY_ELEMENT) + sizeof(AUTOCONNECT_JSON_KEY_AUTH) + sizeof(AUTOCONNECT_JSON_VALUE_DIGEST); bufferSize += JSON_ARRAY_SIZE(_addonElm.size()); } else @@ -919,6 +962,10 @@ size_t AutoConnectAux::saveElement(Stream& out, std::vector const& names json[F(AUTOCONNECT_JSON_KEY_TITLE)] = _title; json[F(AUTOCONNECT_JSON_KEY_URI)] = _uriStr; json[F(AUTOCONNECT_JSON_KEY_MENU)] = _menu; + if (_httpAuth == AC_AUTH_BASIC) + json[F(AUTOCONNECT_JSON_KEY_AUTH)] = String(F(AUTOCONNECT_JSON_VALUE_BASIC)); + else if (_httpAuth == AC_AUTH_DIGEST) + json[F(AUTOCONNECT_JSON_KEY_AUTH)] = String(F(AUTOCONNECT_JSON_VALUE_DIGEST)); ArduinoJsonArray elements = json.createNestedArray(F(AUTOCONNECT_JSON_KEY_ELEMENT)); for (AutoConnectElement& elm : _addonElm) { ArduinoJsonObject element = elements.createNestedObject(); diff --git a/src/AutoConnectAux.h b/src/AutoConnectAux.h index df83c78..39fd5a8 100644 --- a/src/AutoConnectAux.h +++ b/src/AutoConnectAux.h @@ -1,9 +1,9 @@ /** * Declaration of AutoConnectAux basic class. - * @file AutoConnectAuxBasis.h + * @file AutoConnectAux.h * @author hieromon@gmail.com - * @version 1.1.1 - * @date 2019-10-17 + * @version 1.2.0 + * @date 2029-04-17 * @copyright MIT license. */ @@ -20,6 +20,7 @@ #endif // !AUTOCONNECT_USE_JSON #include #include "AutoConnectElement.h" +#include "AutoConnectTypes.h" class AutoConnect; // Reference to avoid circular class AutoConnectAux; // Reference to avoid circular @@ -53,6 +54,7 @@ class AutoConnectAux : public PageBuilder { AutoConnectElement& operator[](const String& name) { return *getElement(name); } void add(AutoConnectElement& addon); /**< Add an element to the auxiliary page */ void add(AutoConnectElementVT addons); /**< Add the element set to the auxiliary page */ + void authentication(const AC_AUTH_t auth) { _httpAuth = auth; } /**< Set certain page authentication */ void fetchElement(void); /**< Fetch AutoConnectElements values from http query parameters */ template T& getElement(const String& name); @@ -146,6 +148,7 @@ class AutoConnectAux : public PageBuilder { String _title; /**< A title of the page */ bool _menu; /**< Switch for menu displaying */ + AC_AUTH_t _httpAuth = AC_AUTH_NONE; /**< Applying HTTP authentication */ String _uriStr; /**< uri as String */ AutoConnectElementVT _addonElm; /**< A vector set of AutoConnectElements placed on this auxiliary page */ AutoConnectAux* _next = nullptr; /**< Auxiliary pages chain list */ @@ -160,4 +163,4 @@ class AutoConnectAux : public PageBuilder { friend class AutoConnect; }; -#endif // _AUTOCONNECTAUX_H_ +#endif // !_AUTOCONNECTAUX_H_ diff --git a/src/AutoConnectDefs.h b/src/AutoConnectDefs.h index 75d3bd9..40d8cb6 100644 --- a/src/AutoConnectDefs.h +++ b/src/AutoConnectDefs.h @@ -234,6 +234,11 @@ #define AUTOCONNECT_UPDATE_CATALOG_JSONBUFFER_SIZE 256 #endif // !AUTOCONNECT_UPDATE_CATALOG_JSONBUFFER_SIZE +// HTTP authentication default realm +#ifndef AUTOCONNECT_AUTH_REALM +#define AUTOCONNECT_AUTH_REALM "AUTOCONNECT" +#endif // !AUTOCONNECT_AUTH_REALM + // Explicitly avoiding unused warning with token handler of PageBuilder #define AC_UNUSED(expr) do { (void)(expr); } while (0) diff --git a/src/AutoConnectElementJson.h b/src/AutoConnectElementJson.h index 07724ae..05a37dc 100644 --- a/src/AutoConnectElementJson.h +++ b/src/AutoConnectElementJson.h @@ -2,8 +2,8 @@ * Declaration of AutoConnectElement extended classes using JSON. * @file AutoConnectElementJson.h * @author hieromon@gmail.com - * @version 1.0.0 - * @date 2019-09-03 + * @version 1.2.0 + * @date 2020-04-17 * @copyright MIT license. */ @@ -15,6 +15,7 @@ #define AUTOCONNECT_JSON_KEY_ACTION "action" #define AUTOCONNECT_JSON_KEY_ARRANGE "arrange" +#define AUTOCONNECT_JSON_KEY_AUTH "auth" #define AUTOCONNECT_JSON_KEY_CHECKED "checked" #define AUTOCONNECT_JSON_KEY_ELEMENT "element" #define AUTOCONNECT_JSON_KEY_FORMAT "format" @@ -44,8 +45,10 @@ #define AUTOCONNECT_JSON_TYPE_ACSTYLE "ACStyle" #define AUTOCONNECT_JSON_TYPE_ACSUBMIT "ACSubmit" #define AUTOCONNECT_JSON_TYPE_ACTEXT "ACText" +#define AUTOCONNECT_JSON_VALUE_BASIC "basic" #define AUTOCONNECT_JSON_VALUE_BEHIND "behind" #define AUTOCONNECT_JSON_VALUE_BR "br" +#define AUTOCONNECT_JSON_VALUE_DIGEST "digest" #define AUTOCONNECT_JSON_VALUE_EXTERNAL "extern" #define AUTOCONNECT_JSON_VALUE_FS "fs" #define AUTOCONNECT_JSON_VALUE_HORIZONTAL "horizontal" diff --git a/src/AutoConnectLabels.h b/src/AutoConnectLabels.h index 3795b9c..d656ae1 100644 --- a/src/AutoConnectLabels.h +++ b/src/AutoConnectLabels.h @@ -2,7 +2,7 @@ * AutoConnect proper menu label constant definition. * @file AutoConnectLabels.h * @author hieromon@gmail.com - * @version 1.1.6 + * @version 1.2.0 * @date 2020-04-17 * @copyright MIT license. */ @@ -247,6 +247,11 @@ #define AUTOCONNECT_TEXT_OTAFAILURE "Failed to update: " #endif // !AUTOCONNECT_TEXT_OTAFAILURE +// Text: Authenticaton failed +#ifndef AUTOCONNECT_TEXT_AUTHFAILED +#define AUTOCONNECT_TEXT_AUTHFAILED "Authenticaton failed" +#endif // !AUTOCONNECT_TEXT_AUTHFAILED + // Menu Text: Connecting #ifndef AUTOCONNECT_MENUTEXT_CONNECTING #define AUTOCONNECT_MENUTEXT_CONNECTING "Connecting" diff --git a/src/AutoConnectOTA.cpp b/src/AutoConnectOTA.cpp index 8a094ec..bfca879 100644 --- a/src/AutoConnectOTA.cpp +++ b/src/AutoConnectOTA.cpp @@ -26,6 +26,15 @@ AutoConnectOTA::~AutoConnectOTA() { _auxResult.reset(nullptr); } +/** + * Request authentication with an OTA page access + * @param auth Authentication method + */ +void AutoConnectOTA::authentication(const AC_AUTH_t auth) { + if (_auxUpdate) + _auxUpdate->authentication(auth); +} + /** * Attach the AutoConnectOTA to hosted AutoConnect which constitutes * the update process. This function creates an OTA operation page as diff --git a/src/AutoConnectOTA.h b/src/AutoConnectOTA.h index 2e0d2ef..9ffc6fb 100644 --- a/src/AutoConnectOTA.h +++ b/src/AutoConnectOTA.h @@ -36,6 +36,7 @@ class AutoConnectOTA : public AutoConnectUploadHandler { AutoConnectOTA() : _status(OTA_IDLE), _tickerPort(-1), _tickerOn(LOW) {} ~AutoConnectOTA(); void attach(AutoConnect& portal); + void authentication(const AC_AUTH_t auth); /**< Set certain page authentication */ String error(void) const { return _err; } /**< Returns current error string */ void menu(const bool post) { _auxUpdate->menu(post); }; /**< Enabel or disable arranging a created AutoConnectOTA page in the menu. */ AC_OTAStatus_t status(void) const { return _status; } /**< Return current error status of the Update class */ diff --git a/src/AutoConnectPage.cpp b/src/AutoConnectPage.cpp index 2902402..93fa15c 100644 --- a/src/AutoConnectPage.cpp +++ b/src/AutoConnectPage.cpp @@ -1,8 +1,8 @@ /** * AutoConnect portal site web page implementation. - * @file AutoConnectPage.h + * @file AutoConnectPage.cpp * @author hieromon@gmail.com - * @version 1.1.6 + * @version 1.2.0 * @date 2020-04-17 * @copyright MIT license. */ @@ -1008,7 +1008,7 @@ String AutoConnect::_token_WIFI_MODE(PageArgument& args) { break; #endif default: - wifiMode = PSTR("experiment"); + wifiMode = PSTR("experimental"); } return String(FPSTR(wifiMode)); } @@ -1301,7 +1301,7 @@ String AutoConnect::_token_OPEN_SSID(PageArgument& args) { PGM_P rssiSym = _ssidNA; PGM_P ssidLock = _ssidNull; credit.load(i, &entry); - AC_DBG("A credential #%d loaded\n", (int)i); + AC_DBG("Credential #%d loaded\n", (int)i); for (int8_t sc = 0; sc < (int8_t)_scanCount; sc++) { if (!memcmp(entry.bssid, WiFi.BSSID(sc), sizeof(station_config_t::bssid))) { _connectCh = WiFi.channel(sc); @@ -1401,6 +1401,7 @@ String AutoConnect::_attachMenuItem(const AC_MENUITEM_t item) { */ PageElement* AutoConnect::_setupPage(String& uri) { PageElement *elm = new PageElement(); + bool reqAuth = false; // Restore menu title _menuTitle = _apConfig.title; @@ -1408,7 +1409,8 @@ PageElement* AutoConnect::_setupPage(String& uri) { // Build the elements of current requested page. if (uri == String(AUTOCONNECT_URI)) { - // Setup /auto + // Setup /_ac + reqAuth = true; _freeHeapSize = ESP.getFreeHeap(); elm->setMold(_PAGE_STAT); elm->addToken(String(FPSTR("HEAD")), std::bind(&AutoConnect::_token_HEAD, this, std::placeholders::_1)); @@ -1436,7 +1438,8 @@ PageElement* AutoConnect::_setupPage(String& uri) { } else if (uri == String(AUTOCONNECT_URI_CONFIG) && (_apConfig.menuItems & AC_MENUITEM_CONFIGNEW)) { - // Setup /auto/config + // Setup /_ac/config + reqAuth = true; elm->setMold(_PAGE_CONFIGNEW); elm->addToken(String(FPSTR("HEAD")), std::bind(&AutoConnect::_token_HEAD, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CSS_BASE")), std::bind(&AutoConnect::_token_CSS_BASE, this, std::placeholders::_1)); @@ -1455,7 +1458,8 @@ PageElement* AutoConnect::_setupPage(String& uri) { } else if (uri == String(AUTOCONNECT_URI_CONNECT) && (_apConfig.menuItems & AC_MENUITEM_CONFIGNEW || _apConfig.menuItems & AC_MENUITEM_OPENSSIDS)) { - // Setup /auto/connect + // Setup /_ac/connect + reqAuth = true; _menuTitle = FPSTR(AUTOCONNECT_MENUTEXT_CONNECTING); elm->setMold(_PAGE_CONNECTING); elm->addToken(String(FPSTR("REQ")), std::bind(&AutoConnect::_induceConnect, this, std::placeholders::_1)); @@ -1469,7 +1473,8 @@ PageElement* AutoConnect::_setupPage(String& uri) { } else if (uri == String(AUTOCONNECT_URI_OPEN) && (_apConfig.menuItems & AC_MENUITEM_OPENSSIDS)) { - // Setup /auto/open + // Setup /_ac/open + reqAuth = true; elm->setMold(_PAGE_OPENCREDT); elm->addToken(String(FPSTR("HEAD")), std::bind(&AutoConnect::_token_HEAD, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CSS_BASE")), std::bind(&AutoConnect::_token_CSS_BASE, this, std::placeholders::_1)); @@ -1483,7 +1488,7 @@ PageElement* AutoConnect::_setupPage(String& uri) { } else if (uri == String(AUTOCONNECT_URI_DISCON) && (_apConfig.menuItems & AC_MENUITEM_DISCONNECT)) { - // Setup /auto/disc + // Setup /_ac/disc _menuTitle = FPSTR(AUTOCONNECT_MENUTEXT_DISCONNECT); elm->setMold(_PAGE_DISCONN); elm->addToken(String(FPSTR("DISCONNECT")), std::bind(&AutoConnect::_induceDisconnect, this, std::placeholders::_1)); @@ -1495,7 +1500,7 @@ PageElement* AutoConnect::_setupPage(String& uri) { } else if (uri == String(AUTOCONNECT_URI_RESET) && (_apConfig.menuItems & AC_MENUITEM_RESET)) { - // Setup /auto/reset + // Setup /_ac/reset elm->setMold(_PAGE_RESETTING); elm->addToken(String(FPSTR("HEAD")), std::bind(&AutoConnect::_token_HEAD, this, std::placeholders::_1)); elm->addToken(String(FPSTR("BOOTURI")), std::bind(&AutoConnect::_token_BOOTURI, this, std::placeholders::_1)); @@ -1504,13 +1509,13 @@ PageElement* AutoConnect::_setupPage(String& uri) { } else if (uri == String(AUTOCONNECT_URI_RESULT)) { - // Setup /auto/result + // Setup /_ac/result elm->setMold("{{RESULT}}"); elm->addToken(String(FPSTR("RESULT")), std::bind(&AutoConnect::_invokeResult, this, std::placeholders::_1)); } else if (uri == String(AUTOCONNECT_URI_SUCCESS)) { - // Setup /auto/success + // Setup /_ac/success elm->setMold(_PAGE_SUCCESS); elm->addToken(String(FPSTR("HEAD")), std::bind(&AutoConnect::_token_HEAD, this, std::placeholders::_1)); elm->addToken(String(FPSTR("CSS_BASE")), std::bind(&AutoConnect::_token_CSS_BASE, this, std::placeholders::_1)); @@ -1530,7 +1535,7 @@ PageElement* AutoConnect::_setupPage(String& uri) { } else if (uri == String(AUTOCONNECT_URI_FAIL)) { - // Setup /auto/fail + // Setup /_ac/fail _menuTitle = FPSTR(AUTOCONNECT_MENUTEXT_FAILED); elm->setMold(_PAGE_FAIL); elm->addToken(String(FPSTR("HEAD")), std::bind(&AutoConnect::_token_HEAD, this, std::placeholders::_1)); @@ -1557,6 +1562,20 @@ PageElement* AutoConnect::_setupPage(String& uri) { _responsePage->chunked(_pageBuildMode[n].transMode); break; } + + // Regiter authentication method + bool authCond = _apConfig.auth != AC_AUTH_NONE && + _apConfig.authScope == AC_AUTHSCOPE_PORTAL && + WiFi.status() == WL_CONNECTED && + reqAuth; + if (authCond) { + HTTPAuthMethod auth = _apConfig.auth == AC_AUTH_BASIC ? BASIC_AUTH : DIGEST_AUTH; + String failsContent = String(FPSTR(AutoConnect::_ELM_HTML_HEAD)) + String(F("" AUTOCONNECT_TEXT_AUTHFAILED "")); + _responsePage->authentication(_apConfig.username.c_str(), _apConfig.password.c_str(), auth, AUTOCONNECT_AUTH_REALM, failsContent); + AC_DBG_DUMB(",%s+%s/%s", auth == BASIC_AUTH ? "BASIC" : "DIGEST", _apConfig.username.c_str(), _apConfig.password.c_str()); + } + else + _responsePage->authentication(nullptr, nullptr); } return elm; diff --git a/src/AutoConnectTypes.h b/src/AutoConnectTypes.h new file mode 100644 index 0000000..b761403 --- /dev/null +++ b/src/AutoConnectTypes.h @@ -0,0 +1,63 @@ +/** + * AutoConnect quoted type declarations. + * @file AutoConnectTypes.h + * @author hieromon@gmail.com + * @version 1.2.0 + * @date 2020-04-17 + * @copyright MIT license. + */ + +#ifndef _AUTOCONNECTTYPES_H_ +#define _AUTOCONNECTTYPES_H_ + +/**< A type to save established credential at WiFi.begin automatically. */ +typedef enum AC_SAVECREDENTIAL { + AC_SAVECREDENTIAL_NEVER, + AC_SAVECREDENTIAL_AUTO +} AC_SAVECREDENTIAL_t; + +/**< URI that can be specified to AutoConnectConfig::bootUri. */ +typedef enum AC_ONBOOTURI { + AC_ONBOOTURI_ROOT, + AC_ONBOOTURI_HOME +} AC_ONBOOTURI_t; + +/** WiFi connection principle, it specifies the order of WiFi connecting with saved credentials. */ +typedef enum AC_PRINCIPLE { + AC_PRINCIPLE_RECENT, + AC_PRINCIPLE_RSSI +} AC_PRINCIPLE_t; + +/**< An enumerated type of the designated menu items. */ +typedef enum AC_MENUITEM { + AC_MENUITEM_NONE = 0x0000, + AC_MENUITEM_CONFIGNEW = 0x0001, + AC_MENUITEM_OPENSSIDS = 0x0002, + AC_MENUITEM_DISCONNECT = 0x0004, + AC_MENUITEM_RESET = 0x0008, + AC_MENUITEM_HOME = 0x0010, + AC_MENUITEM_UPDATE = 0x0020, + AC_MENUITEM_DEVINFO = 0x0040 +} AC_MENUITEM_t; + +/**< Specifier for using built-in OTA */ +typedef enum AC_OTA { + AC_OTA_EXTRA, + AC_OTA_BUILTIN +} AC_OTA_t; + +/**< Scope of certification influence */ +typedef enum AC_AUTHSCOPE { + AC_AUTHSCOPE_PARTIAL, // Available for particular AUX-pages. + AC_AUTHSCOPE_AUX, // All AUX-pages are affected by an authentication. + AC_AUTHSCOPE_PORTAL // All AutoConnect pages are affected by an authentication. +} AC_AUTHSCOPE_t; + +/**< A type to enable authentication. */ +typedef enum AC_AUTH { + AC_AUTH_NONE, + AC_AUTH_DIGEST, + AC_AUTH_BASIC +} AC_AUTH_t; + +#endif // !_AUTOCONNECTTYPES_H_