ESP32 WebServer Library – authenticateBasicSHA1()

Home / References / ESP32 Library / WebServer Library

Description

The authenticateBasicSHA1() method provides a way to verify client credentials submitted via HTTP Basic Authentication, similar to the standard authenticate() method. The key difference lies in how the password is verified: instead of comparing the plaintext password sent by the client against a plaintext password stored in your code, authenticateBasicSHA1() calculates the SHA1 hash of the password sent by the client and compares it against a pre-calculated SHA1 hash stored in your code.

This approach avoids storing the actual password in plaintext within your ESP32 firmware, offering a minor security enhancement for the stored credentials. However, it’s crucial to understand that this method still relies on HTTP Basic Authentication. The client’s browser sends the username and password encoded in Base64 over the network. This encoding is easily reversible, meaning the actual password is still transmitted insecurely unless the connection is protected by HTTPS.

Like standard authentication, this method is typically used in conjunction with requestAuthentication() to prompt the user for credentials if they are missing or incorrect.


Syntax and Usage

The method is called on your WebServer object, providing the expected username and the expected SHA1 hash of the password.

// Pre-calculate the SHA1 hash of your desired password
const char* expected_username = "user";
const char* expected_password_sha1_hash = "40_character_hex_sha1_hash_string"; // e.g., for "password" -> "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8"

// Inside a request handler:
bool isAuthenticated = server.authenticateBasicSHA1(expected_username, expected_password_sha1_hash);

if (!isAuthenticated) {
  // Request credentials if authentication failed
  return server.requestAuthentication(BASIC_AUTH, "SHA1 Protected Area");
} else {
  // Proceed with authenticated access
  // ... send protected content ...
}
  • You must provide the correct username and the corresponding SHA1 password hash.
  • The SHA1 hash must be a 40-character lowercase hexadecimal string.

Argument(s)

This method requires the following arguments:

  • username: A const char* representing the username that the client is expected to provide.
  • sha1_password_hash: A const char* representing the pre-calculated SHA1 hash of the expected password. This must be a 40-character lowercase hexadecimal string (e.g., “5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8”). You need to generate this hash beforehand using external tools (like command-line sha1sum or online generators) or potentially cryptographic libraries on the ESP32 itself.

Return Value

This method returns a bool (boolean value):

  • true: If the client provided credentials via HTTP Basic Authentication, the provided username matches the username argument, AND the SHA1 hash calculated from the password provided by the client matches the sha1_password_hash argument.
  • false: If the client did not provide credentials, the username did not match, or the calculated SHA1 hash of the provided password did not match the stored hash.

Example Codes

Example 1 Basic Authentication verified with a SHA1 password hash

This example demonstrates protecting a resource at the /settings path using Basic Authentication verified with a SHA1 password hash.

Explanation:

  1. Include necessary libraries and configure WiFi credentials.
  2. Define the required username (auth_user).
  3. Define the required password’s SHA1 hash (auth_pass_sha1). In this example, we use the hash for the password “esp32secret”. You must generate the SHA1 hash for your chosen password. You can use online tools or command-line utilities like echo -n "yourpassword" | sha1sum (ensure no newline character is included in the hash calculation, hence the -n).
  4. Register a handler handleSettings() for the /settings path.
  5. Inside handleSettings(), call server.authenticateBasicSHA1() with the defined username and SHA1 hash.
  6. If it returns false, call server.requestAuthentication() to prompt the user.
  7. If it returns true, send the protected content.
  8. A public root handler is also included.
  9. To test:
    • Generate the SHA1 hash for your desired password (e.g., “esp32secret”). Replace the example hash in the code if needed.
    • Upload the sketch after filling in WiFi details. Get the IP address from Serial Monitor.
    • Access http://<ESP32_IP>/ (public page).
    • Access http://<ESP32_IP>/settings.
    • A browser login prompt should appear for the realm “ESP32 Settings”.
    • Enter the correct username (“config”) and the password (esp32secret). You should see the success message.
    • Try incorrect credentials; you should be prompted again or see an error.

If you need a tool to generate your own SHA1 password hash, you can use Example 2 code on this page. This code demonstrates how to create a simple utility on your ESP32 for generating SHA1 password hashes.

/*
 * Author: Avant Maker
 * Date: April 12, 2025
 * Version: 1.0
 * License: MIT 
 * 
 * Description: 
 * This example demonstrates how to use ESP32 WebServer Library's 
 * authenticateBasicSHA1() method to protect a resource at the /settings
 * path using Basic Authentication verified with a SHA1 password hash.
 *
 * Code Source:
 * This example code is sourced from the Comprehensive Guide
 * to the ESP32 Arduino Core Library, accessible on AvantMaker.com.
 * For additional code examples and in-depth documentation related to
 * the ESP32 Arduino Core Library, please visit:
 *
 * https://avantmaker.com/home/all-about-esp32-arduino-core-library/
 *
 * AvantMaker.com, your premier destination for all things
 * DIY, AI, IoT, Smart Home, and STEM projects. We are dedicated
 * to empowering makers, learners, and enthusiasts with
 * the resources they need to bring their innovative ideas to life.
 */

#include <WiFi.h>
#include <WebServer.h>

// Replace with your network credentials
const char* ssid = "your_SSID";          // Replace with your Wi-Fi SSID
const char* password = "your_PASSWORD";  // Replace with your Wi-Fi password

WebServer server(80);

// --- Authentication Details ---
// Define username
const char* auth_user = "config";
// Define the SHA1 hash of the desired password.
// This hash is for the password "esp32secret".
// The hash MUST be a 40-character lowercase hexadecimal string.
// Generate your own hash using AvantMaker's SHA1 hash tool.
// You can find this tool at the Example Code section of the following web page:
// https://avantmaker.com/references/esp32-arduino-core-index/esp32-webserver-library/esp32-webserver-library-authenticatebasicsha1/
const char* auth_pass_sha1 = "0db7cf3d5e811dcc1205017cd2b2d85577ab20c9"; // Example hash for "esp32secret" - REPLACE WITH YOUR HASH

// Handler for the protected settings page
void handleSettings() {
  Serial.println("Attempting to access /settings");

  // Check credentials using username and SHA1 hash of the password
  if (!server.authenticateBasicSHA1(auth_user, auth_pass_sha1)) {
    Serial.println("Authentication failed (SHA1 check), requesting credentials.");
    // If authentication fails, request credentials from the browser
    return server.requestAuthentication(BASIC_AUTH, "ESP32 Settings");
  }

  // If authentication succeeds
  Serial.println("Authentication successful (SHA1 check)!");
  server.send(200, "text/plain", "Settings Access Granted (SHA1 Authenticated)");
}

// Handler for the root page (public)
void handleRoot() {
  server.send(200, "text/html", "<h1>AvantMaker ESP32 Web Server</h1><p>Public Area</p><p>Access the <a href=\"/settings\">Settings</a> (requires SHA1 authentication).</p>");
}

void setup() {
  Serial.begin(115200);
  Serial.println();
  Serial.println("Connecting to WiFi...");

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.print("IP Address: ");
  Serial.println(WiFi.localIP());

  // Register public root handler
  server.on("/", HTTP_GET, handleRoot);

  // Register the handler for the protected settings path
  server.on("/settings", HTTP_GET, handleSettings);

  server.begin();
  Serial.println("HTTP server started.");
  Serial.print("Protected path /settings (User: ");
  Serial.print(auth_user);
  Serial.print(", Pass SHA1: ");
  Serial.print(auth_pass_sha1);
  Serial.println(")");
  Serial.println("Note: The actual password is not stored, only its hash.");
}

void loop() {
  server.handleClient();
}

Example 2 SHA1 password hash Utility

This code demonstrates how to create a simple utility on your ESP32 to generate SHA1 password hashes. This is particularly useful when setting up SHA1-based authentication, as it allows you to generate the hash values needed for methods like authenticateBasicSHA1().

The utility connects to your Wi-Fi network and hosts a web server where you can input a plain text password. When submitted, the server processes the input using the calculateSHA1() function to generate the corresponding SHA1 hash. The hash is then displayed on the webpage, ready to be copied and used in your projects.

To test the generated hash, the code includes an example route at /test. This route uses a predefined username (“avantmaker”) and SHA1 hash of the password “testpassword”. If the correct credentials are provided, the user is authenticated successfully, demonstrating how authenticateBasicSHA1() works in practice.

Users can access the main page at the root URL (/) to generate new hashes or return from the test page. This tool is ideal for users on AvantMaker.com who need a straightforward way to generate SHA1 password hashes for their applications.

/*
 * Author: Avant Maker
 * Date: April 12, 2025
 * Version: 1.0
 * License: MIT 
 * 
 * Description: 
 * This example demonstrates how to create a simple utility
 * on your ESP32 to generate SHA1 password hashes. This is
 * useful when setting up SHA1-based authentication as it
 * allows you to generate the hash values you'll need to
 * include in your code.
 *
 * Code Source:
 * This example code is sourced from the Comprehensive Guide
 * to the ESP32 Arduino Core Library, accessible on AvantMaker.com.
 * For additional code examples and in-depth documentation related to
 * the ESP32 Arduino Core Library, please visit:
 *
 * https://avantmaker.com/home/all-about-esp32-arduino-core-library/
 *
 * AvantMaker.com, your premier destination for all things
 * DIY, AI, IoT, Smart Home, and STEM projects. We are dedicated
 * to empowering makers, learners, and enthusiasts with
 * the resources they need to bring their innovative ideas to life.
 */

#include <WiFi.h>
#include <WebServer.h>
#include <mbedtls/sha1.h>

const char* ssid = "your_SSID";          // Replace with your Wi-Fi SSID
const char* password = "your_PASSWORD";  // Replace with your Wi-Fi password

WebServer server(80);

void setup() {
  Serial.begin(115200);
  
  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
  Serial.println("Connected to WiFi");
  Serial.print("IP Address: ");
  Serial.println(WiFi.localIP());
  
  // Route for root / web page with form
  server.on("/", HTTP_GET, []() {
    server.send(200, "text/html", 
      "<!DOCTYPE html><html>"
      "<head><title>SHA1 Password Generator</title></head>"
      "<body>"
      "<h1>SHA1 Password Generator</h1>"
      "<p>Use this tool to generate SHA1 hashes for use with authenticateBasicSHA1()</p>"
      "<form action='/generate' method='post'>"
      "  <label for='password'>Password to hash:</label><br>"
      "  <input type='text' id='password' name='password'><br><br>"
      "  <input type='submit' value='Generate SHA1 Hash'>"
      "</form>"
      "</body></html>");
  });
  
  // Route to handle form submission
  server.on("/generate", HTTP_POST, []() {
    String password = server.arg("password");
    String sha1Hash = "";
    
    if (password.length() > 0) {
      sha1Hash = calculateSHA1(password);
    }
    
    server.send(200, "text/html", 
      "<!DOCTYPE html><html>"
      "<head><title>SHA1 Hash Result</title></head>"
      "<body>"
      "<h1>SHA1 Hash Result</h1>"
      "<p><strong>Original Password:</strong> " + password + "</p>"
      "<p><strong>SHA1 Hash:</strong> " + sha1Hash + "</p>"
      "<p>To use this hash in your code:</p>"
      "<pre>const char* password_sha1 = \"" + sha1Hash + "\";</pre>"
      "<p><a href='/'>Generate Another Hash</a></p>"
      "</body></html>");
  });
  
  // Route to demonstrate authentication using a SHA1 hash
  server.on("/test", HTTP_GET, []() {
    // SHA1 hash of "testpassword" is "9140cd2c988ac10e754457276d5c0b24c6b9a8ad"
    const char* test_username = "avantmaker";
    const char* test_password_sha1 = "9140cd2c988ac10e754457276d5c0b24c6b9a8ad";
    
    if (!server.authenticateBasicSHA1(test_username, test_password_sha1)) {
      server.requestAuthentication();
      return;
    }
    
    server.send(200, "text/html", 
      "<!DOCTYPE html><html>"
      "<head><title>Authentication Test</title></head>"
      "<body>"
      "<h1>Authentication Successful!</h1>"
      "<p>You have successfully authenticated with SHA1 hashed password.</p>"
      "<p>Username: avantmaker</p>"
      "<p>Password: testpassword</p>"
      "<p><a href='/'>Return to Generator</a></p>"
      "</body></html>");
  });
  
  server.begin();
}

void loop() {
  server.handleClient();
}

// Function to calculate SHA1 hash of a string
String calculateSHA1(String text) {
  uint8_t hash[20];
  char hexstring[41];
  
  mbedtls_sha1_context ctx;
  mbedtls_sha1_init(&ctx);
  mbedtls_sha1_starts(&ctx);
  mbedtls_sha1_update(&ctx, (const unsigned char*)text.c_str(), text.length());
  mbedtls_sha1_finish(&ctx, hash);
  mbedtls_sha1_free(&ctx);
  
  for(int i = 0; i < 20; i++) {
    sprintf(&hexstring[i*2], "%02x", hash[i]);
  }
  hexstring[40] = 0;
  
  return String(hexstring);
}

Example 3 Multiple Users with SHA1 Hashed Passwords

This code demonstrates the use of the authenticateBasicSHA1() method from the ESP32 WebServer Library. This method is used to authenticate users by verifying their credentials against precomputed SHA1 password hashes, making it suitable for secure authentication in web-based applications.

The example defines multiple users with different access levels (basic and admin) and their corresponding SHA1 hashed passwords. When accessing specific routes like /user or /admin, the server iterates through the list of valid users and uses authenticateBasicSHA1() to verify the provided credentials. Based on the user’s access level, they are granted access to either the user area, admin area, or denied access entirely.

This implementation showcases how to restrict access to different parts of a web application based on user roles. For instance, only admin users can access the /admin route, while both basic and admin users can access the /user route. If authentication fails or the user lacks sufficient privileges, appropriate responses are sent back to the client.

This example is particularly useful for developers looking to implement role-based access control using the ESP32 WebServer Library’s authenticateBasicSHA1() method, ensuring secure and efficient user authentication.

If you need a tool to generate your own SHA1 password hash, you can use Example 2 code on this page. This code demonstrates how to create a simple utility on your ESP32 for generating SHA1 password hashes.

/*
 * Author: Avant Maker
 * Date: April 12, 2025
 * Version: 1.0
 * License: MIT 
 * 
 * Description: 
 * This example demonstrates how to use ESP32 WebServer Library's 
 * authenticateBasicSHA1() method to implement a multi-user
 * authentication system with different access levels,
 * using SHA1 hashed passwords for better security.
 *
 * Code Source:
 * This example code is sourced from the Comprehensive Guide
 * to the ESP32 Arduino Core Library, accessible on AvantMaker.com.
 * For additional code examples and in-depth documentation related to
 * the ESP32 Arduino Core Library, please visit:
 *
 * https://avantmaker.com/home/all-about-esp32-arduino-core-library/
 *
 * AvantMaker.com, your premier destination for all things
 * DIY, AI, IoT, Smart Home, and STEM projects. We are dedicated
 * to empowering makers, learners, and enthusiasts with
 * the resources they need to bring their innovative ideas to life.
 */

#include <WiFi.h>
#include <WebServer.h>

const char* ssid = "your_SSID";          // Replace with your Wi-Fi SSID
const char* password = "your_PASSWORD";  // Replace with your Wi-Fi password

// Define multiple users with SHA1 hashed passwords
struct User {
  const char* username;
  const char* passwordSha1;
  int accessLevel; // 1=basic, 2=admin
};

// Array of valid users with SHA1 hashed passwords
// SHA1 hashes:
// - "userpass" -> "45f106ef4d5161e7aa38cf6c666607f25748b6ca"
// - "adminpass" -> "74913f5cd5f61ec0bcfdb775414c2fb3d161b620"
// - "guestpass" -> "76e1f98366934e087adb4ea26a45ca208e6ab340"
User validUsers[] = {
  {"user1", "45f106ef4d5161e7aa38cf6c666607f25748b6ca", 1},
  {"admin", "74913f5cd5f61ec0bcfdb775414c2fb3d161b620", 2},
  {"guest", "76e1f98366934e087adb4ea26a45ca208e6ab340", 1}
};

WebServer server(80);

void setup() {
  Serial.begin(115200);
  
  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
  Serial.println("Connected to WiFi");
  Serial.print("IP Address: ");
  Serial.println(WiFi.localIP());
  
  // Route for root / web page
  server.on("/", HTTP_GET, []() {
    server.send(200, "text/html", 
      "<!DOCTYPE html><html>"
      "<head><title>AvantMaker Multi-User SHA1 Auth Demo</title></head>"
      "<body>"
      "<h1>AvantMaker Multi-User SHA1 Authentication Demo</h1>"
      "<p><a href='/user'>User Area</a> (Level 1 or 2 required)</p>"
      "<p><a href='/admin'>Admin Area</a> (Level 2 required)</p>"
      "</body></html>");
  });
  
  // Route for user area
  server.on("/user", HTTP_GET, []() {
    // Try to authenticate against each valid user
    int accessLevel = 0;
    String username = "";
    
    int numUsers = sizeof(validUsers) / sizeof(validUsers[0]);
    for (int i = 0; i < numUsers; i++) {
      if (server.authenticateBasicSHA1(validUsers[i].username, validUsers[i].passwordSha1)) {
        accessLevel = validUsers[i].accessLevel;
        username = String(validUsers[i].username);
        break;
      }
    }
    
    if (accessLevel >= 1) {
      // User has at least level 1 access
      server.send(200, "text/html", 
        "<!DOCTYPE html><html>"
        "<head><title>User Area</title></head>"
        "<body>"
        "<h1>User Area</h1>"
        "<p>Welcome, " + username + "!</p>"
        "<p>Your access level: " + String(accessLevel) + "</p>"
        "<p><a href='/'>Return to Home</a></p>"
        "</body></html>");
    } else {
      // Invalid credentials
      server.requestAuthentication();
    }
  });
  
  // Route for admin area
  server.on("/admin", HTTP_GET, []() {
    // Try to authenticate against each valid user
    int accessLevel = 0;
    String username = "";
    
    int numUsers = sizeof(validUsers) / sizeof(validUsers[0]);
    for (int i = 0; i < numUsers; i++) {
      if (server.authenticateBasicSHA1(validUsers[i].username, validUsers[i].passwordSha1)) {
        accessLevel = validUsers[i].accessLevel;
        username = String(validUsers[i].username);
        break;
      }
    }
    
    if (accessLevel >= 2) {
      // User has admin access
      server.send(200, "text/html", 
        "<!DOCTYPE html><html>"
        "<head><title>Admin Area</title></head>"
        "<body>"
        "<h1>Admin Area</h1>"
        "<p>Welcome, Administrator " + username + "!</p>"
        "<p>This area is restricted to admin users only.</p>"
        "<p><a href='/'>Return to Home</a></p>"
        "</body></html>");
    } else if (accessLevel == 1) {
      // Insufficient privileges
      server.send(403, "text/html", 
        "<!DOCTYPE html><html>"
        "<head><title>Access Denied</title></head>"
        "<body>"
        "<h1>Access Denied</h1>"
        "<p>You need admin privileges to access this area.</p>"
        "<p><a href='/'>Return to Home</a></p>"
        "</body></html>");
    } else {
      // Not authenticated
      server.requestAuthentication();
    }
  });
  
  server.begin();
}

void loop() {
  server.handleClient();
}
error: Content is protected !!