Link to home
Start Free TrialLog in
Avatar of massea
massea

asked on

Authorization, AGAIN !?!

ok, i have looked through ee, newsgroups rfc's and so on
but...

could anyone show me a CGI that uses the basic auth scheeme?
don't make it hard, hard code user password and i don't need more than something like:

$ENV{WWW-Authentication} or
  print "401 Access denied\n\n";

print <<EOF;
Content-type: text/plain

It worked, you're in

EOF

exit 1;

is this possible?


Avatar of thoellri
thoellri

massea,

there are several answers, more or less complicated, to your question. Talking about "Basic Authentication" means that the server is taking care of the authentication piece. I'll show you three differnet methods and you pick whatever you want. I assume you're on Unix and using the Apache server:

1.) htpasswd:

a) Create a passwd-file with the first username, as in "htpasswd -c /usr/local/etc/httpd.users admin". This would create a new password file and prompt you to enter the password for user "admin".
b) For every user who needs access to your restricted area call "htpasswd /usr/local/etc/httpd.users user". This time with "-c". Enter password for each username.
c) Now to restrict access to a directory you would create a ".htaccess"  file in that directory and put the following in there:

            AuthName "restricted"
            AuthType Basic
            AuthUserFile /usr/local/etc/httpd.users
            require valid-user
d) Now try to access the directory and you'll see that only user/password combinations which appear in /usr/local/etc/httpd.users are allowed to enter the area.

2.) mod_perl:
Using mod_perl allows you to write different authentication handlers directly in perl. There are a number of Authen-handlers already out there. Is suggest to look at http://theory.uwinnipeg.ca/search/cpan-search.html and search for "Authen"
a) Create the following file (in my case it is /usr/local/apache/lib/perl/Apache/AuthNIS.pm):

package Apache::AuthNIS;
# authenticate users on system password database
use strict;
use Apache::Constants ':common';
sub handler {
         my $r = shift;
         my($res, $sent_pwd) = $r->get_basic_auth_pw;
         return $res if $res != OK;
         my $user = $r->connection->user;
         my $reason = "";
         my($name,$passwd) = getpwnam($user);
         if (!$name) {
             $reason = "user does not have an account on this system";
         } else {
             $reason = "user did not provide correct password"
                 unless $passwd eq crypt($sent_pwd,$passwd);
         }
         if($reason) {
             $r->note_basic_auth_failure;
             $r->log_reason($reason,$r->filename);
             return AUTH_REQUIRED;
         }
         return OK;
}
1;

b) Now for the restircted area, create another .htaccess file with the following content:

    AuthName Test
    AuthType Basic
    PerlAuthenHandler Apache::AuthNIS
    require valid-user

c) If you have mod_perl configured to include the AuthenHandler, then the Perl-module will be called and it will check against your /etc/passwd (/etc/shadow) or yp/nis passwd file to authenticate valid users. There is no need to create a separate passwd-file using htpasswd

3.) Do-it-your-self:
a) Write a little cgi-script, which creates a form with username/password entries:

#!/usr/local/bin/perl
use strict;
use CGI;
my $cgi=new CGI;
my $error;
if (defined($cgi->param('user')) && defined($cgi->param('password'))) {
   $error=checkAuthen($cgi->param('user'), $cgi->param('password'));
   if (!$error) {
      # send the user to a secret place or do what ever you want here
      print $cgi->redirect("http://www.adobe.com");
      exit 0;
   }
}
genAuthen($cgi,$error);
sub genAuthen {
   my($cgi,$error)=@_;
   print $cgi->header;
   print $cgi->start_html("Authorisation required");
   if ($error) {
      print "Error: <b>$error<b><p>\n";
   }
   print $cgi->start_form();
   print "Username: ",$cgi->textfield("user"),"<p>";
   print "Password: ",$cgi->password_field("password"),"<p>";
   print $cgi->submit;
   print $cgi->end_form();
   print $cgi->end_html();
}
sub checkAuthen {
   my($user,$password)=@_;
   return undef if ($user eq "me" && $password eq "secret");
   return "Not authorized!";
}

b) Put the script somewhere on your server where executable content is allowed.
c) Now access it, you will only be able to proceed to the "secret" place if you enter the right username and password.

Hope this helps
  Tobias
Avatar of massea

ASKER

thanks tobias,
I hate to dissapoint you, with your extensive reply in mind and all, but what I want is the propper HTTP exchange/negotiation that makes Netscape/IExplorer pop up the 'enter password' dialog, what responses to expect and generate according to HTTP-protocol.
Please write me if you think this is unfair.

massea

ps. using PWS/Jigsaw/Apache and ActivePerl on Win98 ds.
Hi massea,

sorry if I misunderstood your question in the first. Let me try to show you what's going on when a browser requests access to an area which is protected by basic authentication. In the following I captured all the packets which are sent between the browser (tobiasnt) and the server (basic). The lines with *** in the beginning are the start of a new packet. Following the time you can identify the sending host.port and the receiving host.port. After each packet I add an explanation, of what's happening there. The explanation starts with +++ and is not part of the packet:

*** 08:57:54 tobiasnt.2827 > tobias.http:
GET /admin/ HTTP/1.0
Connection: Keep-Alive
User-Agent: Mozilla/4.5 [en] (WinNT; I)
Host: tobias.corp.adobe.com
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*
Accept-Encoding: gzip
Accept-Language: en
Accept-Charset: iso-8859-1,*,utf-8

+++ This is the initial request from my browser (tobiasnt.2827) to the Apache-server (tobias.http). Nothing special here.

*** 08:57:55 tobias.http > tobiasnt.2827:
HTTP/1.1 401 Authorization Required
Date: Fri, 02 Jul 1999 15:57:54 GMT
Server: Apache/1.3.4 (Unix) mod_perl/1.18
WWW-Authenticate: Basic realm="Test"
Connection: close
Content-Type: text/html

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<HTML><HEAD>
<TITLE>401 Authorization Required</TITLE>
</HEAD><BODY>
<H1>Authorization Required</H1>
This server could not verify that you
are authorized to access the document you
requested.  Either you supplied the wrong
credentials (e.g., bad password), or your
browser doesn't understand how to supply
the credentials required.<P>
</BODY></HTML>

+++ The Apache server sees that the area I'm trying to access is protected. The information is stored in the .htaccess file of this directory on the server. The server responds with the header 'WWW-Authenticate: Basic realm="Test"'. This header causes the browser to pop up the window where it asks for username/password. The HTML in the response is for browser which do not understand status-code 401 and the WWW-Authenticate" header. At this point I enter my username and password in the dialog and hit OK.

*** 08:58:02 tobiasnt.2828 > tobias.http:
GET /admin/ HTTP/1.0
Connection: Keep-Alive
User-Agent: Mozilla/4.5 [en] (WinNT; I)
Host: tobias.corp.adobe.com
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*
Accept-Encoding: gzip
Accept-Language: en
Accept-Charset: iso-8859-1,*,utf-8
Authorization: Basic GdvAXuIodkl78903uiosdh=5

+++ The browser sends the information about my username/password MD5-encoded to  the server in the "Authorization" header. The string following the this header-field defines the type of authentication used. "Basic" in our case. The string following Basic is my username/password MD5 encoded (Of course I changed the string and you won't be able to get my username/password from the one above).


*** 08:58:06 tobias.http > tobiasnt.2828:
HTTP/1.1 200 OK
Date: Fri, 02 Jul 1999 15:58:02 GMT
Server: Apache/1.3.4 (Unix) mod_perl/1.18
Connection: close
Content-Type: text/html

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<HTML><HEAD> .....

+++ The server checks the information in the 'Authenticate' header and finds out that I have enough credentials to access the area. The html is following the response. If I make a mistake when entering the username/password the server will present the same response as before (401).

Does this help you?

  Tobias



Avatar of massea

ASKER

Thanks Tobias,
Sorry for the delayed reply :-( .
your excerpt showed me I missed something obvious. It solved it for me. Now I'm only going to find out how to give you your doe...

Thanks again Mats.


Avatar of massea

ASKER

OK I've just checked out the rules.
You haven't locked my question and so I can't grade your answer, but do that and I will..

Mats
ASKER CERTIFIED SOLUTION
Avatar of thoellri
thoellri

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial