Archive: August 24, 2015

<<< August 23, 2015

Home

August 31, 2015 >>>


performing HTTP authentication in CGI

Monday,  08/24/15  05:13 PM

Pardon this nerdy post, but here is how you can do HTTP authentication processing in a CGI program.  The Internet doesn't know how to do this, and I do.  So here you go, Internet.

Here's how HTTP authentication works.  A request is sent to a server, and if there is no authentication the server responds with a 401 status.  This causes the client (browser) to prompt the user for a username and password.  When entered, the username and password are combined and sent to the server in the Authorization: header, like this:

Authorization: basic <username:password>

The <username:password> part is base-64 encoded, which is *not* encryption, so to avoid sniffing this should only be done on an SSL-encrypted (HTTPS) connection.

The server validates the username and password, and if there's a problem, it sends back a 401 status again.  If everything is okay, it processes the request, such as executing a CGI program.  So far so good.

Now ... what if you don't want the server to perform authentication for you, and instead, want to perform the authentication inside the CGI program itself?  Aha, glad you asked!

You have to modify the Apache [webserver] configuration, as follows:

... in modules section, if not already enabled:
LoadModule authn_anon_module modules/mod_authn_anon.so

... in server section, or in <VirtualHost>:
SetEnvIf Authorization (.*) HTTP_AUTHORIZATION=$1

... in appropriate <Directory>:
AuthName "My auth realm"     (required; default if realm not set)
AuthType Basic               (username:password, base64-encoded)
AuthBasicProvider anon       (use anonymous auth)
Anonymous *                  (allow any username)
Anonymous_NoUserID on        (optional, ok if username blank)
Anonymous_MustGiveEmail off  (optional, ok if password blank)
Require valid-user           (optional, forces auth processing)

Here's what's happening.  Loading mod_authn_anon enables the use of a "AuthBasicProvider anon " directive.  That's the secret sauce.  The "Anonymous * " directive allows any user through the server checking.  Once through the server checking, the SetEnvIf directive sets an environment variable named HTTP_AUTHORIZATION with the value of the Authorization: header, from where it can be accessed by the CGI program.

You can tune the way this works a bit.  The "Require valid-user " directive means the initial 401 will be sent (because there is no Authorization: header), so you will always prompt for entry of a username and password.  That's probably what you want, but if not, you can omit this directive in which case no Authorization: at all is okay and a blank value will be passed through to the CGI.  The "Anonymous_NoUserID on " directive allows a blank username; if omitted, a blank username will be treated like a missing Authorization: header, and a 401 will be returned by the server.  The "Anonymous_MustGiveEmail off " directive allows a blank password; if omitted, a blank password will result in the server returning a 401 directly.  (The anon mechanism was initially devised for anonymous FTP, where an email address is often supplied as the password.)

Note that in all cases the CGI can return a 401 itself by writing a "Status: 401 " header, which will cause the client (browser) to prompt for a username and password again.

Trust me, this works, and I tried just about everything else.  You are welcome!

 
 

Return to the archive.