summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2010-09-01 16:58:14 -0500
committerJesse Luehrs <doy@tozt.net>2010-09-01 16:58:14 -0500
commitfe1a91cd0621e40da8d70963f9f87ca50453f7ee (patch)
tree5a9698a9491965ea5588af4ef53ecf18372d32cb
parent8be747a4fb3d67af1722d6d8f20f20fe41565387 (diff)
downloadplack-middleware-auth-htpasswd-fe1a91cd0621e40da8d70963f9f87ca50453f7ee.tar.gz
plack-middleware-auth-htpasswd-fe1a91cd0621e40da8d70963f9f87ca50453f7ee.zip
initial (untested) implementation
-rw-r--r--dist.ini4
-rw-r--r--lib/Plack/Middleware/Auth/Htpasswd.pm81
2 files changed, 85 insertions, 0 deletions
diff --git a/dist.ini b/dist.ini
index 5e0580a..1684e85 100644
--- a/dist.ini
+++ b/dist.ini
@@ -7,3 +7,7 @@ copyright_holder = Jesse Luehrs
dist = Plack-Middleware-Auth-Htpasswd
[Prereq]
+Authen::Htpasswd = 0
+MIME::Base64 = 0
+Path::Class = 0
+Plack = 0
diff --git a/lib/Plack/Middleware/Auth/Htpasswd.pm b/lib/Plack/Middleware/Auth/Htpasswd.pm
index e69de29..087efa3 100644
--- a/lib/Plack/Middleware/Auth/Htpasswd.pm
+++ b/lib/Plack/Middleware/Auth/Htpasswd.pm
@@ -0,0 +1,81 @@
+package Plack::Middleware::Auth::Htpasswd;
+use strict;
+use warnings;
+use base 'Plack::Middleware';
+use Plack::Util::Accessor qw(realm file file_root);
+use Plack::Request;
+
+use Authen::Htpasswd;
+use MIME::Base64;
+use Path::Class;
+
+sub prepare_app {
+ my $self = shift;
+ die "must specify either file or file_root"
+ unless defined $self->file || $self->file_root;
+}
+
+sub call {
+ my($self, $env) = @_;
+ my $auth = $env->{HTTP_AUTHORIZATION};
+ return $self->unauthorized
+ unless $auth && $auth =~ /^Basic (.*)$/;
+
+ my $auth_string = $1;
+ my ($user, $pass) = split /:/, (MIME::Base64::decode($auth_string) || ":");
+ $pass = '' unless defined $pass;
+
+ if ($self->authenticate($env, $user, $pass)) {
+ $env->{REMOTE_USER} = $user;
+ return $self->app->($env);
+ }
+ else {
+ return $self->unauthorized;
+ }
+}
+
+sub _check_password {
+ my $self = shift;
+ my ($file, $user, $pass) = @_;
+ return Authen::Htpasswd->new($file)->check_user_password($user, $pass);
+}
+
+sub authenticate {
+ my $self = shift;
+ my ($env, $user, $pass) = @_;
+
+ return $self->_check_password($self->file, $user, $pass)
+ if defined $self->file;
+
+ my $req = Plack::Request->new($env);
+ my $dir = dir($self->file_root);
+ my @htpasswd = reverse
+ map { $_->file('.htpasswd')->stringify }
+ map { $dir = $dir->subdir($_) }
+ split m{/}, $req->path;
+
+ for my $htpasswd (@htpasswd) {
+ next unless -f $htpasswd && -r _;
+ return $self->_check_password($htpasswd, $user, $pass);
+ }
+
+ return;
+}
+
+sub unauthorized {
+ my $self = shift;
+ my $body = 'Authorization required';
+ return [
+ 401,
+ [
+ 'Content-Type' => 'text/plain',
+ 'Content-Length' => length $body,
+ 'WWW-Authenticate' => 'Basic realm="'
+ . ($self->realm || "restricted area")
+ . '"'
+ ],
+ [ $body ],
+ ];
+}
+
+1;