0013326: use userid@instancename and for email account name
[tine20] / tests / tine20 / Tinebase / AuthTest.php
1 <?php
2 /**
3  * Tine 2.0 - http://www.tine20.org
4  * 
5  * @package     Tinebase
6  * @subpackage  Auth
7  * @license     http://www.gnu.org/licenses/agpl.html
8  * @copyright   Copyright (c) 2009-2016 Metaways Infosystems GmbH (http://www.metaways.de)
9  * @author      Jonas Fischer <j.fischer@metaways.de>
10  * 
11  * @todo        split this
12  */
13
14 /**
15  * Test helper
16  */
17 require_once dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'TestHelper.php';
18
19 /**
20  * Test class for Tinebase_Auth_Abstract
21  */
22 class Tinebase_AuthTest extends TestCase
23 {
24     /**
25      * @var array test objects
26      */
27     protected $_objects = array();
28     
29     /**
30      * @var mixed
31      */
32     protected $_originalBackendConfiguration = null;
33     
34     /**
35      * @var mixed
36      */
37     protected $_originalBackendType = null;
38
39     /**
40      * Sets up the fixture.
41      * This method is called before a test is executed.
42      *
43      * @access protected
44      */
45     protected function setUp()
46     {
47         parent::setUp();
48
49         $this->_originalBackendConfiguration = Tinebase_Auth::getBackendConfiguration();
50         $this->_originalBackendType = Tinebase_Auth::getConfiguredBackend();
51     }
52
53     /**
54      * Tears down the fixture
55      * This method is called after a test is executed.
56      *
57      * @access protected
58      */
59     protected function tearDown()
60     {
61         // this needs to be done because Tinebase_Auth & Tinebase_Config use caching mechanisms
62         Tinebase_Auth::setBackendType($this->_originalBackendType);
63         Tinebase_Auth::deleteBackendConfiguration();
64         Tinebase_Auth::setBackendConfiguration($this->_originalBackendConfiguration);
65         Tinebase_Auth::saveBackendConfiguration();
66         Tinebase_Auth::getInstance()->setBackend();
67         
68         parent::tearDown();
69     }
70
71     /**
72      * testSaveBackendConfiguration
73      */
74     public function testSaveBackendConfiguration()
75     {
76         Tinebase_Auth::setBackendType(Tinebase_Auth::LDAP);
77      
78         $rawConfigBefore = Tinebase_Config::getInstance()->get(Tinebase_Config::AUTHENTICATIONBACKEND);
79         $key = 'host';
80         $testValue = 'phpunit-test-host2';
81         Tinebase_Auth::setBackendConfiguration($testValue, $key);
82         Tinebase_Auth::saveBackendConfiguration();
83         $rawConfigAfter = Tinebase_Config::getInstance()->get(Tinebase_Config::AUTHENTICATIONBACKEND);
84         $this->assertNotEquals($rawConfigBefore, $rawConfigAfter);
85     }
86     
87     /**
88      * 
89      * testSetBackendConfiguration
90      */
91     public function testSetBackendConfiguration()
92     {
93         Tinebase_Auth::setBackendType(Tinebase_Auth::LDAP);
94      
95         $key = 'host';
96         $testValue = 'phpunit-test-host';
97         Tinebase_Auth::setBackendConfiguration($testValue, $key);
98         $this->assertEquals($testValue, Tinebase_Auth::getBackendConfiguration($key));
99
100         $testValues = array('host' => 'phpunit-test-host2',
101            'username' => 'cn=testcn,ou=teestou,o=testo',
102            'password' => 'secret'
103         );
104         Tinebase_Auth::setBackendConfiguration($testValues);
105         foreach ($testValues as $key => $testValue) {
106             $this->assertEquals($testValue, Tinebase_Auth::getBackendConfiguration($key));
107         }
108     }
109     
110     /**
111      * testDeleteBackendConfiguration
112      */
113     public function testDeleteBackendConfiguration()
114     {
115         Tinebase_Auth::setBackendType(Tinebase_Auth::LDAP);
116      
117         $key = 'host';
118         Tinebase_Auth::setBackendConfiguration('configured-host', $key);
119         $this->assertEquals('configured-host', Tinebase_Auth::getBackendConfiguration($key, 'default-host'));
120         Tinebase_Auth::deleteBackendConfiguration($key);
121         $this->assertEquals('default-host', Tinebase_Auth::getBackendConfiguration($key, 'default-host'));
122         
123         $configOptionsCount = count(Tinebase_Auth::getBackendConfiguration());
124         Tinebase_Auth::deleteBackendConfiguration('non-existing-key');
125         $this->assertEquals($configOptionsCount, count(Tinebase_Auth::getBackendConfiguration()));
126         
127         Tinebase_Auth::setBackendConfiguration('phpunit-dummy-value', $key);
128         $this->assertTrue(count(Tinebase_Auth::getBackendConfiguration()) > 0);
129         Tinebase_Auth::deleteBackendConfiguration();
130         $this->assertTrue(count(Tinebase_Auth::getBackendConfiguration()) == 0);
131     }
132     
133     /**
134      * testGetBackendConfigurationDefaults
135      */
136     public function testGetBackendConfigurationDefaults()
137     {
138         $defaults = Tinebase_Auth::getBackendConfigurationDefaults();
139         $this->assertTrue((isset($defaults[Tinebase_Auth::SQL]) || array_key_exists(Tinebase_Auth::SQL, $defaults)));
140         $this->assertTrue((isset($defaults[Tinebase_Auth::LDAP]) || array_key_exists(Tinebase_Auth::LDAP, $defaults)));
141         $this->assertTrue(is_array($defaults[Tinebase_Auth::LDAP]));
142         $this->assertFalse((isset($defaults['host']) || array_key_exists('host', $defaults)));
143         
144         $defaults = Tinebase_Auth::getBackendConfigurationDefaults(Tinebase_Auth::LDAP);
145         $this->assertTrue((isset($defaults['host']) || array_key_exists('host', $defaults)));
146         $this->assertFalse((isset($defaults[Tinebase_Auth::LDAP]) || array_key_exists(Tinebase_Auth::LDAP, $defaults)));
147     }
148     
149     /**
150      * test imap authentication
151      */
152     public function testImapAuth()
153     {
154         self::markTestSkipped('FIXME 0013338: repair some failing email tests ');
155
156         // use imap config for the auth config
157         $imapConfig = Tinebase_Config::getInstance()->get(Tinebase_Config::IMAP, new Tinebase_Config_Struct())->toArray();
158         
159         if (empty($imapConfig)) {
160              $this->markTestSkipped('No IMAP config found.');
161         }
162         
163         $authConfig = array(
164             'host'      => $imapConfig['host'],
165             'port'      => $imapConfig['port'],
166             'ssl'       => $imapConfig['ssl'],
167             'domain'    => $imapConfig['domain'],
168         );
169         Tinebase_Auth::setBackendType(Tinebase_Auth::IMAP);
170         Tinebase_Auth::setBackendConfiguration($authConfig);
171         Tinebase_Auth::saveBackendConfiguration();
172         Tinebase_Auth::getInstance()->setBackend();
173         
174         $this->assertEquals(Tinebase_Auth::IMAP, Tinebase_Auth::getConfiguredBackend());
175
176         $testCredentials = TestServer::getInstance()->getTestCredentials();
177         
178         // valid authentication
179         $authResult = Tinebase_Auth::getInstance()->authenticate($testCredentials['username'], $testCredentials['password']);
180         $this->assertTrue($authResult->isValid(), 'could not authenticate with imap');
181         
182         // invalid authentication
183         $authResult = Tinebase_Auth::getInstance()->authenticate($testCredentials['username'], 'some pw');
184         $this->assertFalse($authResult->isValid());
185         $this->assertEquals(Tinebase_Auth::FAILURE_CREDENTIAL_INVALID, $authResult->getCode());
186         $this->assertEquals(array('Invalid credentials for user ' . $this->_getEmailAddress(), ''), $authResult->getMessages());
187     }
188     
189     /**
190      * test credential cache cleanup
191      */
192     public function testClearCredentialCacheTable()
193     {
194         // add dummy record to credential cache
195         $id = Tinebase_Record_Abstract::generateUID();
196         $db = Tinebase_Core::getDb();
197         $oneMinuteAgo = Tinebase_DateTime::now()->subMinute(1)->format(Tinebase_Record_Abstract::ISO8601LONG);
198         $data = array(
199             'id'            => $id,
200             'cache'         => Tinebase_Record_Abstract::generateUID(),
201             'creation_time' => $oneMinuteAgo,
202             'valid_until'   => $oneMinuteAgo,
203         );
204         $table = SQL_TABLE_PREFIX . 'credential_cache';
205         Tinebase_Core::getDb()->insert($table, $data);
206         
207         Tinebase_Auth_CredentialCache::getInstance()->clearCacheTable();
208         
209         $result = $db->fetchCol('SELECT id FROM ' . $db->quoteIdentifier($table) . ' WHERE ' . $db->quoteInto($db->quoteIdentifier('valid_until') .' < ?', Tinebase_DateTime::now()->format(Tinebase_Record_Abstract::ISO8601LONG)));
210         $this->assertNotContains($id, $result);
211     }
212
213     /**
214      * @see 0011366: support privacyIdea authentication
215      */
216     public function testSecondFactor()
217     {
218         $result = Tinebase_Auth::validateSecondFactor('phil', 'phil', array(
219             'active' => true,
220             'provider' => 'Mock',
221             'url' => 'https://localhost/validate/check',
222         ));
223         $this->assertEquals(Tinebase_Auth::SUCCESS, $result);
224     }
225
226     /**
227      * @see 0013272: add pin column, backend and config
228      */
229     public function testSecondFactorTine20()
230     {
231         $user = Tinebase_Core::getUser();
232         Tinebase_User::getInstance()->setPin($user, '1234');
233         $result = Tinebase_Auth::validateSecondFactor($user->accountLoginName, '1234', array(
234             'active' => true,
235             'provider' => 'Tine20',
236         ));
237         $this->assertEquals(Tinebase_Auth::SUCCESS, $result);
238     }
239
240     /**
241      * @see 0013328: protect applications with second factor
242      */
243     public function testSecondFactorAppProtection()
244     {
245         // set configs
246         Tinebase_Config::getInstance()->set(Tinebase_Config::SECONDFACTORPROTECTEDAPPS, array(
247             'Tasks'
248         ));
249         Tinebase_Config::getInstance()->set(Tinebase_Config::AUTHENTICATIONSECONDFACTOR, array(
250             'active' => true,
251             'provider' => 'Tine20',
252         ));
253
254         // set pin
255         $user = Tinebase_Core::getUser();
256         Tinebase_User::getInstance()->setPin($user, '1234');
257
258         // try to access app
259         try {
260             $tasks = Tasks_Controller_Task::getInstance()->getAll();
261             self::fail('it should not be possible to access app without PIN');
262         } catch (Tinebase_Exception $te) {
263             // check exception
264             self::assertTrue($te instanceof Tinebase_Exception_SecondFactorRequired);
265         }
266
267         // validate pin
268         $json = new Tinebase_Frontend_Json();
269         $json->validateSecondFactor('1234');
270
271         // try to access app again
272         $result = Tasks_Controller_Task::getInstance()->getAll();
273         self::assertGreaterThanOrEqual(0, count($result));
274     }
275 }