Skip to content

Commit e7eb739

Browse files
authored
Merge pull request #16 from tomer-w/master
Add basic authorization support.
2 parents f0f2beb + f9cc232 commit e7eb739

File tree

7 files changed

+96
-3
lines changed

7 files changed

+96
-3
lines changed

examples/HelloHttp/HelloHttp.ino

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ void loop()
7272

7373
httpReply.send( errorStr );
7474
}
75+
client.stop();
7576
}
7677

7778
}

library.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ category=Communication
88
url=https://github.com/QuickSander/ArduinoHttpServer
99
architectures=*
1010
repository=https://github.com/QuickSander/ArduinoHttpServer.git
11+
depends=Base64

src/internals/HttpField.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const char* ArduinoHttpServer::HttpField::SEPERATOR = ": ";
1414
const char* ArduinoHttpServer::HttpField::CONTENT_TYPE_STR = "Content-Type";
1515
const char* ArduinoHttpServer::HttpField::CONTENT_LENGTH_TYPE_STR = "Content-Length";
1616
const char* ArduinoHttpServer::HttpField::USER_AGENT_TYPE_STR = "User-Agent";
17+
const char* ArduinoHttpServer::HttpField::AUTHORIZATION_TYPE_STR = "Authorization";
1718

1819

1920
ArduinoHttpServer::HttpField::HttpField(const char* fieldLine) :
@@ -66,6 +67,10 @@ void ArduinoHttpServer::HttpField::determineType(const String& typeStr)
6667
{
6768
m_type = Type::USER_AGENT;
6869
}
70+
else if (typeStr.equalsIgnoreCase(AUTHORIZATION_TYPE_STR))
71+
{
72+
m_type = Type::AUTHORIZATION;
73+
}
6974
}
7075

7176

src/internals/HttpField.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ class HttpField
2626
NOT_SUPPORTED,
2727
CONTENT_TYPE,
2828
CONTENT_LENGTH,
29-
USER_AGENT
29+
USER_AGENT,
30+
AUTHORIZATION
3031
};
3132

3233
HttpField(const char* fieldLine);
@@ -49,6 +50,7 @@ class HttpField
4950
static const char* CONTENT_TYPE_STR;
5051
static const char* CONTENT_LENGTH_TYPE_STR;
5152
static const char* USER_AGENT_TYPE_STR;
53+
static const char* AUTHORIZATION_TYPE_STR;
5254

5355
Type m_type;
5456
String m_value;

src/internals/StreamHttpReply.cpp

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,11 @@ void ArduinoHttpServer::AbstractStreamHttpReply::send(const String& data, const
3232
httpErrorReply += title + "\r\n";
3333
httpErrorReply += AHS_F("Connection: close\r\n");
3434
httpErrorReply += AHS_F("Content-Length: ");
35-
httpErrorReply += data.length(); httpErrorReply += AHS_F("\r\n");
36-
httpErrorReply += AHS_F("Content-Type: "); httpErrorReply += m_contentType; httpErrorReply+= AHS_F("\r\n");
35+
httpErrorReply += data.length();
36+
httpErrorReply += AHS_F("\r\n");
37+
httpErrorReply += AHS_F("Content-Type: ");
38+
httpErrorReply += m_contentType;
39+
httpErrorReply += AHS_F("\r\n");
3740
httpErrorReply += AHS_F("\r\n");
3841
httpErrorReply += data;
3942
httpErrorReply += AHS_F("\r\n");
@@ -132,3 +135,29 @@ String ArduinoHttpServer::StreamHttpErrorReply::getJsonBody(const String& data)
132135

133136
return body;
134137
}
138+
139+
//------------------------------------------------------------------------------
140+
// Class Definition
141+
//------------------------------------------------------------------------------
142+
143+
ArduinoHttpServer::StreamHttpAuthenticateReply::StreamHttpAuthenticateReply(Stream& stream, const String& contentType) :
144+
AbstractStreamHttpReply(stream, contentType, "401")
145+
{
146+
147+
}
148+
149+
void ArduinoHttpServer::StreamHttpAuthenticateReply::send()
150+
{
151+
// Read away remaining bytes.
152+
while(getStream().read()>=0);
153+
154+
DEBUG_ARDUINO_HTTP_SERVER_PRINT("Printing Reply ... ");
155+
getStream().println(AHS_F("HTTP/1.1 401 Unauthorized"));
156+
getStream().println(AHS_F("WWW-Authenticate: Basic realm=\"Login Required\""));
157+
getStream().println(AHS_F("Connection: close"));
158+
getStream().println(AHS_F(""));
159+
getStream().println(AHS_F("<HTML><HEAD><TITLE>401 Unauthorized</TITLE></HEAD><BODY BGCOLOR=\"#cc9999\"><H4>401 Unauthorized</H4>Authorization required.</BODY></HTML>"));
160+
getStream().println(AHS_F(""));
161+
getStream().println(AHS_F(""));
162+
DEBUG_ARDUINO_HTTP_SERVER_PRINTLN("done.");
163+
}

src/internals/StreamHttpReply.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,18 @@ class StreamHttpErrorReply: public AbstractStreamHttpReply
5959
virtual String getJsonBody(const String& data);
6060
};
6161

62+
//------------------------------------------------------------------------------
63+
// Class Declaration
64+
//------------------------------------------------------------------------------
65+
//! Authenticate reply
66+
class StreamHttpAuthenticateReply: public AbstractStreamHttpReply
67+
{
68+
public:
69+
StreamHttpAuthenticateReply(Stream& stream, const String& contentType);
70+
virtual void send();
71+
};
72+
73+
6274
//------------------------------------------------------------------------------
6375
// Class Declaration
6476
//------------------------------------------------------------------------------

src/internals/StreamHttpRequest.hpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "ArduinoHttpServerDebug.h"
1818

1919
#include <Arduino.h>
20+
#include <Base64.h>
2021

2122
#include <string.h>
2223

@@ -64,6 +65,9 @@ class StreamHttpRequest
6465
const ErrorString getError() const;
6566
Stream& getStream() { return m_stream; };
6667

68+
// Check if authenticated request
69+
bool authenticate(const char * username, const char * password) const;
70+
6771
private:
6872

6973
enum class Error: char {
@@ -100,6 +104,7 @@ class StreamHttpRequest
100104
ArduinoHttpServer::HttpVersion m_version;
101105
ArduinoHttpServer::HttpField m_contentTypeField;
102106
ArduinoHttpServer::HttpField m_contentLengthField;
107+
ArduinoHttpServer::HttpField m_authorizationField;
103108

104109
Error m_error;
105110
ErrorMessageString m_errorDetail;
@@ -321,6 +326,10 @@ void ArduinoHttpServer::StreamHttpRequest<MAX_BODY_SIZE>::parseField(char lineBu
321326
{
322327
m_contentLengthField = httpField;
323328
}
329+
else if(httpField.getType() == ArduinoHttpServer::HttpField::Type::AUTHORIZATION)
330+
{
331+
m_authorizationField = httpField;
332+
}
324333
else
325334
{
326335
// Ignore other fields for now.
@@ -370,6 +379,40 @@ const ArduinoHttpServer::ErrorString ArduinoHttpServer::StreamHttpRequest<MAX_BO
370379
return errorString;
371380
}
372381

382+
template <size_t MAX_BODY_SIZE>
383+
bool ArduinoHttpServer::StreamHttpRequest<MAX_BODY_SIZE>::authenticate(const char * username, const char * password) const
384+
{
385+
if (m_authorizationField.getType() == HttpField::Type::NOT_SUPPORTED)
386+
{
387+
return false;
388+
}
389+
390+
if (!m_authorizationField.getValueAsString().startsWith("Basic"))
391+
{
392+
DEBUG_ARDUINO_HTTP_SERVER_PRINTLN("Unsupported auth header");
393+
return false;
394+
}
395+
396+
String combinedInput;
397+
if (!combinedInput.reserve(strlen(username) + strlen(password) + 2))
398+
{
399+
DEBUG_ARDUINO_HTTP_SERVER_PRINTLN("Not enough memory");
400+
return false;
401+
}
402+
combinedInput += username;
403+
combinedInput += AHS_F(":");
404+
combinedInput += password;
405+
406+
int encodedLength = Base64.encodedLength(combinedInput.length());
407+
char encodedString[encodedLength];
408+
Base64.encode(encodedString, combinedInput.c_str(), combinedInput.length());
409+
410+
if (strcmp(m_authorizationField.getValueAsString().c_str()+6,encodedString) == 0)
411+
{
412+
return true;
413+
}
373414

415+
return false;
416+
}
374417

375418
#endif // __ArduinoHttpServer__StreamHttpRequest__

0 commit comments

Comments
 (0)