Initial revision
[OpenSRF.git] / src / perlmods / OpenSRF / DOM / Element / userAuth.pm
1 package OpenSRF::DOM::Element::userAuth;
2 use OpenSRF::DOM;
3 use OpenSRF::Utils::Logger qw/:level/;
4 use OpenSRF::Utils::Config;
5 use Digest::MD5 qw/md5_hex/;
6 use OpenSRF::DomainObject::oilsMethod;
7 use OpenSRF::DomainObject::oilsResponse;
8 use OpenSRF::App::Auth;
9 use OpenSRF::EX qw/:try/;
10 use OpenSRF::Utils::Cache;
11
12 use base 'OpenSRF::DOM::Element';
13
14 my $log = 'OpenSRF::Utils::Logger';
15
16 =head1 NAME
17
18 OpenSRF::DOM::Element::userAuth
19
20 =over 4
21
22 User authentication data structure for use in oilsMessage objects.
23
24 =back
25
26 =head1 SYNOPSIS
27
28  use OpenSRF::DOM::Element::userAuth;
29
30  %auth_structure = ( userid   => '0123456789', secret => 'junko' );
31  %auth_structure = ( username => 'miker',      secret => 'junko' );
32
33  my $auth = OpenSRF::DOM::Element::userAuth->new( %auth_structure );
34
35 ...
36
37  my %server_auth = ( sysname    => 'OPACServer',
38                      secret     => 'deadbeefdeadbeef' );
39
40  my $auth = OpenSRF::DOM::Element::userAuth->new( %server_auth );
41
42 =cut
43
44 sub new {
45         my $class = shift;
46         $class = ref($class) || $class;
47
48         my %args = @_;
49
50         $args{hashseed} ||= int( rand( $$ ) );
51
52         $args{secret} = md5_hex($args{secret});
53         $args{secret} = md5_hex($args{hashseed}. $args{secret});
54
55         return $class->SUPER::new( %args );
56 }
57
58 sub username {
59         my $self = shift;
60         return $self->getAttribute('username');
61 }
62
63 sub userid {
64         my $self = shift;
65         return $self->getAttribute('userid');
66 }
67
68 sub sysname {
69         my $self = shift;
70         return $self->getAttribute('sysname');
71 }
72
73 sub secret {
74         my $self = shift;
75         return $self->getAttribute('secret');
76 }
77
78 sub hashseed {
79         my $self = shift;
80         return $self->getAttribute('hashseed');
81 }
82
83 sub authenticate {
84         my $self = shift;
85         my $session = shift;
86         my $u = $self->username ||
87                 $self->userid ||
88                 $self->sysname;
89         $log->debug("Authenticating user [$u]",INFO);
90
91
92         # We need to make sure that we are not the auth server.  If we are,
93         # we don't want to send a request to ourselves.  Instead just call
94         # the local auth method.
95         my @params = ( $u, $self->secret, $self->hashseed );
96         my $res;
97
98         # ------------------------------
99         # See if we can auth with the cache first
100         $log->debug( "Attempting cache auth...", INTERNAL );
101         my $cache = OpenSRF::Utils::Cache->current("user"); 
102         my $value = $cache->get( $u );
103
104         if( $value  and $value eq $self->secret ) {
105                 $log->debug( "User $u is cached and authenticated", INTERNAL );
106                 return 1;
107         }
108         # ------------------------------
109
110         if( $session->service eq "auth" ) {
111                 $log->debug( "We are AUTH. calling local auth", DEBUG ); 
112                 my $meth = OpenSRF::App::Auth->method_lookup('authenticate', 1);
113                 $log->debug("Meth ref is $meth", INTERNAL);
114                 $res = $meth->run( 1, @params );
115
116         } else { 
117                 $log->debug( "Calling AUTH server", DEBUG );    
118                 $res = _request_remote_auth( $session, @params ); 
119         }
120
121
122         if( $res and $res->class->isa('OpenSRF::DomainObject::oilsResult') and 
123                         $res->content and ($res->content->value eq "yes") ) {
124
125                 $log->debug( "User $u is authenticated", DEBUG );
126                 $log->debug( "Adding $u to cache", INTERNAL );
127
128                 # Add to the cache ------------------------------
129                 $cache->set( $u, $self->secret ); 
130
131                 return 1;
132
133         } else { 
134                 return 0; 
135         }
136         
137
138
139 sub _request_remote_auth {
140
141         my $server_session = shift;
142         my @params = @_;
143
144         my $service = $server_session->service;
145
146         my @server_auth = (sysname => OpenSRF::Utils::Config->current->$service->sysname,
147                            secret  => OpenSRF::Utils::Config->current->$service->secret );
148
149         my $session = OpenSRF::AppSession->create( "auth", @server_auth ); 
150
151         $log->debug( "Sending request to auth server", INTERNAL );
152         
153         my $req; my $res;
154
155         try {
156
157                 if( ! $session->connect() ) {
158                         throw OpenSRF::EX::CRITICAL ("Cannot communicate with auth server");
159                 }
160                 $req = $session->request( authenticate => @params );
161                 $req->wait_complete( OpenSRF::Utils::Config->current->client->connect_timeout );
162                 $res = $req->recv(); 
163
164         } catch OpenSRF::DomainObject::oilsAuthException with {
165                 return 0;
166
167         } finally {
168                 $req->finish() if $req;
169                 $session->finish() if $session;
170         };
171
172         return $res;
173
174 }
175
176
177
178 1;