Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot

automating basic authentication

by cLive ;-) (Prior)
on Sep 13, 2003 at 09:16 UTC ( #291226=perlquestion: print w/replies, xml ) Need Help??

cLive ;-) has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to write a proxy server that will automatically add basic authentication to a request to a particular host. I've been having a play with BooK's HTTP::Proxy, but can't seem to get it to work as expected. Here's the server:

#!/usr/bin/perl use HTTP::Proxy qw(); use strict; use warnings; my $proxy = HTTP::Proxy->new( port => 3128 ); $proxy->push_headers_filter( request => sub { my $headers = shift; # grabbed from http request header of logged in browser $headers->header( Authorization => "BASIC cm9verMSZXZhadDpRHRq +"); }, response => sub { $_[0]->remove_header(qw(WWW-Authenticate)); }, ); $proxy->start;
So far, the proxy server works OK as far as other domains go. But, when I try to connect to the authentication server, I still get the enter password box.

Any suggestions on how to proceed?

I'm not 100% sure I'm doing this the right way either - the docs for the module are quite basic, and I haven't found any tutorials yet on writing proxies.

The above example is for just one password. In reality, there may be a few, and I need to add the correct encrypted password to the request header as appropriate.

Or maybe there's a better way to achieve this? What I need to be able to do is:

  • authenticate users via proxy (probably set a session cookie)
  • when authenticated by the proxy, if a user calls a password protected server in my list, I automatically add Authorization headers to requests, so they get a seamless login and don't have to know passwords (and I can lock them out as needed)
  • only call the push_headers_filter() method if user's sessioncookie is valid and site is on list.

I do not have access to the machine sending the username/password challenges.

Any thoughts or suggestions?

cLive ;-)

Replies are listed 'Best First'.
Re: automating basic authentication
by liz (Monsignor) on Sep 13, 2003 at 10:16 UTC
    The password box is caused by a status code 401 (Authorization Required) if I remember correctly. I don't see you changing the status of the request towards the final client. The client should get a status 200 (OK). No sure how to do that with HTTP::Proxy.

    Hope this helps.


Re: automating basic authentication
by bsb (Priest) on Sep 13, 2003 at 10:54 UTC
    Disclaimer: I know nothing about HTTP::Proxy
    Claimer: I know way too much about Basic Authentication (1)

    I'm assuming url credentials like aren't relevant.

    LWP's GET -eSUd is a good debugging aid here. It'll show you the basic headers to compare to your own.

    Another idea: put up your own server and watch the requests (or proxy your proxy to see what it's trying to do)

    (1) I tried to write a module that would fallback to using the basic credentials as a pseudo-cookie if a client had cookies switched off. Many 401's and 30x's later I discovered that it wasn't practically possible if you want to support Mozilla and changing user(IE works though). "wasn't practically possible" is a big call, let's say I couldn't do it.

      The username/password combo is base64 encoded and sent as a line of the request header.

      I'm looking to intercept the request to add this authentication header. I just had the remove header in while playing around with it.

      I guess I just want to see a non trivial example of this module in action.


      cLive ;-)

Re: automating basic authentication
by BooK (Curate) on Sep 16, 2003 at 14:32 UTC

    What you want to do is to add auto-authentication to a particular web site. I'll talk about how you could do this with the next version of HTTP::Proxy, which will be out someday, when I have more time to work on the remaining details.

    I must admit I haven't read your code that much, and that the old API is a little behind me now, but:

    • You simply have to add a filter that adds the correct WWW-Authenticate: header (you can sniff the connection, for example). You shouldn't receive any 401, since you are authenticated.
    • You should only push this filter for request that you need to authenticate:
      proxy->push_headers_filter( host => 'www\\.example\\.com', # it's a regexp request => sub { my ( $headers, $message ) = @_; $headers->header( Authorization => "Basic cm9verMSZXZhadDpRHRq +" ); } );
    • There is no need for a response filter, if the answer you get is a 200. If you are correctly authenticated by the server, it won't send back a WWW-Authenticate: header.
    • If you send the wrong password, you'll get a 401.
    • Did you try Basic instead of BASIC?
    • A possible application would be a filter that catches WWW-Authenticate: and Authorization: to store/cache authentication information and reuse it for all users.

    In your post you say:

    the docs for the module are quite basic

    I resent that... ;-) In version 0.09, the HTTP/ file is 974 lines long, and there are 303 lines of pod documentation. Please tell me what's missing, so I can improve that in the next version (where 12 new modules will appear).

    Warning: The HTTP::Proxy API will change a lot in version 0.10. It should be much easier to write simple filters, and a lot of helper filters and examples will be included. The latest CVS snapshot is always available from

    For those interested, an example proxy is running most of the time on (It's a proxy: you need to configure your browser to use it.)

      "Please tell me what's missing"

      Just some more slightly complicated examples :) I get the general idea, but it would be good to include an example that does quite a bit more based on the request - eg, cookie retrieval and testing and then proceeding based on cookie value etc...

      But thanks for the reply. Much appreciated :)

      cLive ;-)

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://291226]
Approved by gmax
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (2)
As of 2023-05-29 02:38 GMT
Find Nodes?
    Voting Booth?

    No recent polls found