HTTP Authentication for Arduino Server

Hi, I’m quite new to all this and finished setting up a server on a mega 2560 using the w5100 ethernet shield. I used this tutorial to do it.

http://startingelectronics.org/tutorials/arduino/ethernet-shield-web-server-tutorial/

I have one html page, using AJAX and XML. The page works great and I’m happy with it so next I thought I better add authentication. Don’t need the most secure, HTTP is fine. Unfortunately the tutorial I used didn’t include such a feature.

I must have put as much time into the auth as I have the whole ethernet. Of course it has to be acting oddly and I don’t know what to try next.

Here’s a sketch I put together with no authentication. It works great.

#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

#define REQ_BUF_SZ   60
EthernetServer server(80);
File webFile;               // the web page file on the SD card
char HTTP_req[REQ_BUF_SZ] = {0}; // buffered HTTP request stored as null terminated string
char req_index = 0;              // index into HTTP_req buffer

void setup() {
  Serial.begin(9600);   
  
  // disable Ethernet chip
  pinMode(10, OUTPUT);
  digitalWrite(10, HIGH);
  
  // initialize SD card
  Serial.println("Initializing SD card...");
  if (!SD.begin(4)) {
      Serial.println("ERROR - SD card initialization failed!");
//      return;    // init failed
  }
  Serial.println("SUCCESS - SD card initialized.");
  // check for index.htm file
  if (!SD.exists("index.htm")) {
      Serial.println("ERROR - Can't find index.htm file!");
//      return;  // can't find index file
  }
  Serial.println("SUCCESS - Found index.htm file.");
  
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    // no point in carrying on, so do nothing forevermore:
    for(;;)
      ;
  }  
  
//  Ethernet.begin(mac, ip);
  server.begin();
  //delay(10000); // <--- add this, wait for the shield to connect
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
  
}

void loop() {
    

    EthernetClient client = server.available();  // try to get client

    if (client) {  // got client?
        boolean currentLineIsBlank = true;
        while (client.connected()) {
            if (client.available()) {   // client data available to read
                char c = client.read(); // read 1 byte (character) from client
                Serial.write(c);
                // limit the size of the stored received HTTP request
                // buffer first part of HTTP request in HTTP_req array (string)
                // leave last element in array as 0 to null terminate string (REQ_BUF_SZ - 1)
                if (req_index < (REQ_BUF_SZ - 1)) {
                    HTTP_req[req_index] = c;          // save HTTP request character
                    req_index++;
                }
                // last line of client request is blank and ends with \n
                // respond to client only after last line received
                if (c == '\n' && currentLineIsBlank) {
                    // send a standard http response header
           //         client.println("HTTP/1.1 200 OK");
                    // remainder of header follows below, depending on if
                    // web page or XML page is requested
                    // Ajax request - send XML file
                    client.println("HTTP/1.1 200 OK");
                    renderFile(client);
                    // display received HTTP request on serial port
                    Serial.print(HTTP_req);
                    // reset buffer index and all buffer elements to 0
                    req_index = 0;
                    StrClear(HTTP_req, REQ_BUF_SZ);
                    break;
                }
                // every line of text received from the client ends with \r\n
                if (c == '\n') {
                    // last character on line of received text
                    // starting new line with next character read
                    currentLineIsBlank = true;
                } 
                else if (c != '\r') {
                    // a text character was received from client
                    currentLineIsBlank = false;
                }
            } // end if (client.available())
        } // end while (client.connected())
        delay(1);      // give the web browser time to receive the data
        client.stop(); // close the connection
    } // end if (client)
  
  

}


void renderFile(EthernetClient client) {
    
    Serial.println("HELLO");
    if  (StrContains(HTTP_req, "GET / ")
              || StrContains(HTTP_req, "GET /index.htm")) {  // web page request
        
    Serial.println("HELLO2");
        // send web page
        webFile = SD.open("index.htm");        // open web page file
        if (webFile) {
            // send rest of HTTP header
            client.println("Content-Type: text/html");
            client.println("Connection: keep-alive");
            client.println();
        }
    }
    if (webFile) {
        while(webFile.available()) {
            client.write(webFile.read()); // send web page to client
        }
        webFile.close();
    }
}

// sets every element of str to 0 (clears array)
void StrClear(char *str, char length)
{
    for (int i = 0; i < length; i++) {
        str[i] = 0;
    }
}

// searches for the string sfind in the string str
// returns 1 if string found
// returns 0 if string not found
char StrContains(char *str, char *sfind)
{
    char found = 0;
    char index = 0;
    char len;

    len = strlen(str);
    
    if (strlen(sfind) > len) {
        return 0;
    }
    while (index < len) {
        if (str[index] == sfind[found]) {
            found++;
            if (strlen(sfind) == found) {
                return 1;
            }
        }
        else {
            found = 0;
        }
        index++;
    }

    return 0;
}

Notice in the renderFile function the 2 HELLO serial prints. Of course when I load the page I see both of those in the serial window.

However once I wrap authentication code where the renderFile fuction is called I only get the first HELLO serial print.

The auth code works good on my main sketch however when auth passes it never makes it into the HELLO2 statement like it does with no auth code. It simply loads a white screen.

This is the code I’m using for authentication. This works good but when it calls renderFile those statements won’t run.

                if(strstr(HTTP_req, "bWluaDp0ZXN0") != NULL)
                {
                    // send a standard http response header
                    client.println("HTTP/1.1 200 OK");
                    renderFile(client);
                    
                } 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>Unauthorized!</html>");
                }

In my main sketch when I add the auth code I have to change the following otherwise it won’t work. And oddly if I remove the auth code and use the complete sketch I posted above this has to be 60, if its 300 it won’t load.
#define REQ_BUF_SZ  60to

#define REQ_BUF_SZ   300

If anyone can help I would really appreciate it.