Set AuthName to prompt for sequential passwords

Set AuthName to prompt for sequential passwords

am 20.12.2010 04:36:16 von Matt Puumala

Greetings!

I am trying to make a two-factor authentication module, built on
AuthType Basic. (google for Perfect Paper Passwords for the scheme I'm
using). To make it work, I need to be able to prompt the user to type
in two passwords sequentially.

So, the user comes to the page, apache sends "401 AuthRequired" and
the configured AuthName (this is prompt 1).

The user enters username and first password. The module verifies, and
constructs the second prompt.

In my plan, I'd like to set the AuthName for that client, then send
back "401 AuthRequired" again. The new AuthName realm is prompt 2,
which is shown to the user.

However, I'm having problems changing the AuthName.

I'm starting with extremely simple test bed, using output files to
dump data.

I expected the "Old Auth Name" to be "Testing the Thing", and the "New
Auth Name" to be "Simple String". But the Auth Name doesn't change.

This is my first apache module. Is there something in the intricacies
of the request cycle that I'm missing? Or is there some other obviously
better way to prompt for passwords sequentially?


Server: Windows XP running XAMPP.
Server version: Apache/2.2.14 (Win32)
Server built: Nov 11 2009 14:29:03
mod_perl/2.0.4 Perl/v5.10.1

------- Auth Handler Skeleton ---------------
package CustomAuth::AuthTwoPW;

use strict;
use Apache2::Const qw(:common);
use Apache2::Access ();

sub handler
{
my $r = shift;
my($res, $sent_pw) = $r->get_basic_auth_pw;

# debug output
my $FH;
open $FH, ">", "/Documents and Settings/Matt/Desktop/stuff.txt";
my $stoij = "response is " . $res . "\nSent pw is " . $sent_pw . "\n";
print $FH $stoij;

return $res if $res != OK;

my $user = $r->connection->user;
unless($user eq "matt" and $sent_pw eq "pw1")
{

print $FH "Didnt get good pw, returning AUTH_REQUIRED\n";

$r->note_basic_auth_failure;
$r->log_error("Didn't get good first password",
$r->filename);
return AUTH_REQUIRED;
}

# Got first username/pw combo. RESET, change prompts, and get next set

# reset prompts
my $oldval = $r->auth_name("Simple String");
my $newval = $r->auth_name();

print $FH "Old authname val is " . $oldval . "\n";
print $FH "New authname val is " . $newval . "\n";

# Reset headers so client auth's again
$r->note_basic_auth_failure;

# ask for second pw
return AUTH_REQUIRED;


} # closes 'handler'

1;
------- END Auth Handler Skeleton ---------------

------- Debug File Output -----------------
response is 0
Sent pw is pw1
Old authname val is Testing The Thing
New authname val is Testing The Thing
------- END Debug File Output -----------------


------- ModPerl Config ----------------------
LoadFile "C:/Documents and Settings/Matt/My
Documents/xampp/perl/bin/perl510.dll"
LoadModule perl_module modules/mod_perl.so
LoadModule apreq_module modules/mod_apreq2.so

PerlSwitches -T
PerlPostConfigRequire "C:/Documents and Settings/Matt/My
Documents/xampp/apache/conf/extra/startup.pl"


....[ snip ]...


Documents/xampp/htdocs/authenticatedstuff">
SetHandler perl-script
AuthName "Testing The Thing"
AuthType Basic
PerlOptions +GlobalRequest
PerlAuthenHandler CustomAuth::AuthTwoPW
require valid-user



# ASP settings
Include "conf/extra/asp.conf"
------- END ModPerl Config ----------------------

Re: Set AuthName to prompt for sequential passwords

am 20.12.2010 10:46:04 von aw

Hi.

Without going into the details of your code, I believe that what you are bumping against
may be the very nature of HTTP.

In your scheme, you need 2 consecutive interactions with the user, and the second one
needs to be able to "remember" what the first one was.
The basic logic of HTTP goes against that : each request/response cycle is totally
independent of the others, and there is no "memory" kept between two transactions.
At least not by HTTP itself. Think that between your first interaction, and the second,
there may have been 1000 other request/response cycles happening for other users.

So the only way to do this, is by super-imposing some kind of "session" mechanism, whereby
the server can detect, on the second request, that there has been a first one, and what
its results were.
There are various such schemes, but the simplest mechanism for doing that is probably via
cookies.
Your first request/response should set a "step 1 cookie", which is detected and read by
the second request/response cycle, which then modifies that cookie into a "step 2 cookie".
Your real application areas should then require the step 2 cookie for authenticating a
user and granting the resource.

I think that trying to do this by playing with the "realm", which is intimately linked to
the URL requested by the browser, is going to lead you into loops of logic.



Matt Puumala wrote:
> Greetings!
>
> I am trying to make a two-factor authentication module, built on
> AuthType Basic. (google for Perfect Paper Passwords for the scheme I'm
> using). To make it work, I need to be able to prompt the user to type
> in two passwords sequentially.
>
> So, the user comes to the page, apache sends "401 AuthRequired" and
> the configured AuthName (this is prompt 1).
>
> The user enters username and first password. The module verifies, and
> constructs the second prompt.
>
> In my plan, I'd like to set the AuthName for that client, then send
> back "401 AuthRequired" again. The new AuthName realm is prompt 2,
> which is shown to the user.
>
> However, I'm having problems changing the AuthName.
>
> I'm starting with extremely simple test bed, using output files to
> dump data.
>
> I expected the "Old Auth Name" to be "Testing the Thing", and the "New
> Auth Name" to be "Simple String". But the Auth Name doesn't change.
>
> This is my first apache module. Is there something in the intricacies
> of the request cycle that I'm missing? Or is there some other obviously
> better way to prompt for passwords sequentially?
>
>
> Server: Windows XP running XAMPP.
> Server version: Apache/2.2.14 (Win32)
> Server built: Nov 11 2009 14:29:03
> mod_perl/2.0.4 Perl/v5.10.1
>
> ------- Auth Handler Skeleton ---------------
> package CustomAuth::AuthTwoPW;
>
> use strict;
> use Apache2::Const qw(:common);
> use Apache2::Access ();
>
> sub handler
> {
> my $r = shift;
> my($res, $sent_pw) = $r->get_basic_auth_pw;
>
> # debug output
> my $FH;
> open $FH, ">", "/Documents and Settings/Matt/Desktop/stuff.txt";
> my $stoij = "response is " . $res . "\nSent pw is " . $sent_pw . "\n";
> print $FH $stoij;
>
> return $res if $res != OK;
>
> my $user = $r->connection->user;
> unless($user eq "matt" and $sent_pw eq "pw1")
> {
>
> print $FH "Didnt get good pw, returning AUTH_REQUIRED\n";
>
> $r->note_basic_auth_failure;
> $r->log_error("Didn't get good first password",
> $r->filename);
> return AUTH_REQUIRED;
> }
>
> # Got first username/pw combo. RESET, change prompts, and get next set
>
> # reset prompts
> my $oldval = $r->auth_name("Simple String");
> my $newval = $r->auth_name();
>
> print $FH "Old authname val is " . $oldval . "\n";
> print $FH "New authname val is " . $newval . "\n";
>
> # Reset headers so client auth's again
> $r->note_basic_auth_failure;
>
> # ask for second pw
> return AUTH_REQUIRED;
>
>
> } # closes 'handler'
>
> 1;
> ------- END Auth Handler Skeleton ---------------
>
> ------- Debug File Output -----------------
> response is 0
> Sent pw is pw1
> Old authname val is Testing The Thing
> New authname val is Testing The Thing
> ------- END Debug File Output -----------------
>
>
> ------- ModPerl Config ----------------------
> LoadFile "C:/Documents and Settings/Matt/My
> Documents/xampp/perl/bin/perl510.dll"
> LoadModule perl_module modules/mod_perl.so
> LoadModule apreq_module modules/mod_apreq2.so
>
> PerlSwitches -T
> PerlPostConfigRequire "C:/Documents and Settings/Matt/My
> Documents/xampp/apache/conf/extra/startup.pl"
>
>
> ...[ snip ]...
>
>
> > Documents/xampp/htdocs/authenticatedstuff">
> SetHandler perl-script
> AuthName "Testing The Thing"
> AuthType Basic
> PerlOptions +GlobalRequest
> PerlAuthenHandler CustomAuth::AuthTwoPW
> require valid-user
>

>
>
> # ASP settings
> Include "conf/extra/asp.conf"
> ------- END ModPerl Config ----------------------
>

Re: Set AuthName to prompt for sequential passwords

am 20.12.2010 20:38:11 von Matt Puumala

Thank you for the reply!

I am with you 100%. There are plans for the session db, and the cookie
format, all on the drawing boards, to get past "stateless http". But
I'm trying to do it stepwise, to save my sanity.

So for now the question is: How do I actually prompt the user for the
passwords? My reason for using Basic Auth and changing the realm is to
make use of browsers' built-in popup auth mechanism. Is my solution of
just authenticating twice naive? Is there a way to control that
mechanism more manually (this is where my "change the AuthName in
code" idea came from)? If not that, then...? Create an HTML form on
the fly? (My gut says "eww" to that.) Any ideas you might have, including
where to go to read more, are welcome.

Also, you mention that secure areas should "require a cookie". You've
anticipated my next question... BUT!!! I'll start a new thread
later, if I can't find answers in my reading.

Again, thanks for your thoughts!

Matt


On Mon, Dec 20, 2010 at 3:46 AM, Andr=E9 Warnier wrote:
> Hi.
>
> Without going into the details of your code, I believe that what you are
> bumping against may be the very nature of HTTP.
>
> In your scheme, you need 2 consecutive interactions with the user, and th=
e
> second one needs to be able to "remember" what the first one was.
> The basic logic of HTTP goes against that : each request/response cycle i=
s
> totally independent of the others, and there is no "memory" kept between =
two
> transactions.
> At least not by HTTP itself. Think that between your first interaction, a=
nd
> the second, there may have been 1000 other request/response cycles happen=
ing
> for other users.
>
> So the only way to do this, is by super-imposing some kind of "session"
> mechanism, whereby the server can detect, on the second request, that the=
re
> has been a first one, and what its results were.
> There are various such schemes, but the simplest mechanism for doing that=
is
> probably via cookies.
> Your first request/response should set a "step 1 cookie", which is detect=
ed
> and read by the second request/response cycle, which then modifies that
> cookie into a "step 2 cookie".
> Your real application areas should then require the step 2 cookie for
> authenticating a user and granting the resource.
>
> I think that trying to do this by playing with the "realm", which is
> intimately linked to the URL requested by the browser, is going to lead y=
ou
> into loops of logic.
>
>
>
> Matt Puumala wrote:
>> [ snip ]

Re: Set AuthName to prompt for sequential passwords

am 21.12.2010 01:40:15 von aw

Matt Puumala wrote:
> Thank you for the reply!
>
> I am with you 100%. There are plans for the session db, and the cookie
> format, all on the drawing boards, to get past "stateless http". But
> I'm trying to do it stepwise, to save my sanity.

Talking about HTTP authentication, that's a good plan.
Unfortunately sometimes difficult to follow, because HTTP authentication is full of twists
and turns that don't usually let you do things stepwise.

>
> So for now the question is: How do I actually prompt the user for the
> passwords? My reason for using Basic Auth and changing the realm is to
> make use of browsers' built-in popup auth mechanism. Is my solution of
> just authenticating twice naive? Is there a way to control that
> mechanism more manually (this is where my "change the AuthName in
> code" idea came from)? If not that, then...? Create an HTML form on
> the fly? (My gut says "eww" to that.) Any ideas you might have, including
> where to go to read more, are welcome.
>
There is already plenty of stuff in the above paragraph to be answered.

What the browser displays in the title bar of its embedded authentication mechanism, is
nothing else than the content of the "realm" of the "auth required" header that it
receives back from the server. So you could "trick" that by fabricating this header (and
the 401 response) yourself, instead of letting Apache send it.
When the browser response will come back, it will have an "Authorization" header
containing this same "realm" part that you sent, and since it is your authentication
module catching this new request, you can deal with it too.
I am also quite sure that you could, with mod_perl, go and play games with Apache to
change it's notion of the "realm" you are in. But what I am not so sure of, are the
unforeseen side-effects of doing that.

So I do believe that with your scheme, it may be better to go right away to your own login
pages. You can either create them on-the-fly, or have a template on disk with some
pre-defined kind of markers which you would replace by whatever message you want to place
there. Which could even be things such as


....
which you find with a perl regexp and replace on the fly before sending the page to the
user. Then when the user re-posts that form (remember, maybe 30 minutes later), you can
re-read these parameters to remember where you're at. That may replace the cookie.
Provided that you do not give the opportunity for an ill-intentioned user to save the
received form to disk, play with the hidden values, and then re-post the modified form and
gain some advantage by doing so.

For more ideas, the Apache::AuthCookie module and the other Apache::Auth* on CPAN are a
good start.

I think that the main thing to keep in mind, is that whenever you send back a response to
the browser (whether it is a 401 or a 200 or whatever), the current request/response cycle
is finished, done, forgotten, and the next request your module handles may be in 3 hours,
come from another browser in another country, and be handled by another Apache child
running another perl interpreter and another copy of your Auth module.
And if this new request happens to be a second one from a browser with which you
interacted before, you have to be able to tell that only by the content of this new
request. (Whether that is because it contains a cookie, or because it posts some special
parameter from a form is a matter of choice, it is not essential in the overall logic).
And never trust what the browser sends. It may not even be a browser.

Apache+mod_perl AAA is very powerful, and fun. It can also quickly become very messy.

Re: Set AuthName to prompt for sequential passwords

am 21.12.2010 05:14:50 von Matt Puumala

Thank you so much for the insight. Your thoughts are very
valuable. I'll be digging into the CookieAuth module to see what I can
see. After I look at it just a bit, it may be that I can just use
CookieAuth as it is, or with minor tweaks and a big authentication
routine. It would deny authentication, but set a different cookie after
"phase 1"; and grant authentication with a good "phase 1" cookie and
proper "phase 2" responses.

You'll hear from me again, as I find other questions, or if a miracle
happens and I complete the project and get something that works.

Thank you again!

Matt

On Mon, Dec 20, 2010 at 6:40 PM, Andr=E9 Warnier wrote:
>
> Talking about HTTP authentication, that's a good plan.
> Unfortunately sometimes difficult to follow, because HTTP authentication =
is
> full of twists and turns that don't usually let you do things stepwise.
>
> There is already plenty of stuff in the above paragraph to be answered.
>
> What the browser displays in the title bar of its embedded authentication
> mechanism, is nothing else than the content of the "realm" of the "auth
> required" header that it receives back from the server. So you could
> "trick" that by fabricating this header (and the 401 response) yourself,
> instead of letting Apache send it.

.... [snip]...

Re: Set AuthName to prompt for sequential passwords

am 28.12.2010 20:47:16 von David Nicol

> Matt Puumala wrote:
>>
>> Greetings!
>>
>> I am trying to make a two-factor authentication module, built on
>> AuthType Basic. (google for Perfect Paper Passwords for the scheme I'm
>> using).  To make it work, I need to be able to prompt the user to t=
ype
>> in two passwords sequentially.


my thought is that the two basic authentications would make sense at
two separate virtual domains.

Firstly, the client would authenticate to
http://step1.example.org/step1, after which they would be directed to
step2.example.org/step2/XYZABC where XYZABC is a one-time-use,
hard-to-guess code generated by step 1 and stored somewhere step2 can
see it.

step1 and step2 are different domains, the authentication starts all
over for step2, the infrastructure has now clue that they are two
steps in your process.

After passing the test at step2, the paranoia really starts.