From 507735058992486ab38262f1968ee354bc0fca81 Mon Sep 17 00:00:00 2001 From: Sergey Lyubka Date: Thu, 9 Oct 2014 11:29:39 +0100 Subject: [PATCH] Added cookie based auth example --- examples/cookie_authentication/Makefile | 12 +++ examples/cookie_authentication/cookie_auth.c | 93 ++++++++++++++++++++ examples/cookie_authentication/index.html | 33 +++++++ examples/cookie_authentication/login.html | 44 +++++++++ 4 files changed, 182 insertions(+) create mode 100644 examples/cookie_authentication/Makefile create mode 100644 examples/cookie_authentication/cookie_auth.c create mode 100644 examples/cookie_authentication/index.html create mode 100644 examples/cookie_authentication/login.html diff --git a/examples/cookie_authentication/Makefile b/examples/cookie_authentication/Makefile new file mode 100644 index 00000000..018c18ad --- /dev/null +++ b/examples/cookie_authentication/Makefile @@ -0,0 +1,12 @@ +# Copyright (c) 2014 Cesanta Software +# All rights reserved + +PROG = cookie_auth +CFLAGS = -W -Wall -I../.. -g -O0 $(CFLAGS_EXTRA) +SOURCES = $(PROG).c ../../mongoose.c + +$(PROG): $(SOURCES) + $(CC) -o $(PROG) $(SOURCES) $(CFLAGS) + +clean: + rm -rf $(PROG) *.exe *.dSYM *.obj *.exp .*o *.lib diff --git a/examples/cookie_authentication/cookie_auth.c b/examples/cookie_authentication/cookie_auth.c new file mode 100644 index 00000000..19bcea06 --- /dev/null +++ b/examples/cookie_authentication/cookie_auth.c @@ -0,0 +1,93 @@ +// Copyright (c) 2014 Cesanta Software +// All rights reserved + +#include +#include +#include +#include "mongoose.h" + +static const char *s_login_uri = "/login.html"; +static const char *s_secret = ":-)"; // Must be known only to server + +static void generate_ssid(const char *user_name, const char *expiration_date, + char *ssid, size_t ssid_size) { + char hash[33]; + mg_md5(hash, user_name, ":", expiration_date, ":", s_secret, NULL); + snprintf(ssid, ssid_size, "%s|%s|%s", user_name, expiration_date, hash); +} + +static int check_auth(struct mg_connection *conn) { + char ssid[100], calculated_ssid[100], name[100], expire[100]; + + // Always authenticate requests to login page + if (strcmp(conn->uri, s_login_uri) == 0) { + return MG_TRUE; + } + + // Look for session ID in the Cookie. + // That session ID can be validated against the database that stores + // current active sessions. + mg_parse_header(mg_get_header(conn, "Cookie"), "ssid", ssid, sizeof(ssid)); + if (sscanf(ssid, "%[^|]|%[^|]|", name, expire) == 2) { + generate_ssid(name, expire, calculated_ssid, sizeof(calculated_ssid)); + if (strcmp(ssid, calculated_ssid) == 0) { + return MG_TRUE; // Authenticate + } + } + + // Auth failed, do NOT authenticate, redirect to login page + mg_printf(conn, "HTTP/1.1 302 Moved\r\nLocation: %s\r\n\r\n", s_login_uri); + return MG_FALSE; +} + +static int serve_request(struct mg_connection *conn) { + char name[100], password[100], ssid[100], expire[100], expire_epoch[100]; + + // Always authorize requests to login page + if (strcmp(conn->uri, s_login_uri) == 0 && + strcmp(conn->request_method, "POST") == 0) { + mg_get_var(conn, "name", name, sizeof(name)); + mg_get_var(conn, "password", password, sizeof(password)); + + // A real authentication mechanism should be employed here. + // Also, the whole site should be served through HTTPS. + if (strcmp(name, "Joe") == 0 && strcmp(password, "Doe") == 0) { + // Generate expiry date + time_t t = time(NULL) + 3600; // Valid for 1 hour + snprintf(expire_epoch, sizeof(expire_epoch), "%lu", (unsigned long) t); + strftime(expire, sizeof(expire), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&t)); + generate_ssid(name, expire_epoch, ssid, sizeof(ssid)); + // Set "session id" cookie, there could be some data encoded in it. + mg_printf(conn, + "HTTP/1.1 302 Moved\r\n" + "Set-Cookie: ssid=%s; expire=\"%s\"; http-only; HttpOnly;\r\n" + "Location: /\r\n\r\n", + ssid, expire); + return MG_TRUE; + } + } + + return MG_FALSE; +} + +static int ev_handler(struct mg_connection *conn, enum mg_event ev) { + switch (ev) { + case MG_AUTH: return check_auth(conn); + case MG_REQUEST: return serve_request(conn); + default: return MG_FALSE; + } +} + +int main(void) { + struct mg_server *server = mg_create_server(NULL, ev_handler); + mg_set_option(server, "listening_port", "8080"); + mg_set_option(server, "document_root", "."); + + printf("Starting on port %s\n", mg_get_option(server, "listening_port")); + for (;;) { + mg_poll_server(server, 1000); + } + mg_destroy_server(&server); + + return 0; +} diff --git a/examples/cookie_authentication/index.html b/examples/cookie_authentication/index.html new file mode 100644 index 00000000..fc992fd0 --- /dev/null +++ b/examples/cookie_authentication/index.html @@ -0,0 +1,33 @@ + + + + + WebSocket Test + + + + +
+

Mongoose Cookie Base Authentication

+

This is an index page. Authentication succeeded.

+ + \ No newline at end of file diff --git a/examples/cookie_authentication/login.html b/examples/cookie_authentication/login.html new file mode 100644 index 00000000..d3ff7056 --- /dev/null +++ b/examples/cookie_authentication/login.html @@ -0,0 +1,44 @@ + + + + + WebSocket Test + + + + +
+

Mongoose Cookie Based Authentication

+

Use name "Joe", password "Doe" to login.

+
+
+ + +
+ + +
+ +
+
+ + \ No newline at end of file