source: LATMOS-Accounts-Web/lib/Catalyst/Authentication/Credential/La.pm @ 895

Last change on this file since 895 was 895, checked in by nanardon, 12 years ago
  • check there is Authorization header
File size: 3.5 KB
Line 
1package Catalyst::Authentication::Credential::La;
2
3use strict;
4use warnings;
5use MIME::Base64;
6
7sub new {
8    my ($class) = @_;
9    return bless({}, $class);
10}
11
12sub _search_user {
13    my ($self, $c) = @_;
14   
15    my $attribute = $c->config->{ssl}->{ATTRIBUTE_ID} || 'mail';
16    my $sslid     = $c->config->{ssl}->{SSL_ID}       || 'HTTP_SSL_CLIENT_S_DN_EMAIL';
17    my $value     = $ENV{$sslid} or do {
18        $c->log->debug("Cannot find user: ENV{$sslid} is empty");
19        return;
20    };
21
22    my $base = $c->model('Accounts')->db;
23    # quick prefilter
24    my @res = $base->search_objects(
25        'user',
26        sprintf('%s~%s', $attribute, $value)
27    );
28
29    @res = grep {
30        my $o = $base->get_object('user', $_);
31        $o && grep { lc($_) eq lc($value) } $o->get_attributes($attribute);   
32    } @res;
33
34    if (@res == 1) {
35        return $res[0];
36    } else {
37        $c->log->error(sprintf
38            "Can't identify `%s' user from `%s' attributes, multiple user found: %s",
39            $value,
40            $attribute,
41            join(', ', @res),
42        );
43        return;
44    }
45}
46
47sub _ssl_filter {
48    my ($self, $c, $realm, $authinfo) = @_;
49
50    foreach my $f (@{ $c->config->{ssl}->{filters} }) {
51        my $matchtype = $f->{op} || '=';
52        my $var = $ENV{$f->{var}};
53        if ($matchtype eq '=') {
54            do {
55                $c->log->debug(sprintf
56                    'Filter failed: %s = %s',
57                    $var, $f->{value}
58                );
59                return;
60            } unless($var eq $f->{value});
61        }
62        elsif ($matchtype eq 're') {
63            my $value = $f->{value};
64            do {
65                $c->log->debug(sprintf
66                    'Filter failed: %s match %s',
67                    $var, $f->{value}
68                );
69                return;
70            } unless($var =~ m/$value/);
71        }
72        else {
73            $c->log->error(sprintf 'Wrong filter op: %s', $matchtype);
74            return;
75        }
76    }
77
78    return 1;
79}
80
81sub _ssl_auth {
82    my ($self, $c, $realm, $authinfo) = @_;
83
84    if ($c->config->{ssl}->{filters}) {
85        if (!$self->_ssl_filter($c, $realm, $authinfo)) {
86            return;
87        }
88    }
89
90    if (my $u = $self->_search_user($c)) {
91        $c->log->info(sprintf 'SSL auth for %s', $u);
92        $authinfo->{username} = $u;
93        return 1;
94    } else {
95        return;
96    }
97}
98
99sub _login_auth {
100    my ($self, $c, $realm, $authinfo) = @_;
101    my $authheader = $c->req->headers->header('Authorization')
102        or do {
103        $c->log->debug('No Authorization header found');   
104        return;
105    };
106    # TODO check auth type
107    my ($type, $base64) = $authheader =~ /(\w+) (\S+)/;
108    ($authinfo->{username}, $authinfo->{password})
109        = decode_base64($base64) =~ /^([^:]+):(.*)/;
110   
111    if($c->model('Accounts')->db->connect(
112        $authinfo->{username},
113        $authinfo->{password}
114    )) {
115        $c->log->info(sprintf 'basic auth for %s', $authinfo->{username});
116        return $realm->find_user($authinfo)
117    } else {
118        return;
119        $c->log->error(sprintf
120            'Invalid password or user for user %s',
121            $authinfo->{username} ||
122            '(none)'
123        );
124    }
125}
126
127sub authenticate {
128    my ($self, $c, $realm, $authinfo) = @_;
129    if (! (
130        $self->_ssl_auth  ($c, $realm, $authinfo) ||
131        $self->_login_auth($c, $realm, $authinfo)
132        )) { return; }
133
134    $c->model('Accounts')->db->{_user} = $authinfo->{username};
135    return $realm->find_user($authinfo);
136}
137
1381;
Note: See TracBrowser for help on using the repository browser.