1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/signin/easy_unlock_auth_attempt.h"
7 #include "base/macros.h"
8 #include "chrome/browser/signin/easy_unlock_app_manager.h"
9 #include "chrome/browser/signin/screenlock_bridge.h"
10 #include "testing/gtest/include/gtest/gtest.h"
12 #if defined(OS_CHROMEOS)
13 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.h"
18 // Fake user ids used in tests.
19 const char kTestUser1
[] = "user1";
20 const char kTestUser2
[] = "user2";
22 #if defined(OS_CHROMEOS)
23 const unsigned char kSecret
[] = {
24 0x7c, 0x85, 0x82, 0x7d, 0x00, 0x1f, 0x6a, 0x29, 0x2f, 0xc4, 0xb5, 0x60,
25 0x08, 0x9b, 0xb0, 0x5b
29 const unsigned char kSessionKey
[] = {
30 0xc3, 0xd9, 0x83, 0x16, 0x52, 0xde, 0x99, 0xd7, 0x4e, 0x60, 0xf9, 0xec,
31 0xa8, 0x9c, 0x0e, 0xbe
34 const unsigned char kWrappedSecret
[] = {
35 0x3a, 0xea, 0x51, 0xd9, 0x64, 0x64, 0xe1, 0xcd, 0xd8, 0xee, 0x99, 0xf5,
36 0xb1, 0xd4, 0x9f, 0xc4, 0x28, 0xd6, 0xfd, 0x69, 0x0b, 0x9e, 0x06, 0x21,
37 0xfc, 0x40, 0x1f, 0xeb, 0x75, 0x64, 0x52, 0xd8
40 #if defined(OS_CHROMEOS)
41 std::string
GetSecret() {
42 return std::string(reinterpret_cast<const char*>(kSecret
),
47 std::string
GetWrappedSecret() {
48 return std::string(reinterpret_cast<const char*>(kWrappedSecret
),
49 arraysize(kWrappedSecret
));
52 std::string
GetSessionKey() {
53 return std::string(reinterpret_cast<const char*>(kSessionKey
),
54 arraysize(kSessionKey
));
57 // Fake app manager used by the EasyUnlockAuthAttempt during tests.
58 // It tracks screenlockPrivate.onAuthAttempted events.
59 class FakeAppManager
: public EasyUnlockAppManager
{
62 : auth_attempt_count_(0u), auth_attempt_should_fail_(false) {}
63 ~FakeAppManager() override
{}
65 void EnsureReady(const base::Closure
& ready_callback
) override
{
66 ADD_FAILURE() << "Not reached";
69 void LaunchSetup() override
{ ADD_FAILURE() << "Not reached"; }
71 void LoadApp() override
{ ADD_FAILURE() << "Not reached"; }
73 void DisableAppIfLoaded() override
{ ADD_FAILURE() << "Not reached"; }
75 void ReloadApp() override
{ ADD_FAILURE() << "Not reached"; }
77 bool SendUserUpdatedEvent(const std::string
& user_id
,
79 bool data_ready
) override
{
80 ADD_FAILURE() << "Not reached";
84 bool SendAuthAttemptEvent() override
{
85 ++auth_attempt_count_
;
86 return !auth_attempt_should_fail_
;
89 size_t auth_attempt_count() const { return auth_attempt_count_
; }
91 void set_auth_attempt_should_fail(bool value
) {
92 auth_attempt_should_fail_
= value
;
96 size_t auth_attempt_count_
;
97 bool auth_attempt_should_fail_
;
99 DISALLOW_COPY_AND_ASSIGN(FakeAppManager
);
102 // Fake lock handler to be used in these tests.
103 class TestLockHandler
: public ScreenlockBridge::LockHandler
{
105 // The state of unlock/signin procedure.
108 STATE_ATTEMPTING_UNLOCK
,
109 STATE_UNLOCK_CANCELED
,
111 STATE_ATTEMPTING_SIGNIN
,
112 STATE_SIGNIN_CANCELED
,
116 explicit TestLockHandler(const std::string
& user_id
)
117 : state_(STATE_NONE
), auth_type_(USER_CLICK
), user_id_(user_id
) {}
119 ~TestLockHandler() override
{}
121 void set_state(AuthState value
) { state_
= value
; }
122 AuthState
state() const { return state_
; }
124 // Changes the user associated with the lock handler.
125 // Caller should make sure that |state_| is also appropriately updated.
126 void set_user_id(const std::string
& value
) { user_id_
= value
; }
128 // Sets the secret that is expected to be sent to |AttemptEasySignin|
129 void set_expected_secret(const std::string
& value
) {
130 expected_secret_
= value
;
133 // Not using |SetAuthType| to make sure it's not called during tests.
134 void set_auth_type(AuthType value
) { auth_type_
= value
; }
136 // ScreenlockBridge::LockHandler implementation:
137 void ShowBannerMessage(const base::string16
& message
) override
{
138 ADD_FAILURE() << "Should not be reached.";
141 void ShowUserPodCustomIcon(
142 const std::string
& user_email
,
143 const ScreenlockBridge::UserPodCustomIconOptions
& icon
) override
{
144 ADD_FAILURE() << "Should not be reached.";
147 void HideUserPodCustomIcon(const std::string
& user_email
) override
{
148 ADD_FAILURE() << "Should not be reached.";
151 void EnableInput() override
{
152 ASSERT_EQ(STATE_ATTEMPTING_UNLOCK
, state_
);
153 state_
= STATE_UNLOCK_CANCELED
;
156 void SetAuthType(const std::string
& user_email
,
158 const base::string16
& auth_value
) override
{
159 ADD_FAILURE() << "Should not be reached.";
162 AuthType
GetAuthType(const std::string
& user_email
) const override
{
166 ScreenType
GetScreenType() const override
{
167 // Return an arbitrary value; this is not used by the test code.
171 void Unlock(const std::string
& user_email
) override
{
172 ASSERT_EQ(user_id_
, user_email
);
173 ASSERT_EQ(STATE_ATTEMPTING_UNLOCK
, state_
);
174 state_
= STATE_UNLOCK_DONE
;
177 void AttemptEasySignin(const std::string
& user_email
,
178 const std::string
& secret
,
179 const std::string
& key_label
) override
{
180 #if defined(OS_CHROMEOS)
181 ASSERT_EQ(user_id_
, user_email
);
183 ASSERT_EQ(STATE_ATTEMPTING_SIGNIN
, state_
);
184 if (secret
.empty()) {
185 state_
= STATE_SIGNIN_CANCELED
;
187 ASSERT_EQ(expected_secret_
, secret
);
188 ASSERT_EQ(chromeos::EasyUnlockKeyManager::GetKeyLabel(0u), key_label
);
189 state_
= STATE_SIGNIN_DONE
;
191 #else // if !defined(OS_CHROMEOS)
192 ADD_FAILURE() << "Should not be reached.";
199 std::string user_id_
;
200 std::string expected_secret_
;
202 DISALLOW_COPY_AND_ASSIGN(TestLockHandler
);
205 class EasyUnlockAuthAttemptUnlockTest
: public testing::Test
{
207 EasyUnlockAuthAttemptUnlockTest() {}
208 ~EasyUnlockAuthAttemptUnlockTest() override
{}
210 void SetUp() override
{
211 app_manager_
.reset(new FakeAppManager());
212 auth_attempt_
.reset(new EasyUnlockAuthAttempt(
213 app_manager_
.get(), kTestUser1
, EasyUnlockAuthAttempt::TYPE_UNLOCK
,
214 EasyUnlockAuthAttempt::FinalizedCallback()));
217 void TearDown() override
{
218 ScreenlockBridge::Get()->SetLockHandler(NULL
);
219 auth_attempt_
.reset();
223 void InitScreenLock() {
224 lock_handler_
.reset(new TestLockHandler(kTestUser1
));
225 lock_handler_
->set_state(TestLockHandler::STATE_ATTEMPTING_UNLOCK
);
226 ScreenlockBridge::Get()->SetLockHandler(lock_handler_
.get());
229 scoped_ptr
<EasyUnlockAuthAttempt
> auth_attempt_
;
230 scoped_ptr
<FakeAppManager
> app_manager_
;
231 scoped_ptr
<TestLockHandler
> lock_handler_
;
234 DISALLOW_COPY_AND_ASSIGN(EasyUnlockAuthAttemptUnlockTest
);
237 TEST_F(EasyUnlockAuthAttemptUnlockTest
, StartWhenNotLocked
) {
238 ASSERT_FALSE(ScreenlockBridge::Get()->IsLocked());
240 EXPECT_FALSE(auth_attempt_
->Start());
241 EXPECT_EQ(0u, app_manager_
->auth_attempt_count());
244 TEST_F(EasyUnlockAuthAttemptUnlockTest
, StartWhenAuthTypeIsPassword
) {
246 ASSERT_TRUE(ScreenlockBridge::Get()->IsLocked());
247 ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_UNLOCK
, lock_handler_
->state());
249 lock_handler_
->set_auth_type(ScreenlockBridge::LockHandler::OFFLINE_PASSWORD
);
251 EXPECT_FALSE(auth_attempt_
->Start());
253 EXPECT_EQ(0u, app_manager_
->auth_attempt_count());
254 EXPECT_EQ(TestLockHandler::STATE_UNLOCK_CANCELED
, lock_handler_
->state());
257 TEST_F(EasyUnlockAuthAttemptUnlockTest
,
258 StartWhenDispatchingAuthAttemptEventFails
) {
260 ASSERT_TRUE(ScreenlockBridge::Get()->IsLocked());
261 ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_UNLOCK
, lock_handler_
->state());
263 app_manager_
->set_auth_attempt_should_fail(true);
265 EXPECT_FALSE(auth_attempt_
->Start());
267 EXPECT_EQ(1u, app_manager_
->auth_attempt_count());
268 EXPECT_EQ(TestLockHandler::STATE_UNLOCK_CANCELED
, lock_handler_
->state());
271 TEST_F(EasyUnlockAuthAttemptUnlockTest
, ResetBeforeFinalizeUnlock
) {
273 ASSERT_TRUE(ScreenlockBridge::Get()->IsLocked());
274 ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_UNLOCK
, lock_handler_
->state());
276 ASSERT_TRUE(auth_attempt_
->Start());
278 ASSERT_EQ(1u, app_manager_
->auth_attempt_count());
279 EXPECT_EQ(TestLockHandler::STATE_ATTEMPTING_UNLOCK
, lock_handler_
->state());
281 auth_attempt_
.reset();
283 EXPECT_EQ(TestLockHandler::STATE_UNLOCK_CANCELED
, lock_handler_
->state());
286 TEST_F(EasyUnlockAuthAttemptUnlockTest
, FinalizeUnlockFailure
) {
288 ASSERT_TRUE(ScreenlockBridge::Get()->IsLocked());
289 ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_UNLOCK
, lock_handler_
->state());
291 ASSERT_TRUE(auth_attempt_
->Start());
293 ASSERT_EQ(1u, app_manager_
->auth_attempt_count());
294 EXPECT_EQ(TestLockHandler::STATE_ATTEMPTING_UNLOCK
, lock_handler_
->state());
296 auth_attempt_
->FinalizeUnlock(kTestUser1
, false);
298 EXPECT_EQ(TestLockHandler::STATE_UNLOCK_CANCELED
, lock_handler_
->state());
301 TEST_F(EasyUnlockAuthAttemptUnlockTest
, FinalizeSigninCalled
) {
303 ASSERT_TRUE(ScreenlockBridge::Get()->IsLocked());
304 ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_UNLOCK
, lock_handler_
->state());
306 ASSERT_TRUE(auth_attempt_
->Start());
308 ASSERT_EQ(1u, app_manager_
->auth_attempt_count());
309 EXPECT_EQ(TestLockHandler::STATE_ATTEMPTING_UNLOCK
, lock_handler_
->state());
311 // Wrapped secret and key should be irrelevant in this case.
312 auth_attempt_
->FinalizeSignin(kTestUser1
, GetWrappedSecret(),
315 EXPECT_EQ(TestLockHandler::STATE_UNLOCK_CANCELED
, lock_handler_
->state());
318 TEST_F(EasyUnlockAuthAttemptUnlockTest
, UnlockSucceeds
) {
320 ASSERT_TRUE(ScreenlockBridge::Get()->IsLocked());
321 ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_UNLOCK
, lock_handler_
->state());
323 ASSERT_TRUE(auth_attempt_
->Start());
325 ASSERT_EQ(1u, app_manager_
->auth_attempt_count());
326 EXPECT_EQ(TestLockHandler::STATE_ATTEMPTING_UNLOCK
, lock_handler_
->state());
328 auth_attempt_
->FinalizeUnlock(kTestUser1
, true);
330 ASSERT_EQ(TestLockHandler::STATE_UNLOCK_DONE
, lock_handler_
->state());
333 TEST_F(EasyUnlockAuthAttemptUnlockTest
, FinalizeUnlockCalledForWrongUser
) {
335 ASSERT_TRUE(ScreenlockBridge::Get()->IsLocked());
336 ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_UNLOCK
, lock_handler_
->state());
338 ASSERT_TRUE(auth_attempt_
->Start());
340 ASSERT_EQ(1u, app_manager_
->auth_attempt_count());
341 EXPECT_EQ(TestLockHandler::STATE_ATTEMPTING_UNLOCK
, lock_handler_
->state());
343 auth_attempt_
->FinalizeUnlock(kTestUser2
, true);
345 // If FinalizeUnlock is called for an incorrect user, it should be ignored
346 // rather than cancelling the authentication.
347 ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_UNLOCK
, lock_handler_
->state());
349 // When FinalizeUnlock is called for the correct user, it should work as
351 auth_attempt_
->FinalizeUnlock(kTestUser1
, true);
353 ASSERT_EQ(TestLockHandler::STATE_UNLOCK_DONE
, lock_handler_
->state());
356 #if defined(OS_CHROMEOS)
357 class EasyUnlockAuthAttemptSigninTest
: public testing::Test
{
359 EasyUnlockAuthAttemptSigninTest() {}
360 ~EasyUnlockAuthAttemptSigninTest() override
{}
362 void SetUp() override
{
363 app_manager_
.reset(new FakeAppManager());
364 auth_attempt_
.reset(new EasyUnlockAuthAttempt(
365 app_manager_
.get(), kTestUser1
, EasyUnlockAuthAttempt::TYPE_SIGNIN
,
366 EasyUnlockAuthAttempt::FinalizedCallback()));
369 void TearDown() override
{
370 ScreenlockBridge::Get()->SetLockHandler(NULL
);
371 auth_attempt_
.reset();
375 void InitScreenLock() {
376 lock_handler_
.reset(new TestLockHandler(kTestUser1
));
377 lock_handler_
->set_state(TestLockHandler::STATE_ATTEMPTING_SIGNIN
);
378 ScreenlockBridge::Get()->SetLockHandler(lock_handler_
.get());
381 scoped_ptr
<EasyUnlockAuthAttempt
> auth_attempt_
;
382 scoped_ptr
<FakeAppManager
> app_manager_
;
383 scoped_ptr
<TestLockHandler
> lock_handler_
;
386 DISALLOW_COPY_AND_ASSIGN(EasyUnlockAuthAttemptSigninTest
);
389 TEST_F(EasyUnlockAuthAttemptSigninTest
, StartWhenNotLocked
) {
390 ASSERT_FALSE(ScreenlockBridge::Get()->IsLocked());
392 EXPECT_FALSE(auth_attempt_
->Start());
393 EXPECT_EQ(0u, app_manager_
->auth_attempt_count());
396 TEST_F(EasyUnlockAuthAttemptSigninTest
, StartWhenAuthTypeIsPassword
) {
398 ASSERT_TRUE(ScreenlockBridge::Get()->IsLocked());
399 ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN
, lock_handler_
->state());
401 lock_handler_
->set_auth_type(ScreenlockBridge::LockHandler::OFFLINE_PASSWORD
);
403 EXPECT_FALSE(auth_attempt_
->Start());
405 EXPECT_EQ(0u, app_manager_
->auth_attempt_count());
406 EXPECT_EQ(TestLockHandler::STATE_SIGNIN_CANCELED
, lock_handler_
->state());
409 TEST_F(EasyUnlockAuthAttemptSigninTest
,
410 StartWhenDispatchingAuthAttemptEventFails
) {
412 ASSERT_TRUE(ScreenlockBridge::Get()->IsLocked());
413 ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN
, lock_handler_
->state());
415 app_manager_
->set_auth_attempt_should_fail(true);
417 EXPECT_FALSE(auth_attempt_
->Start());
419 EXPECT_EQ(1u, app_manager_
->auth_attempt_count());
420 EXPECT_EQ(TestLockHandler::STATE_SIGNIN_CANCELED
, lock_handler_
->state());
423 TEST_F(EasyUnlockAuthAttemptSigninTest
, ResetBeforeFinalizeSignin
) {
425 ASSERT_TRUE(ScreenlockBridge::Get()->IsLocked());
426 ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN
, lock_handler_
->state());
428 ASSERT_TRUE(auth_attempt_
->Start());
430 ASSERT_EQ(1u, app_manager_
->auth_attempt_count());
431 EXPECT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN
, lock_handler_
->state());
433 auth_attempt_
.reset();
435 EXPECT_EQ(TestLockHandler::STATE_SIGNIN_CANCELED
, lock_handler_
->state());
438 TEST_F(EasyUnlockAuthAttemptSigninTest
, FinalizeSigninWithEmtpySecret
) {
440 ASSERT_TRUE(ScreenlockBridge::Get()->IsLocked());
441 ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN
, lock_handler_
->state());
443 ASSERT_TRUE(auth_attempt_
->Start());
445 ASSERT_EQ(1u, app_manager_
->auth_attempt_count());
446 EXPECT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN
, lock_handler_
->state());
448 auth_attempt_
->FinalizeSignin(kTestUser1
, "", GetSessionKey());
450 EXPECT_EQ(TestLockHandler::STATE_SIGNIN_CANCELED
, lock_handler_
->state());
453 TEST_F(EasyUnlockAuthAttemptSigninTest
, FinalizeSigninWithEmtpyKey
) {
455 ASSERT_TRUE(ScreenlockBridge::Get()->IsLocked());
456 ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN
, lock_handler_
->state());
458 ASSERT_TRUE(auth_attempt_
->Start());
460 ASSERT_EQ(1u, app_manager_
->auth_attempt_count());
461 EXPECT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN
, lock_handler_
->state());
463 auth_attempt_
->FinalizeSignin(kTestUser1
, GetWrappedSecret(), "");
465 EXPECT_EQ(TestLockHandler::STATE_SIGNIN_CANCELED
, lock_handler_
->state());
468 TEST_F(EasyUnlockAuthAttemptSigninTest
, SigninSuccess
) {
470 ASSERT_TRUE(ScreenlockBridge::Get()->IsLocked());
471 ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN
, lock_handler_
->state());
473 ASSERT_TRUE(auth_attempt_
->Start());
475 ASSERT_EQ(1u, app_manager_
->auth_attempt_count());
476 EXPECT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN
, lock_handler_
->state());
478 lock_handler_
->set_expected_secret(GetSecret());
479 auth_attempt_
->FinalizeSignin(kTestUser1
, GetWrappedSecret(),
482 EXPECT_EQ(TestLockHandler::STATE_SIGNIN_DONE
, lock_handler_
->state());
485 TEST_F(EasyUnlockAuthAttemptSigninTest
, WrongWrappedSecret
) {
487 ASSERT_TRUE(ScreenlockBridge::Get()->IsLocked());
488 ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN
, lock_handler_
->state());
490 ASSERT_TRUE(auth_attempt_
->Start());
492 ASSERT_EQ(1u, app_manager_
->auth_attempt_count());
493 EXPECT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN
, lock_handler_
->state());
495 auth_attempt_
->FinalizeSignin(kTestUser1
, "wrong_secret", GetSessionKey());
497 EXPECT_EQ(TestLockHandler::STATE_SIGNIN_CANCELED
, lock_handler_
->state());
500 TEST_F(EasyUnlockAuthAttemptSigninTest
, InvalidSessionKey
) {
502 ASSERT_TRUE(ScreenlockBridge::Get()->IsLocked());
503 ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN
, lock_handler_
->state());
505 ASSERT_TRUE(auth_attempt_
->Start());
507 ASSERT_EQ(1u, app_manager_
->auth_attempt_count());
508 EXPECT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN
, lock_handler_
->state());
510 auth_attempt_
->FinalizeSignin(kTestUser1
, GetWrappedSecret(), "invalid_key");
512 EXPECT_EQ(TestLockHandler::STATE_SIGNIN_CANCELED
, lock_handler_
->state());
515 TEST_F(EasyUnlockAuthAttemptSigninTest
, FinalizeUnlockCalled
) {
517 ASSERT_TRUE(ScreenlockBridge::Get()->IsLocked());
518 ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN
, lock_handler_
->state());
520 ASSERT_TRUE(auth_attempt_
->Start());
522 ASSERT_EQ(1u, app_manager_
->auth_attempt_count());
523 EXPECT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN
, lock_handler_
->state());
525 auth_attempt_
->FinalizeUnlock(kTestUser1
, true);
527 EXPECT_EQ(TestLockHandler::STATE_SIGNIN_CANCELED
, lock_handler_
->state());
530 TEST_F(EasyUnlockAuthAttemptSigninTest
, FinalizeSigninCalledForWrongUser
) {
532 ASSERT_TRUE(ScreenlockBridge::Get()->IsLocked());
533 ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN
, lock_handler_
->state());
535 ASSERT_TRUE(auth_attempt_
->Start());
537 ASSERT_EQ(1u, app_manager_
->auth_attempt_count());
538 EXPECT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN
, lock_handler_
->state());
540 lock_handler_
->set_expected_secret(GetSecret());
542 auth_attempt_
->FinalizeSignin(kTestUser2
, GetWrappedSecret(),
545 EXPECT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN
, lock_handler_
->state());
547 auth_attempt_
->FinalizeSignin(kTestUser1
, GetWrappedSecret(),
550 EXPECT_EQ(TestLockHandler::STATE_SIGNIN_DONE
, lock_handler_
->state());
552 #endif // defined(OS_CHROMEOS)