Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I have a password protected area on my web site and want to set a cookie once users login into the area. However, I'm wondering what to include in the name and value fields of the cookie. I thought that I could set the name of the cookie to the username and then the value would be "1" if the user had previously logged in. To authenticate the user, I would just check to see if the value were 1. However, it occured to me that other users could gain access to the website by just spoofing a cookie with a particular username and setting the cookie value to 1.

My next thoughts were to assign each user a random number and track this number in a database. I would then set the cookie name to the username and the value to the random number. Each time I would read the cookie in, I would check it in the database if the username and "number" were correctly associated with each other. However, this is going to increase the load of my db because every pageview is now going to require a database check.

Any thoughts on the optimal values for the cookie?

Replies are listed 'Best First'.
Re: Authenticate with Cookies
by John M. Dlugosz (Monsignor) on Dec 25, 2002 at 20:36 UTC
    If you want to avoid the database hit, use a one-way keyed hash of the name or session ID or something. Then you can re-compute it quickly without the disk hit, to see if it matches.
      I understand what you mean, but am not sure how to do it in practice. You are saying that I could run some computation to translate the username into a unique set of numbers. This computation would be done the same way for all the usernames, letting me easily see if the username and number matches, right?

      How would I compute a set of numbers from the username?
      Thanks
        See the Digest::HMAC module, which does that. The result is not unique, but hard to guess because it's 128 or 160 bits, and impossible to figure backwards other than guessing, and nobody else can do it without knowing the same key. Read up on "digest", "one-way hashing function" and "keyed hashing" as a cryptographic primitive.

Re: Authenticate with Cookies
by adrianh (Chancellor) on Dec 25, 2002 at 22:27 UTC
Re: Authenticate with Cookies
by tachyon (Chancellor) on Dec 26, 2002 at 02:44 UTC

    You could save youself a lot of bother by using the .htaccess functionality in Apache which will look after all the details for you.

    tachyon

    s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

Re: Authenticate with Cookies
by PodMaster (Abbot) on Dec 26, 2002 at 08:27 UTC
    I see people pointing merlyns article out all the time, so I read it once, and frankly, I didn't like the code one bit (well I did, but it wasn't very reusable), so I grabbed myself a copy of CGI::Application, and reworked merlyns example using CGI::Application, a framework for CGI Applications ;)

    You can read/download it at http://crazyinsomniac.perlmonk.org/perl/generic-cgi-app/


    MJD says you can't just make shit up and expect the computer to know what you mean, retardo!
    ** The Third rule of perl club is a statement of fact: pod is sexy.

Re: Authenticate with Cookies
by mkirank (Chaplain) on Dec 26, 2002 at 09:32 UTC
    There is a good example in the MOD_PERL Eagle Book which uses MAC ....
    # Check or generate the MAC authentication information sub MAC { my($state, $action) = @_; return undef unless ref($state); my @fields = @{$state}{qw(TIME ODNAME USRNAME)}; my ($newmac) = MD5->hexhash(SECRET . MD5->hexhash(join '', SECRET, @fields)); return $newmac eq $state->{MAC} if $action eq 'check'; return $state->{MAC} = $newmac if $action eq 'generate'; undef; } # Save the current state sub save_state { my $state = shift; MAC($state, 'generate'); # add MAC to the state # encrypt the cookie my $encrypted = $CIPHER->encrypt_hex(join ':', %{$state}); return CGI::Cookie->new(-name => COOKIE_NAME, -path =>'/cgi-bin', -value => $encrypted, ); } # Retrieve an existing state sub get_state { my $cookie = CGI::cookie(COOKIE_NAME); return undef unless $cookie; # decrypt the cookie my %state = split ':', $CIPHER->decrypt_hex($cookie); authentication_error() unless MAC(\%state, 'check'); return \%state; }
Re: Authenticate with Cookies
by tachyon (Chancellor) on Dec 26, 2002 at 03:14 UTC

    For a detailed discussion of how to do it right read this article by the esteemed merlyn There is some well documented code to get you started.

    cheers

    tachyon

    s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

Re: Authenticate with Cookies
by Massyn (Hermit) on Dec 26, 2002 at 10:12 UTC

    #!/fellow/monks.pl

    Personally I'm not a big fan of cookies. When I write CGI's, I'd like the script to be able to run on any machine. By any, I mean machines that do not allow cookies, Java Applets/Scritps, etc. Please note: This is my personal feeling. If you do use it, don't change your code.

    I've been working on a CGI project that will do authentication and session handling within a CGI application. Have a look at MWS (Massyn Web Security). I'm sure the script will be able to do a lot for you. You do need to have mySQL handy...

    Thanks!

    #!/massyn.pl The more I learn, the more I realize I don't know. Albert Einstein 1879-1955

      All browsers since Netscape 1.1 and all versions of IE support cookies. Even Lynx supports cookies.

      While there is an horrible abuse of cookies on the web (why am I getting a new cookie for every single image on the page?) there are a good set of problems that can't be solved without resorting to even worse hacks (like hidden fields in the input or URL munging). HTTP was designed to be stateless, and getting it to fake statefulness is going to require jumping through some hoops. Cookies aren't perfect, but look at the alternatives.