title: permanent ldap authenticated session
body: <p>I am trying to build a simple web based directory navigation/administration application.</p>
  
  <p>Application requirements:</p>
  
  <ul>
  <li>An Active Directory (or another directory service) domain user access
  this web application and log in with the same domain user/password
  credentials.</li>
  <li>Then the user can navigate the directory tree, create/edit entries,
  edit an entry's attribute, etc..</li>
  </ul>
  
  <p>I'm using perl Net::LDAP for the ldap operations, as in:</p>
  
  <pre><code>#!/usr/bin/perl -wT
  
  use Net::LDAP;
  use CGI qw(:standard);
  use CGI::Carp qw(warningsToBrowser fatalsToBrowser);
  
  my $ssl = 1;
  my $srv = '192.168.56.110';
  my $uri = $ssl ? 'ldaps://' : 'ldap://';
  
  my $c = Net::LDAP-&gt;new($uri . $srv) or
      die "Unable to connect to server: $@\n";
  
  # !!! This is a temporary workaround !!!
  my $binddn = "cn=Administrator,cn=users,dc=example,dc=com";
  my $passwd = "password";
  
  my $mesg = $c-&gt;bind($binddn, password =&gt; $passwd);
  die 'Unable to bind: ' . $mesg-&gt;error . "\n" if $mesg-&gt;code;
  
  # DN to be deleted
  my $dn = param('DN');
  
  $mesg = $c-&gt;delete($dn);
  die 'Error in delete: '. $mesg-&gt;error() ."\n" if $mesg-&gt;code();
  
  $c-&gt;unbind;
  </code></pre>
  
  <p>I can call this cgi script with a HTML form, as in:</p>
  
  <pre><code>&lt;form action="/cgi-bin/del.cgi" method="post"&gt;
  &lt;br&gt;Peter Parker
  &lt;input type="radio" name="DN"
      value="cn=peter parker,cn=users,dc=example,dc=com"&gt;
  &lt;br&gt;Clark Kent
  &lt;input type="radio" name="DN"
      value="cn=clark kent,cn=users,dc=example,dc=com"&gt;
  &lt;br&gt;
  &lt;input type="submit" value="Delete User"&gt;
  &lt;/form&gt;
  </code></pre>
  
  <p>The problem with this code is that the ldap operations are using administrative credentials, not the credentials of the user running the web application. I'm using this workaround because I can't ask the user for his/her credentials every time.. and I don't know how to keep a user permanently authenticated.</p>
  
  <p>My web application authenticate the user via ldap, asking he's credentials and issuing a bind request to the directory service, as in:</p>
  
  <pre><code>...
  # read user supplied credentials
  my $user_id = param('user_id');
  my $password = param('password');
  
  # now find the DN of user_id in directory
  my $ssl = 1;
  my $srv = '192.168.56.110';
  my $uri = $ssl ? 'ldaps://' : 'ldap://';
  
  my $c = Net::LDAP-&gt;new($uri . $srv) or
      die "Unable to connect to server: $@";
  
  # admin credentials are needed here to find the user DN
  my $rootdn = "cn=Administrator,cn=users,dc=example,dc=com";
  my $rootpw = "secret";
  
  my $mesg = $c-&gt;bind($rootdn, password =&gt; $rootpw);
  die "Unable to bind: ". $mesg-&gt;error if $mesg-&gt;code;
  
  $mesg = $c-&gt;search(
      base    =&gt; 'dc=example,dc=com',
      scope   =&gt; 'sub',
      filter  =&gt; "(&amp;(objectClass=user)(sAMAccountName=$user_id))",
      attrs   =&gt; ['sAMAccountName'],
  );
  die "Bad search: ". $mesg-&gt;error() if $mesg-&gt;code();
  
  my ($entry) = $mesg-&gt;entries;
  die "User not found: $user_id\n" unless $entry;
  
  my $dn = $entry-&gt;dn;
  
  # User DN found.. now check the credentials
  $mesg = $c-&gt;bind($dn, password =&gt; $password);
  die "Unable to bind: ". $mesg-&gt;error if $mesg-&gt;code;
  
  $c-&gt;unbind();
  
  # credentials validated!
  print header, start_html('Welcome!'), h1('Hello, YOU!'), end_html;
  </code></pre>
  
  <p>After that, a cookie is sent to the user browser initiating a web session.
  I could keep the user credentials in a database and then pass it to del.cgi (and other similar script) any time I needed.. but I don't think it's good security practice. </p>
  
  <p><strong>What can I do to keep a permanent ldap authenticated session as long as the web session is active?</strong></p>