1# $Id: /mirror/gungho/lib/Gungho/Component/Authentication/Basic.pm 1736 2007-05-15T09:58:12.998753Z lestrrat  $
2#
3# Copyright (c) 2007 Daisuke Maki <daisuke@endworks.jp>
4# All rights reserved.
5
6package Gungho::Component::Authentication::Basic;
7use strict;
8use warnings;
9use base qw(Gungho::Component::Authentication);
10use MIME::Base64 ();
11use URI;
12
13__PACKAGE__->mk_classdata($_) for qw(basic_authentication);
14
15sub setup
16{
17    my $self = shift;
18    $self->basic_authentication({});
19
20    my $list = $self->config->{credentials}{basic};
21    if ($list) {
22        foreach my $conf (@$list) {
23            $self->set_basic_credentials(@$conf);
24        }
25    }
26
27    $self->next::method(@_);
28}
29
30sub authenticate
31{
32    my ($self, $proxy, $auth_param, $req, $res) = @_;
33
34    my ($user, $pass) = $self->get_basic_credentials($req->url, $auth_param->{realm});
35
36    return 0 unless defined $user and defined $pass;
37
38    my $auth_header = $proxy ? "Proxy-Authorization" : "Authorization";
39    my $auth_value = "Basic " . MIME::Base64::encode("$user:$pass", "");
40
41    # Check if this is a repeated fialure to auth
42    my $r = $res;
43    while ($r) {
44        my $auth = $r->request->header($auth_header);
45        if ($auth && $auth eq $auth_value) {
46            # here we know this failed before
47            $res->header("Client-Warning" =>
48                  "Credentials for '$user' failed before");
49            return 0;
50        }
51        $r = $r->previous;
52    }
53
54    my $referral = $req->clone;
55    $referral->header($auth_header => $auth_value);
56
57    $self->send_request($referral);
58    return 1;
59}
60
61sub set_basic_credentials
62{
63    my $self = shift;
64    my ($uri, $realm, $uid, $pass) = @_;
65
66    if (! eval { $uri->isa('URI') }) {
67        $uri = URI->new($uri);
68    }
69
70    $self->basic_authentication()->{lc ($uri->host_port)}{$realm} = [$uid, $pass];
71}
72
73sub get_basic_credentials
74{
75    my $self = shift;
76    my ($uri, $realm) = @_;
77
78    if (! eval { $uri->isa('URI') }) {
79        $uri = URI->new($uri);
80    }
81
82    if (exists $self->basic_authentication()->{lc($uri->host_port)}{$realm}) {
83        return @{$self->basic_authentication()->{lc($uri->host_port)}{$realm}};
84    }
85    return (undef, undef);
86}
87
881;
89
90__END__
91
92=head1 NAME
93
94Gungho::Component::Authentication::Basic - Add Basic Auth To Gungho
95
96=head1 SYNOPSIS
97
98  ---
99  components:
100    - Authentication::Basic
101  credentials:
102    basic:
103      -
104        - http://example.com
105        - "Admin Only"
106        - username
107        - password
108      -
109        - http://example2.com
110        - "Admin Only"
111        - username2
112        - password2
113
114=head1 DESCRIPTION
115
116This module adds the capability to store basic authentication information
117inside Gungho.
118
119=head1 METHODS
120
121=head2 setup($c)
122
123Sets up the component
124
125=head2 authenticate($is_proxy, $realm, $request, $response)
126
127Does the WWW Authentication and redispatches the request
128
129=head2 set_basic_credentials($uri, $realm, $uid, $pass)
130
131Sets the credentials for a uri + realm.
132
133=head2 get_basic_credentials($uri, $realm)
134
135Get the credentials for a uri + realm.
136
137=head1 CAVEATS
138
139This component merely stores data in Gungho that can be used for authentication.
140The Engine type that Gungho is currently using must respect the information.
141
142=cut