Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds digest authentication example. #4112

Merged
merged 15 commits into from
Jan 10, 2018
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*

This example is released into public domain,
or, at your option, CC0 licensed.
*/

#include <ESP8266WiFi.h>

#include <ESP8266HTTPClient.h>

const char* ssid = "........";
const char* ssidPassword = "........";

const char *username = "admin";
const char *password = "admin";

const char *server = "http://httpbin.org";
const char *uri = "/digest-auth/auth/admin/admin/MD5";

String exractParam(String& authReq, const String& param, const char delimit){
int _begin = authReq.indexOf(param);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please load this sketch into Arduino IDE and use Tools > Auto Format feature to fix the indentation.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, it is not a common practice to prefix function and field names with an underscore, when not implementing class members, at least in Arduino.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment about reformatting the sketch using Arduino IDE is still valid, by the way. Arduino sketches use 2 spaces for indentation, this file uses tabs.

if (_begin==-1) return "";
return authReq.substring(_begin+param.length(),authReq.indexOf(delimit,_begin+param.length()));
}

void setup() {
Serial.begin(9600);

WiFi.mode(WIFI_STA);
WiFi.begin(ssid, ssidPassword);

while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}

Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}

void loop() {
HTTPClient http;

Serial.print("[HTTP] begin...\n");

// configure traged server and url
http.begin(String(server) + String(uri));


const char *keys[] = {"WWW-Authenticate"};
http.collectHeaders(keys, 1);

Serial.print("[HTTP] GET...\n");
// start connection and send HTTP header
int httpCode = http.GET();

if (httpCode > 0) {
String authReq = http.header("WWW-Authenticate");
Serial.println(authReq);

// extracting required parameters for RFC 2069 simpler Digest
String _realm = exractParam(authReq, "realm=\"", '"');
String _nonce = exractParam(authReq, "nonce=\"", '"');
String _opaque = exractParam(authReq, "opaque=\"", '"');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned previously, it is not a common practice in Arduino sketches to start local variable names with underscores.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I am sorry about them.


// parameters for the RFC 2617 newer Digest
MD5Builder md5;
md5.begin();
md5.add(String(username) + ":" + _realm + ":" + String(password)); // md5 of the user:realm:user
md5.calculate();
String _H1 = md5.toString();

md5.begin();
md5.add(String("GET:") + String(uri));
md5.calculate();
String _H2 = md5.toString();

md5.begin();
md5.add(_H1 + ":" + _nonce + ":" + "00000001" + ":" + "gDBuFY4s" + ":" + "auth" + ":" + _H2);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still some hard-coded strings here.
Nonce gDBuFY4s should be randomly generated.
And as far as i understand the RFC, 00000001 should be incremented on each request, which is not the case here.

md5.calculate();
String _response = md5.toString();

http.end();
http.begin(String(server) + String(uri));

String authorization = "Digest username=\"admin\", realm=\"" + _realm + "\", nonce=\"" + _nonce + "\", uri=\"" + uri + "\", algorithm=\"MD5\", qop=auth, nc=00000001, cnonce=\"gDBuFY4s\", response=\"" + _response + "\"";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's move the part starting from // extracting required parameters for RFC 2069 simpler Diges to calculation of authorization into a separate function, e.g. getDigestAuth.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please break this line, Arduino IDE window is just ~60 characters wide, most of the line will not be readable.

Serial.println(authorization);
http.addHeader("Authorization", authorization);

int httpCode = http.GET();
if (httpCode > 0) {
String payload = http.getString();
Serial.println(payload);
} else {
Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
}
} else {
Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
}

http.end();
delay(10000);
}