Esp32 webserver with user and password authentication

Hi, everyone, I'm now working on the esp32 webserver project but I'm a beginner in programming and I have a lot of trouble here are some of that. and I need your help...

#include <Base64.h>
#include <WiFi.h>

const char* ssid = "ESP";
const char* password = NULL;

WiFiServer server(80);

String header;
String output26State = "off";
String output27State = "off";

const int output26 = 26;
const int output27 = 27;

unsigned long currentTime = millis();
unsigned long previousTime = 0; 
const long timeoutTime = 2000;

// create a list of usernames and passwords
const char* users[][2] = {
  {"admin", "password"},
  {"user1", "1234"},
  {"user2", "5678"}
};

  String base64Decode(String encodedString) {
  const String base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  String decodedString = "";
  int encodedLength = encodedString.length();

  for (int i = 0; i < encodedLength; i += 4) {
    byte byte1 = base64Chars.indexOf(encodedString.charAt(i));
    byte byte2 = base64Chars.indexOf(encodedString.charAt(i + 1));
    byte byte3 = base64Chars.indexOf(encodedString.charAt(i + 2));
    byte byte4 = base64Chars.indexOf(encodedString.charAt(i + 3));

    byte byte5 = (byte1 << 2) | ((byte2 & 0x30) >> 4);
    byte byte6 = ((byte2 & 0x0f) << 4) | ((byte3 & 0x3c) >> 2);
    byte byte7 = ((byte3 & 0x03) << 6) | byte4;

    decodedString += (char)byte5;
    if (byte3 != 64) {
      decodedString += (char)byte6;
    }
    if (byte4 != 64) {
      decodedString += (char)byte7;
    }
  }

  return decodedString;
}

void setup() {
  Serial.begin(115200);
  delay(1000);
  Serial.println("Connecting to : ");
  WiFi.mode(WIFI_AP);
  WiFi.softAP(ssid, password);
  Serial.print("IP Address : ");
  Serial.println(WiFi.softAPIP());  
  
  pinMode(output26, OUTPUT);
  pinMode(output27, OUTPUT);
  
  digitalWrite(output26, LOW);
  digitalWrite(output27, LOW);
  server.begin();
}


void loop() {
  WiFiClient client = server.available();

  if (client) {
    currentTime = millis();
    previousTime = currentTime;
    Serial.println("New Client.");
    String currentLine = "";
    char c;
    while (client.connected() && currentTime - previousTime <= timeoutTime) {
      currentTime = millis();
      if (client.available()) {
        c = client.read();
        Serial.write(c);
        header += c;
        if (c == '\n') {
          if (currentLine.length() == 0) {
            
            // handle requests for the admin page
            if (header.indexOf("GET /admin") >= 0) {
              
                client.println("<h1>Admin page</h1>");
                client.println("<p>Welcome Admin!</p>");
                client.println("<form method='post' action='/changepassword'>");
                client.println("Old Password:<input type='password' name='old password'><br>");
                client.println("New Password:<input type='password' name='new password'><br>");
                client.println("<input type='submit' value='Change password'>");
                client.println("</form>");
                break;
              
            }

            // handle GPIO requests
            if (header.indexOf("GET /26/on") >= 0) {
              Serial.println("GPIO 26 on");
              output26State = "on";
              digitalWrite(output26, HIGH);
            } else if (header.indexOf("GET /26/off") >= 0) {
              Serial.println("GPIO 26 off");
              output26State = "off";
              digitalWrite(output26, LOW);
            } else if (header.indexOf("GET /27/on") >= 0) {
              Serial.println("GPIO 27 on");
              output27State = "on";
              digitalWrite(output27, HIGH);
            } else if (header.indexOf("GET /27/off") >= 0) {
              Serial.println("GPIO 27 off");
              output27State = "off";
              digitalWrite(output27, LOW);
            }

            // send HTTP response
            client.println("<!DOCTYPE html><html>");
            client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
            client.println("<link rel=\"icon\" href=\"data:,\">");

            // add styles to the HTML page
            client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
            client.println(".button { background-color: #4CAF50; border: none; color: white; padding: 16px 40px;");
            client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
            client.println(".button2 {background-color: #555555;}</style></head>");

            // add body content to the HTML page
            client.println("<body><h1>ESP32 Web Server</h1>");
            client.println("<h2>Admin Page</h2>");                  
            client.println("<p><a href=\"/admin\"><button class=\"button button3\">GO</button></a></p>");  
              
              client.println("<p>GPIO 26 - State " + output26State + "</p>");
                     
              if (output26State=="off") {
                client.println("<p><a href=\"/26/on\"><button class=\"button\">ON</button></a></p>");
              } else {
                client.println("<p><a href=\"/26/off\"><button class=\"button button2\">OFF</button></a></p>");
              } 
                                
              client.println("<p>GPIO 27 - State " + output27State + "</p>");
                     
              if (output27State=="off") {
                client.println("<p><a href=\"/27/on\"><button class=\"button\">ON</button></a></p>");
              } else {
                client.println("<p><a href=\"/27/off\"><button class=\"button button2\">OFF</button></a></p>");
              }
              client.println("</body></html>");
              
              
              client.println();
              
              break;
            }
            else{
              client.println("HTTP/1.1 401 Unauthorized");
              client.println("WWW-Authenticate: Basic realm=\"Secure\"");
              client.println("Content-Type: text/html");
              client.println();
              client.println("<html>Authentication failed</html>");
            }
          } else { 
            currentLine = "";
          }
        } else if (c != '\r') {  
          currentLine += c;      
        }
      }
    }
    
    header = "";
    
    client.stop();
    
  }

this code is for admin so I add some code on. here the code

#include <Base64.h>
#include <WiFi.h>

const char* ssid = "32";
const char* password = NULL;

WiFiServer server(80);

String header;
String output26State = "off";
String output27State = "off";

const int output26 = 26;
const int output27 = 27;

unsigned long currentTime = millis();
unsigned long previousTime = 0; 
const long timeoutTime = 2000;

// create a list of usernames and passwords
const char* users[][2] = {
  {"admin", "password"},
  {"user1", "1234"},
  {"user2", "5678"}
};

  String base64Decode(String encodedString) {
  const String base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  String decodedString = "";
  int encodedLength = encodedString.length();

  for (int i = 0; i < encodedLength; i += 4) {
    byte byte1 = base64Chars.indexOf(encodedString.charAt(i));
    byte byte2 = base64Chars.indexOf(encodedString.charAt(i + 1));
    byte byte3 = base64Chars.indexOf(encodedString.charAt(i + 2));
    byte byte4 = base64Chars.indexOf(encodedString.charAt(i + 3));

    byte byte5 = (byte1 << 2) | ((byte2 & 0x30) >> 4);
    byte byte6 = ((byte2 & 0x0f) << 4) | ((byte3 & 0x3c) >> 2);
    byte byte7 = ((byte3 & 0x03) << 6) | byte4;

    decodedString += (char)byte5;
    if (byte3 != 64) {
      decodedString += (char)byte6;
    }
    if (byte4 != 64) {
      decodedString += (char)byte7;
    }
  }

  return decodedString;
}

void setup() {
  Serial.begin(115200);
  delay(1000);
  Serial.println("Connecting to : ");
  WiFi.mode(WIFI_AP);
  WiFi.softAP(ssid, password);
  Serial.print("IP Address : ");
  Serial.println(WiFi.softAPIP());  
  
  pinMode(output26, OUTPUT);
  pinMode(output27, OUTPUT);
  
  digitalWrite(output26, LOW);
  digitalWrite(output27, LOW);
  server.begin();
}


void loop() {
  WiFiClient client = server.available();

  if (client) {
    currentTime = millis();
    previousTime = currentTime;
    Serial.println("New Client.");
    String currentLine = "";
    char c;
    while (client.connected() && currentTime - previousTime <= timeoutTime) {
      currentTime = millis();
      if (client.available()) {
        c = client.read();
        Serial.write(c);
        header += c;
        if (c == '\n') {
          if (currentLine.length() == 0) {
            
            bool auth = false;
            for (int i = 0; i < sizeof(users) / sizeof(users[0]); i++) {
              String user = users[i][0];
              String pass = users[i][1];
              if (header.indexOf("Authorization: Basic ") >= 0) {
                String encoded = header.substring(header.indexOf("Authorization: Basic ") + 21, header.indexOf("Authorization: Basic ") + 21 + 24);
                String decoded = base64Decode(encoded);
                if (decoded == user + ":" + pass) {
                  auth = true;
                  break;
                }
              }
            }
            if (!auth) {
              client.print("HTTP/1.1 401 Unauthorized\r\n");
              client.print("WWW-Authenticate: Basic realm=\"ESP32\"\r\n");
              client.print("Content-Type: text/html\r\n");
              client.print("Connection: close\r\n");
              client.print("\r\n");
              client.print("<!DOCTYPE HTML>\r\n");
              client.print("<html>\r\n");
              client.print("<body>\r\n");
              client.print("<h1>401 Unauthorized</h1>\r\n");
              client.print("</body>\r\n");
              client.print("</html>\r\n");
              break;
            }
            if(auth){
            if (header.indexOf("GET /admin") >= 0) {
                client.println("<h1>Admin page</h1>");
                client.println("<p>Welcome Admin!</p>");
                client.println("<form method='post' action='/changepassword'>");
                client.println("Old Password:<input type='password' name='old password'><br>");
                client.println("New Password:<input type='password' name='new password'><br>");
                client.println("<input type='submit' value='Change password'>");
                client.println("</form>");
                break;
              
            }

            // handle GPIO requests
            if (header.indexOf("GET /26/on") >= 0) {
              Serial.println("GPIO 26 on");
              output26State = "on";
              digitalWrite(output26, HIGH);
            } else if (header.indexOf("GET /26/off") >= 0) {
              Serial.println("GPIO 26 off");
              output26State = "off";
              digitalWrite(output26, LOW);
            } else if (header.indexOf("GET /27/on") >= 0) {
              Serial.println("GPIO 27 on");
              output27State = "on";
              digitalWrite(output27, HIGH);
            } else if (header.indexOf("GET /27/off") >= 0) {
              Serial.println("GPIO 27 off");
              output27State = "off";
              digitalWrite(output27, LOW);
            }

            // send HTTP response
            client.println("<!DOCTYPE html><html>");
            client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
            client.println("<link rel=\"icon\" href=\"data:,\">");

            // add styles to the HTML page
            client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
            client.println(".button { background-color: #4CAF50; border: none; color: white; padding: 16px 40px;");
            client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
            client.println(".button2 {background-color: #555555;}</style></head>");

            // add body content to the HTML page
            client.println("<body><h1>ESP32 Web Server</h1>");
            client.println("<h2>Admin Page</h2>");                  
            client.println("<p><a href=\"/admin\"><button class=\"button button3\">GO</button></a></p>");  
              
              client.println("<p>GPIO 26 - State " + output26State + "</p>");
                     
              if (output26State=="off") {
                client.println("<p><a href=\"/26/on\"><button class=\"button\">ON</button></a></p>");
              } else {
                client.println("<p><a href=\"/26/off\"><button class=\"button button2\">OFF</button></a></p>");
              } 
                                
              client.println("<p>GPIO 27 - State " + output27State + "</p>");
                     
              if (output27State=="off") {
                client.println("<p><a href=\"/27/on\"><button class=\"button\">ON</button></a></p>");
              } else {
                client.println("<p><a href=\"/27/off\"><button class=\"button button2\">OFF</button></a></p>");
              }
              client.println("</body></html>");
              
              
              client.println();
              
              break;
            }}
            
          } else { 
            currentLine = "";
          }
        } else if (c != '\r') {  
          currentLine += c;      
        }
      }
    }
    
    header = "";
    
    client.stop();
        }

from this code, when logging in with the user, pass that set in the code. It should go to the admin page but it is stuck in


and didn't go to the admin page.
I hope you guys can help :smiling_face_with_tear:
best regards.

for (int i = 0; i < sizeof(users) / sizeof(users[0]);

does that work if the users + passwords are not all the same size ?

And the obvious "What does it say in the Serial monitor

So it didn't go anywhere ?

So what part did not get executed ? Can you format the (2nd) code using ctrl-t and make sure that all the braces are in the correct spot ?

header = "";
    
    client.stop();

is there a loop running and adding to header before the client is stopped (cause i don't see one)

and yes it didn't go anywhere just stuck in the log-in loop. and I have also checked all the branches its all correct and have no errors. I also use chatGPT but can't solve the problem.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.