diff --git a/examples/cookie_authentication/Makefile b/examples/cookie_authentication/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..018c18adeb8d0eebce1b0242507f22c65f57c048
--- /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 0000000000000000000000000000000000000000..19bcea06d3522585fb370a31086ac4493ffee972
--- /dev/null
+++ b/examples/cookie_authentication/cookie_auth.c
@@ -0,0 +1,93 @@
+// Copyright (c) 2014 Cesanta Software
+// All rights reserved
+
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#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 0000000000000000000000000000000000000000..fc992fd03de9d1e0f174f1a7b667780686e7f7fc
--- /dev/null
+++ b/examples/cookie_authentication/index.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="utf-8" />
+  <title>WebSocket Test</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1" />
+  <style type="text/css">
+    body {
+      background-color: #cde; margin: 0;
+      padding: 0; font: 14px Helvetica, Arial, sans-serif;
+    }
+    * { outline: none; }
+    div.content {
+      width: 800px; margin: 2em auto; padding: 20px 50px;
+      background-color: #fff; border-radius: 1em;
+    }
+    label { display: inline-block; min-width: 7em; }
+    input { border: 1px solid #ccc; padding: 0.4em; margin: 0 0 10px 0; }
+    a:link, a:visited { color: #69c; text-decoration: none; }
+    @media (max-width: 700px) {
+      body { background-color: #fff; }
+      div.content {
+        width: auto; margin: 0 auto; border-radius: 0; padding: 1em;
+      }
+    }
+</style>
+
+<body>
+  <div class="content">
+    <h1>Mongoose Cookie Base Authentication</h1>
+    <p>This is an index page. Authentication succeeded.</p>
+</body>
+</html>
\ 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 0000000000000000000000000000000000000000..d3ff70565734fb80b2e565128e9a0622cf2ec8a1
--- /dev/null
+++ b/examples/cookie_authentication/login.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="utf-8" />
+  <title>WebSocket Test</title>
+  <meta name="viewport" content="width=device-width, initial-scale=1" />
+  <style type="text/css">
+    body {
+      background-color: #cde; margin: 0;
+      padding: 0; font: 14px Helvetica, Arial, sans-serif;
+    }
+    * { outline: none; }
+    div.content {
+      width: 800px; margin: 2em auto; padding: 20px 50px;
+      background-color: #fff; border-radius: 1em;
+    }
+    label { display: inline-block; min-width: 7em; }
+    input { border: 1px solid #ccc; padding: 0.4em; margin: 0 0 10px 0; }
+    a:link, a:visited { color: #69c; text-decoration: none; }
+    @media (max-width: 700px) {
+      body { background-color: #fff; }
+      div.content {
+        width: auto; margin: 0 auto; border-radius: 0; padding: 1em;
+      }
+    }
+</style>
+
+<body>
+  <div class="content">
+    <h1>Mongoose Cookie Based Authentication</h1>
+    <p>Use name "Joe", password "Doe" to login.</p>
+    <form method="POST">
+      <div>
+        <label>Name:</label>
+        <input type="text" name="name"/>
+      </div><div>
+        <label>Password:</label>
+        <input type="password" name="password"/>
+      </div><div>
+        <input type="submit" value="Login"/>
+      </div>
+    </form>
+</body>
+</html>
\ No newline at end of file