1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* |
5
|
|
|
* This file is part of the Apix Project. |
6
|
|
|
* |
7
|
|
|
* (c) Franck Cassedanne <franck at ouarz.net> |
8
|
|
|
* |
9
|
|
|
* @license http://opensource.org/licenses/BSD-3-Clause New BSD License |
10
|
|
|
* |
11
|
|
|
*/ |
12
|
|
|
|
13
|
|
|
namespace Apix\Plugin; |
14
|
|
|
|
15
|
|
|
use Apix\Service, |
16
|
|
|
Apix\Exception; |
17
|
|
|
|
18
|
|
|
class Auth extends PluginAbstractEntity |
19
|
|
|
{ |
20
|
|
|
public static $hook = array('entity', 'early'); |
21
|
|
|
|
22
|
|
|
protected $options = array( |
23
|
|
|
// 'enable' => true, // wether to enable or not |
|
|
|
|
24
|
|
|
'adapter' => 'Apix\Plugin\Auth\Adapter', |
25
|
|
|
'public_group' => 'public', // public group to skip auth |
26
|
|
|
); |
27
|
|
|
|
28
|
|
|
protected $annotation = 'api_auth'; |
29
|
|
|
|
30
|
|
|
public function update(\SplSubject $entity) |
|
|
|
|
31
|
|
|
{ |
32
|
|
|
$this->entity = $entity; |
|
|
|
|
33
|
|
|
|
34
|
|
|
$groups = $this->getSubTagValues('groups'); |
35
|
|
|
$users = $this->getSubTagValues('users'); |
36
|
|
|
|
37
|
|
|
// skip auth if groups and users are both null |
38
|
|
|
// or if the group is public. |
39
|
|
|
if( |
40
|
|
|
null === $users |
41
|
|
|
&& null === $groups |
42
|
|
|
|| null !== $groups |
43
|
|
|
&& in_array($this->options['public_group'], $groups) |
44
|
|
|
) { |
45
|
|
|
return null; |
46
|
|
|
} |
47
|
|
|
|
48
|
|
|
$logger = Service::get('logger'); |
49
|
|
|
|
50
|
|
|
// authenticate |
51
|
|
|
if ( !$this->adapter->authenticate() ) { |
52
|
|
|
|
53
|
|
|
// $logger->info( |
54
|
|
|
// 'Login failed for "{username}"', |
55
|
|
|
// array('username' => $this->adapter->getUsername()) |
|
|
|
|
56
|
|
|
// ); |
57
|
|
|
|
58
|
|
|
$this->adapter->send(); |
59
|
|
|
|
60
|
|
|
// TODO: eventually in Auth... |
61
|
|
|
// $response = Service::get('response'); |
|
|
|
|
62
|
|
|
// $response->setHeaders($headers); |
|
|
|
|
63
|
|
|
// $response->send(); |
|
|
|
|
64
|
|
|
|
65
|
|
|
throw new Exception('Authentication required', 401); |
66
|
|
|
} |
67
|
|
|
|
68
|
|
|
// TODO: get the Session object. |
69
|
|
|
if (Service::has('session')) { |
70
|
|
|
$session = Service::get('session'); |
71
|
|
|
|
72
|
|
|
$context = array('user' => $session->getUsername()); |
73
|
|
|
|
74
|
|
|
// check the username is in the authorised list. |
75
|
|
View Code Duplication |
if (null !== $users && !in_array($context['user'], $users)) { |
|
|
|
|
76
|
|
|
|
77
|
|
|
$logger->notice('Auth: User unauthorised [{user}]', $context); |
78
|
|
|
|
79
|
|
|
throw new Exception('Access unauthorised', 401); |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
// check user group |
83
|
|
|
$context['group'] = $session->getGroup(); |
84
|
|
View Code Duplication |
if (null !== $groups && !in_array($context['group'], $groups) ) { |
|
|
|
|
85
|
|
|
|
86
|
|
|
$logger->notice( |
87
|
|
|
'Auth: Sessions\'s group unauthorised [{user}/{group}]".', |
88
|
|
|
$context |
89
|
|
|
); |
90
|
|
|
|
91
|
|
|
throw new Exception('Access unauthorised.', 401); |
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
// check for (required) trusted user IPs |
95
|
|
|
if ($session->hasTrustedIps()) { |
96
|
|
|
$context['ip'] = Service::get('response')->getRequest()->getIp(); |
97
|
|
|
if (!$this->isTrustedIp($context['ip'], $session->getTrustedIps())) { |
98
|
|
|
|
99
|
|
|
$logger->notice( |
100
|
|
|
'Auth: Session\'s IP not trusted [{user}/{group}/{ip}].', |
101
|
|
|
$context |
102
|
|
|
); |
103
|
|
|
|
104
|
|
|
throw new Exception('Session\'s IP not trusted', 401); |
105
|
|
|
} |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
// TODO: set X_REMOTE_USER or X_AUTH_USER |
109
|
|
|
$_SERVER['X_AUTH_USER'] = $context['user']; |
110
|
|
|
|
111
|
|
|
$logger->info( |
112
|
|
|
'Auth: User logged in [{user}/{group}/{ip}]', |
113
|
|
|
$context |
114
|
|
|
); |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
return true; |
118
|
|
|
} |
119
|
|
|
|
120
|
|
|
protected function isTrustedIp($ip, array $ips) |
121
|
|
|
{ |
122
|
|
|
// TODO: improve this, check IP ranges, etc... |
123
|
|
|
return in_array($ip, $ips); |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
} |
127
|
|
|
|
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.