Cookies

Cookies are bits of information that web-based applications can store in the browser. Applications can set cookie values then retrieve and modify those values later.

Auto-Authentication

Cookies are commonly used to store authentication information so a user won't have to log in to a web-based application each time they want to use it. The first time the user logs in, the application sets a cookie. Subsequent times, the application finds the cookie and lets the user in automatically.

The http class provides the setCookie method for setting the value of a cookie.

#include <groundwork/http.h>
#include <groundwork/cgimodule.h>

MAIN {

        http    *h=new http(APISTRUCT);

        // send the content type
        h->contentType("text","html",NULL);

	... get the username and password ...

        // set some cookies
        h->setCookie("username",username,NULL,NULL,NULL,0);
        h->setCookie("password",password,NULL,NULL,NULL,0);
        h->setCookie("loggedin","yes",NULL,NULL,NULL,0);

        // terminate the header
        h->cr();

        ... send some data ...

        delete h;
}

The cgi class provides the method cookieEntry for reading the value of a cookie.

#include <groundwork/cgi.h>
#include <groundwork/cgimodule.h>

MAIN {

        cgi     *c=new cgi(APISTRUCT);

        // send an http header
        c->sendHeader();

        // get whether the user has already logged in or not
        char    *loggedin=c->cookieEntry("loggedin");

        ... do something with loggedin ...

        delete c;
}
Saving State

Cookies can also be used to give applications "memory". If the application stores stateful information in a set of cookies, when the user leaves and returns to the application, his previous state can be restored. This gives the user the impression that the application remembered where he was and what he was doing. For example, an application for reading books online might remember what book the user was reading and what page he was on.

#include <groundwork/http.h>
#include <groundwork/cgi.h>
#include <groundwork/cgimodule.h>

MAIN {

        http    *h=new http(APISTRUCT);
        cgi     *c=new cgi(APISTRUCT);

        // send the content type
        h->contentType("text","html",NULL);

        ... determine if the user is coming from the previous page or
            if he is returning to the application from somewhere else ...

        char    *bookname;
        char    *page;
        if (!comingfrompreviouspage) {
                // get bookname and page from cookie
                bookname=c->cookieEntry("book");
                page=c->cookieEntry("page");
        }

        // store the current book and page in cookies
        h->setCookie("book",bookname,NULL,NULL,NULL,0);
        h->setCookie("page",page,NULL,NULL,NULL,0);

        // terminate the header
        h->cr();

        ... display the page ...

        delete c;
        delete h;
}

More often than not an application needs to store lots of information to save its state. It would be cumbersome to manage that information using cookies alone so applications typically store the stateful information in a database along with a session id and store the session id in a cookie.

#include <groundwork/http.h>
#include <groundwork/cgimodule.h>

MAIN {

        http    *h=new http(APISTRUCT);

        // send the content type
        h->contentType("text","html",NULL);

	... store the session state to the database ...

	... get the session id ...

        // set the session id
        h->setCookie("sessionid",sessionid,NULL,NULL,NULL,0);

        // terminate the header
        h->cr();

        ... send some data ...

        delete h;
}
Persistent Cookies

By default, when a cookie is created, it will remain on the user's machine until he closes his browser. To make the cookie hang around longer than that, give it an expiration date.

#include <groundwork/http.h>
#include <groundwork/cgimodule.h>

MAIN {

        http    *h=new http(APISTRUCT);

        // send the content type
        h->contentType("text","html",NULL);

	... store the session state to the database ...

	... get the session id ...

        // set the session id
        h->setCookie("sessionid",sessionid,NULL,NULL,"Fri, 06 Nov 2020 08:49:37 GMT",0);

        // terminate the header
        h->cr();

        ... send some data ...

        delete h;
}

To make the browser get rid of a cookie, set the expiration date to a date that has already passed...

#include <groundwork/http.h>
#include <groundwork/cgimodule.h>

MAIN {

        http    *h=new http(APISTRUCT);

        // send the content type
        h->contentType("text","html",NULL);

        // set the session id
        h->setCookie("sessionid",NULL,NULL,NULL,"Thu, 06 Nov 1975 08:49:37 GMT",0);

        // terminate the header
        h->cr();

        delete h;
}
Cookie Security

Since cookies could contain sensitive information, there are facilities for ensuring that the information doesn't fall into the wrong hands. When setting a cookie, you can indicate what domain has permission to access the cookie. Setting a domain allows any application in that domain or in any of it's subdomains to access the cookie. A domain of myschool.edu would allow applications running from myschool.edu, math.myschool.edu, eng.myschool.edu, cs.myschool.edu, etc. to access the cookie. In order to set a domain, the application setting the cookie has to actually be in that domain. For example, an application running from myschool.edu could not set a domain of yourschool.edu.

#include <groundwork/http.h>
#include <groundwork/cgimodule.h>

MAIN {

        http    *h=new http(APISTRUCT);

        // send the content type
        h->contentType("text","html",NULL);

	... store the session state to the database ...

	... get the session id ...

        // set the session id
        h->setCookie("sessionid",sessionid,"myschool.edu",NULL,"Fri, 06 Nov 2020 08:49:37 GMT",0);

        // terminate the header
        h->cr();

        ... send some data ...

        delete h;
}

By default, when a cookie is set, only CGI's running from the same path as the CGI that set the cookie can access it. For example, if http://www.myschool.edu/library/books/contents.cgi sets a cookie then http://www.myschool.edu/library/books/page.cgi can access the cookie but http://www.myschool.edu/library/magazines/page.cgi cannot. You can use the path parameter to more liberally define what CGI's can access a cookie. For example, setting a path of /library would enable access to the cookie for all three CGI's listed above.

#include <groundwork/http.h>
#include <groundwork/cgimodule.h>

MAIN {

        http    *h=new http(APISTRUCT);

        // send the content type
        h->contentType("text","html",NULL);

	... store the session state to the database ...

	... get the session id ...

        // set the session id
        h->setCookie("sessionid",sessionid,"myschool.edu","/library","Fri, 06 Nov 2020 08:49:37 GMT",0);

        // terminate the header
        h->cr();

        ... send some data ...

        delete h;
}

It is also possible to prevent a cookie from being passed over an insecure connection. If the secure paramter is set to 1 and the CGI is run over an insecure connection, the cookie is not set. If the secure parameter is set to 0, the cookie is set whether the connection is secure or not.

#include <groundwork/http.h>
#include <groundwork/cgimodule.h>

MAIN {

        http    *h=new http(APISTRUCT);

        // send the content type
        h->contentType("text","html",NULL);

	... store the session state to the database ...

	... get the session id ...

        // set the session id
        h->setCookie("sessionid",sessionid,"myschool.edu","/library","Fri, 06 Nov 2020 08:49:37 GMT",1);

        // terminate the header
        h->cr();

        ... send some data ...

        delete h;
}