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/proximity_auth_facade.h"
10 #include "components/proximity_auth/screenlock_bridge.h"
11 #include "testing/gtest/include/gtest/gtest.h"
13 #if defined(OS_CHROMEOS)
14 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.h"
19 // Fake user ids used in tests.
20 const char kTestUser1
[] = "user1";
21 const char kTestUser2
[] = "user2";
23 #if defined(OS_CHROMEOS)
24 const unsigned char kSecret
[] = {
25 0x7c, 0x85, 0x82, 0x7d, 0x00, 0x1f, 0x6a, 0x29, 0x2f, 0xc4, 0xb5, 0x60,
26 0x08, 0x9b, 0xb0, 0x5b
30 const unsigned char kSessionKey
[] = {
31 0xc3, 0xd9, 0x83, 0x16, 0x52, 0xde, 0x99, 0xd7, 0x4e, 0x60, 0xf9, 0xec,
32 0xa8, 0x9c, 0x0e, 0xbe
35 const unsigned char kWrappedSecret
[] = {
36 0x3a, 0xea, 0x51, 0xd9, 0x64, 0x64, 0xe1, 0xcd, 0xd8, 0xee, 0x99, 0xf5,
37 0xb1, 0xd4, 0x9f, 0xc4, 0x28, 0xd6, 0xfd, 0x69, 0x0b, 0x9e, 0x06, 0x21,
38 0xfc, 0x40, 0x1f, 0xeb, 0x75, 0x64, 0x52, 0xd8
41 #if defined(OS_CHROMEOS)
42 std::string
GetSecret() {
43 return std::string(reinterpret_cast<const char*>(kSecret
),
48 std::string
GetWrappedSecret() {
49 return std::string(reinterpret_cast<const char*>(kWrappedSecret
),
50 arraysize(kWrappedSecret
));
53 std::string
GetSessionKey() {
54 return std::string(reinterpret_cast<const char*>(kSessionKey
),
55 arraysize(kSessionKey
));
58 // Fake app manager used by the EasyUnlockAuthAttempt during tests.
59 // It tracks screenlockPrivate.onAuthAttempted events.
60 class FakeAppManager
: public EasyUnlockAppManager
{
63 : auth_attempt_count_(0u), auth_attempt_should_fail_(false) {}
64 ~FakeAppManager() override
{}
66 void EnsureReady(const base::Closure
& ready_callback
) override
{
67 ADD_FAILURE() << "Not reached";
70 void LaunchSetup() override
{ ADD_FAILURE() << "Not reached"; }
72 void LoadApp() override
{ ADD_FAILURE() << "Not reached"; }
74 void DisableAppIfLoaded() override
{ ADD_FAILURE() << "Not reached"; }
76 void ReloadApp() override
{ ADD_FAILURE() << "Not reached"; }
78 bool SendUserUpdatedEvent(const std::string
& user_id
,
80 bool data_ready
) override
{
81 ADD_FAILURE() << "Not reached";
85 bool SendAuthAttemptEvent() override
{
86 ++auth_attempt_count_
;
87 return !auth_attempt_should_fail_
;
90 size_t auth_attempt_count() const { return auth_attempt_count_
; }
92 void set_auth_attempt_should_fail(bool value
) {
93 auth_attempt_should_fail_
= value
;
97 size_t auth_attempt_count_
;
98 bool auth_attempt_should_fail_
;
100 DISALLOW_COPY_AND_ASSIGN(FakeAppManager
);
103 // Fake lock handler to be used in these tests.
104 class TestLockHandler
: public proximity_auth::ScreenlockBridge::LockHandler
{
106 // The state of unlock/signin procedure.
109 STATE_ATTEMPTING_UNLOCK
,
110 STATE_UNLOCK_CANCELED
,
112 STATE_ATTEMPTING_SIGNIN
,
113 STATE_SIGNIN_CANCELED
,
117 explicit TestLockHandler(const std::string
& user_id
)
118 : state_(STATE_NONE
), auth_type_(USER_CLICK
), user_id_(user_id
) {}
120 ~TestLockHandler() override
{}
122 void set_state(AuthState value
) { state_
= value
; }
123 AuthState
state() const { return state_
; }
125 // Changes the user associated with the lock handler.
126 // Caller should make sure that |state_| is also appropriately updated.
127 void set_user_id(const std::string
& value
) { user_id_
= value
; }
129 // Sets the secret that is expected to be sent to |AttemptEasySignin|
130 void set_expected_secret(const std::string
& value
) {
131 expected_secret_
= value
;
134 // Not using |SetAuthType| to make sure it's not called during tests.
135 void set_auth_type(AuthType value
) { auth_type_
= value
; }
137 // proximity_auth::ScreenlockBridge::LockHandler implementation:
138 void ShowBannerMessage(const base::string16
& message
) override
{
139 ADD_FAILURE() << "Should not be reached.";
142 void ShowUserPodCustomIcon(
143 const std::string
& user_email
,
144 const proximity_auth::ScreenlockBridge::UserPodCustomIconOptions
& icon
)
146 ADD_FAILURE() << "Should not be reached.";
149 void HideUserPodCustomIcon(const std::string
& user_email
) override
{
150 ADD_FAILURE() << "Should not be reached.";
153 void EnableInput() override
{
154 ASSERT_EQ(STATE_ATTEMPTING_UNLOCK
, state_
);
155 state_
= STATE_UNLOCK_CANCELED
;
158 void SetAuthType(const std::string
& user_email
,
160 const base::string16
& auth_value
) override
{
161 ADD_FAILURE() << "Should not be reached.";
164 AuthType
GetAuthType(const std::string
& user_email
) const override
{
168 ScreenType
GetScreenType() const override
{
169 // Return an arbitrary value; this is not used by the test code.
173 void Unlock(const std::string
& user_email
) override
{
174 ASSERT_EQ(user_id_
, user_email
);
175 ASSERT_EQ(STATE_ATTEMPTING_UNLOCK
, state_
);
176 state_
= STATE_UNLOCK_DONE
;
179 void AttemptEasySignin(const std::string
& user_email
,
180 const std::string
& secret
,
181 const std::string
& key_label
) override
{
182 #if defined(OS_CHROMEOS)
183 ASSERT_EQ(user_id_
, user_email
);
185 ASSERT_EQ(STATE_ATTEMPTING_SIGNIN
, state_
);
186 if (secret
.empty()) {
187 state_
= STATE_SIGNIN_CANCELED
;
189 ASSERT_EQ(expected_secret_
, secret
);
190 ASSERT_EQ(chromeos::EasyUnlockKeyManager::GetKeyLabel(0u), key_label
);
191 state_
= STATE_SIGNIN_DONE
;
193 #else // if !defined(OS_CHROMEOS)
194 ADD_FAILURE() << "Should not be reached.";
201 std::string user_id_
;
202 std::string expected_secret_
;
204 DISALLOW_COPY_AND_ASSIGN(TestLockHandler
);
207 class EasyUnlockAuthAttemptUnlockTest
: public testing::Test
{
209 EasyUnlockAuthAttemptUnlockTest() {}
210 ~EasyUnlockAuthAttemptUnlockTest() override
{}
212 void SetUp() override
{
213 app_manager_
.reset(new FakeAppManager());
214 auth_attempt_
.reset(new EasyUnlockAuthAttempt(
215 app_manager_
.get(), kTestUser1
, EasyUnlockAuthAttempt::TYPE_UNLOCK
,
216 EasyUnlockAuthAttempt::FinalizedCallback()));
219 void TearDown() override
{
220 GetScreenlockBridgeInstance()->SetLockHandler(NULL
);
221 auth_attempt_
.reset();
225 void InitScreenLock() {
226 lock_handler_
.reset(new TestLockHandler(kTestUser1
));
227 lock_handler_
->set_state(TestLockHandler::STATE_ATTEMPTING_UNLOCK
);
228 GetScreenlockBridgeInstance()->SetLockHandler(lock_handler_
.get());
231 scoped_ptr
<EasyUnlockAuthAttempt
> auth_attempt_
;
232 scoped_ptr
<FakeAppManager
> app_manager_
;
233 scoped_ptr
<TestLockHandler
> lock_handler_
;
236 DISALLOW_COPY_AND_ASSIGN(EasyUnlockAuthAttemptUnlockTest
);
239 TEST_F(EasyUnlockAuthAttemptUnlockTest
, StartWhenNotLocked
) {
240 ASSERT_FALSE(GetScreenlockBridgeInstance()->IsLocked());
242 EXPECT_FALSE(auth_attempt_
->Start());
243 EXPECT_EQ(0u, app_manager_
->auth_attempt_count());
246 TEST_F(EasyUnlockAuthAttemptUnlockTest
, StartWhenAuthTypeIsPassword
) {
248 ASSERT_TRUE(GetScreenlockBridgeInstance()->IsLocked());
249 ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_UNLOCK
, lock_handler_
->state());
251 lock_handler_
->set_auth_type(
252 proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD
);
254 EXPECT_FALSE(auth_attempt_
->Start());
256 EXPECT_EQ(0u, app_manager_
->auth_attempt_count());
257 EXPECT_EQ(TestLockHandler::STATE_UNLOCK_CANCELED
, lock_handler_
->state());
260 TEST_F(EasyUnlockAuthAttemptUnlockTest
,
261 StartWhenDispatchingAuthAttemptEventFails
) {
263 ASSERT_TRUE(GetScreenlockBridgeInstance()->IsLocked());
264 ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_UNLOCK
, lock_handler_
->state());
266 app_manager_
->set_auth_attempt_should_fail(true);
268 EXPECT_FALSE(auth_attempt_
->Start());
270 EXPECT_EQ(1u, app_manager_
->auth_attempt_count());
271 EXPECT_EQ(TestLockHandler::STATE_UNLOCK_CANCELED
, lock_handler_
->state());
274 TEST_F(EasyUnlockAuthAttemptUnlockTest
, ResetBeforeFinalizeUnlock
) {
276 ASSERT_TRUE(GetScreenlockBridgeInstance()->IsLocked());
277 ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_UNLOCK
, lock_handler_
->state());
279 ASSERT_TRUE(auth_attempt_
->Start());
281 ASSERT_EQ(1u, app_manager_
->auth_attempt_count());
282 EXPECT_EQ(TestLockHandler::STATE_ATTEMPTING_UNLOCK
, lock_handler_
->state());
284 auth_attempt_
.reset();
286 EXPECT_EQ(TestLockHandler::STATE_UNLOCK_CANCELED
, lock_handler_
->state());
289 TEST_F(EasyUnlockAuthAttemptUnlockTest
, FinalizeUnlockFailure
) {
291 ASSERT_TRUE(GetScreenlockBridgeInstance()->IsLocked());
292 ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_UNLOCK
, lock_handler_
->state());
294 ASSERT_TRUE(auth_attempt_
->Start());
296 ASSERT_EQ(1u, app_manager_
->auth_attempt_count());
297 EXPECT_EQ(TestLockHandler::STATE_ATTEMPTING_UNLOCK
, lock_handler_
->state());
299 auth_attempt_
->FinalizeUnlock(kTestUser1
, false);
301 EXPECT_EQ(TestLockHandler::STATE_UNLOCK_CANCELED
, lock_handler_
->state());
304 TEST_F(EasyUnlockAuthAttemptUnlockTest
, FinalizeSigninCalled
) {
306 ASSERT_TRUE(GetScreenlockBridgeInstance()->IsLocked());
307 ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_UNLOCK
, lock_handler_
->state());
309 ASSERT_TRUE(auth_attempt_
->Start());
311 ASSERT_EQ(1u, app_manager_
->auth_attempt_count());
312 EXPECT_EQ(TestLockHandler::STATE_ATTEMPTING_UNLOCK
, lock_handler_
->state());
314 // Wrapped secret and key should be irrelevant in this case.
315 auth_attempt_
->FinalizeSignin(kTestUser1
, GetWrappedSecret(),
318 EXPECT_EQ(TestLockHandler::STATE_UNLOCK_CANCELED
, lock_handler_
->state());
321 TEST_F(EasyUnlockAuthAttemptUnlockTest
, UnlockSucceeds
) {
323 ASSERT_TRUE(GetScreenlockBridgeInstance()->IsLocked());
324 ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_UNLOCK
, lock_handler_
->state());
326 ASSERT_TRUE(auth_attempt_
->Start());
328 ASSERT_EQ(1u, app_manager_
->auth_attempt_count());
329 EXPECT_EQ(TestLockHandler::STATE_ATTEMPTING_UNLOCK
, lock_handler_
->state());
331 auth_attempt_
->FinalizeUnlock(kTestUser1
, true);
333 ASSERT_EQ(TestLockHandler::STATE_UNLOCK_DONE
, lock_handler_
->state());
336 TEST_F(EasyUnlockAuthAttemptUnlockTest
, FinalizeUnlockCalledForWrongUser
) {
338 ASSERT_TRUE(GetScreenlockBridgeInstance()->IsLocked());
339 ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_UNLOCK
, lock_handler_
->state());
341 ASSERT_TRUE(auth_attempt_
->Start());
343 ASSERT_EQ(1u, app_manager_
->auth_attempt_count());
344 EXPECT_EQ(TestLockHandler::STATE_ATTEMPTING_UNLOCK
, lock_handler_
->state());
346 auth_attempt_
->FinalizeUnlock(kTestUser2
, true);
348 // If FinalizeUnlock is called for an incorrect user, it should be ignored
349 // rather than cancelling the authentication.
350 ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_UNLOCK
, lock_handler_
->state());
352 // When FinalizeUnlock is called for the correct user, it should work as
354 auth_attempt_
->FinalizeUnlock(kTestUser1
, true);
356 ASSERT_EQ(TestLockHandler::STATE_UNLOCK_DONE
, lock_handler_
->state());
359 #if defined(OS_CHROMEOS)
360 class EasyUnlockAuthAttemptSigninTest
: public testing::Test
{
362 EasyUnlockAuthAttemptSigninTest() {}
363 ~EasyUnlockAuthAttemptSigninTest() override
{}
365 void SetUp() override
{
366 app_manager_
.reset(new FakeAppManager());
367 auth_attempt_
.reset(new EasyUnlockAuthAttempt(
368 app_manager_
.get(), kTestUser1
, EasyUnlockAuthAttempt::TYPE_SIGNIN
,
369 EasyUnlockAuthAttempt::FinalizedCallback()));
372 void TearDown() override
{
373 GetScreenlockBridgeInstance()->SetLockHandler(NULL
);
374 auth_attempt_
.reset();
378 void InitScreenLock() {
379 lock_handler_
.reset(new TestLockHandler(kTestUser1
));
380 lock_handler_
->set_state(TestLockHandler::STATE_ATTEMPTING_SIGNIN
);
381 GetScreenlockBridgeInstance()->SetLockHandler(lock_handler_
.get());
384 scoped_ptr
<EasyUnlockAuthAttempt
> auth_attempt_
;
385 scoped_ptr
<FakeAppManager
> app_manager_
;
386 scoped_ptr
<TestLockHandler
> lock_handler_
;
389 DISALLOW_COPY_AND_ASSIGN(EasyUnlockAuthAttemptSigninTest
);
392 TEST_F(EasyUnlockAuthAttemptSigninTest
, StartWhenNotLocked
) {
393 ASSERT_FALSE(GetScreenlockBridgeInstance()->IsLocked());
395 EXPECT_FALSE(auth_attempt_
->Start());
396 EXPECT_EQ(0u, app_manager_
->auth_attempt_count());
399 TEST_F(EasyUnlockAuthAttemptSigninTest
, StartWhenAuthTypeIsPassword
) {
401 ASSERT_TRUE(GetScreenlockBridgeInstance()->IsLocked());
402 ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN
, lock_handler_
->state());
404 lock_handler_
->set_auth_type(
405 proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD
);
407 EXPECT_FALSE(auth_attempt_
->Start());
409 EXPECT_EQ(0u, app_manager_
->auth_attempt_count());
410 EXPECT_EQ(TestLockHandler::STATE_SIGNIN_CANCELED
, lock_handler_
->state());
413 TEST_F(EasyUnlockAuthAttemptSigninTest
,
414 StartWhenDispatchingAuthAttemptEventFails
) {
416 ASSERT_TRUE(GetScreenlockBridgeInstance()->IsLocked());
417 ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN
, lock_handler_
->state());
419 app_manager_
->set_auth_attempt_should_fail(true);
421 EXPECT_FALSE(auth_attempt_
->Start());
423 EXPECT_EQ(1u, app_manager_
->auth_attempt_count());
424 EXPECT_EQ(TestLockHandler::STATE_SIGNIN_CANCELED
, lock_handler_
->state());
427 TEST_F(EasyUnlockAuthAttemptSigninTest
, ResetBeforeFinalizeSignin
) {
429 ASSERT_TRUE(GetScreenlockBridgeInstance()->IsLocked());
430 ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN
, lock_handler_
->state());
432 ASSERT_TRUE(auth_attempt_
->Start());
434 ASSERT_EQ(1u, app_manager_
->auth_attempt_count());
435 EXPECT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN
, lock_handler_
->state());
437 auth_attempt_
.reset();
439 EXPECT_EQ(TestLockHandler::STATE_SIGNIN_CANCELED
, lock_handler_
->state());
442 TEST_F(EasyUnlockAuthAttemptSigninTest
, FinalizeSigninWithEmtpySecret
) {
444 ASSERT_TRUE(GetScreenlockBridgeInstance()->IsLocked());
445 ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN
, lock_handler_
->state());
447 ASSERT_TRUE(auth_attempt_
->Start());
449 ASSERT_EQ(1u, app_manager_
->auth_attempt_count());
450 EXPECT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN
, lock_handler_
->state());
452 auth_attempt_
->FinalizeSignin(kTestUser1
, "", GetSessionKey());
454 EXPECT_EQ(TestLockHandler::STATE_SIGNIN_CANCELED
, lock_handler_
->state());
457 TEST_F(EasyUnlockAuthAttemptSigninTest
, FinalizeSigninWithEmtpyKey
) {
459 ASSERT_TRUE(GetScreenlockBridgeInstance()->IsLocked());
460 ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN
, lock_handler_
->state());
462 ASSERT_TRUE(auth_attempt_
->Start());
464 ASSERT_EQ(1u, app_manager_
->auth_attempt_count());
465 EXPECT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN
, lock_handler_
->state());
467 auth_attempt_
->FinalizeSignin(kTestUser1
, GetWrappedSecret(), "");
469 EXPECT_EQ(TestLockHandler::STATE_SIGNIN_CANCELED
, lock_handler_
->state());
472 TEST_F(EasyUnlockAuthAttemptSigninTest
, SigninSuccess
) {
474 ASSERT_TRUE(GetScreenlockBridgeInstance()->IsLocked());
475 ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN
, lock_handler_
->state());
477 ASSERT_TRUE(auth_attempt_
->Start());
479 ASSERT_EQ(1u, app_manager_
->auth_attempt_count());
480 EXPECT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN
, lock_handler_
->state());
482 lock_handler_
->set_expected_secret(GetSecret());
483 auth_attempt_
->FinalizeSignin(kTestUser1
, GetWrappedSecret(),
486 EXPECT_EQ(TestLockHandler::STATE_SIGNIN_DONE
, lock_handler_
->state());
489 TEST_F(EasyUnlockAuthAttemptSigninTest
, WrongWrappedSecret
) {
491 ASSERT_TRUE(GetScreenlockBridgeInstance()->IsLocked());
492 ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN
, lock_handler_
->state());
494 ASSERT_TRUE(auth_attempt_
->Start());
496 ASSERT_EQ(1u, app_manager_
->auth_attempt_count());
497 EXPECT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN
, lock_handler_
->state());
499 auth_attempt_
->FinalizeSignin(kTestUser1
, "wrong_secret", GetSessionKey());
501 EXPECT_EQ(TestLockHandler::STATE_SIGNIN_CANCELED
, lock_handler_
->state());
504 TEST_F(EasyUnlockAuthAttemptSigninTest
, InvalidSessionKey
) {
506 ASSERT_TRUE(GetScreenlockBridgeInstance()->IsLocked());
507 ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN
, lock_handler_
->state());
509 ASSERT_TRUE(auth_attempt_
->Start());
511 ASSERT_EQ(1u, app_manager_
->auth_attempt_count());
512 EXPECT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN
, lock_handler_
->state());
514 auth_attempt_
->FinalizeSignin(kTestUser1
, GetWrappedSecret(), "invalid_key");
516 EXPECT_EQ(TestLockHandler::STATE_SIGNIN_CANCELED
, lock_handler_
->state());
519 TEST_F(EasyUnlockAuthAttemptSigninTest
, FinalizeUnlockCalled
) {
521 ASSERT_TRUE(GetScreenlockBridgeInstance()->IsLocked());
522 ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN
, lock_handler_
->state());
524 ASSERT_TRUE(auth_attempt_
->Start());
526 ASSERT_EQ(1u, app_manager_
->auth_attempt_count());
527 EXPECT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN
, lock_handler_
->state());
529 auth_attempt_
->FinalizeUnlock(kTestUser1
, true);
531 EXPECT_EQ(TestLockHandler::STATE_SIGNIN_CANCELED
, lock_handler_
->state());
534 TEST_F(EasyUnlockAuthAttemptSigninTest
, FinalizeSigninCalledForWrongUser
) {
536 ASSERT_TRUE(GetScreenlockBridgeInstance()->IsLocked());
537 ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN
, lock_handler_
->state());
539 ASSERT_TRUE(auth_attempt_
->Start());
541 ASSERT_EQ(1u, app_manager_
->auth_attempt_count());
542 EXPECT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN
, lock_handler_
->state());
544 lock_handler_
->set_expected_secret(GetSecret());
546 auth_attempt_
->FinalizeSignin(kTestUser2
, GetWrappedSecret(),
549 EXPECT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN
, lock_handler_
->state());
551 auth_attempt_
->FinalizeSignin(kTestUser1
, GetWrappedSecret(),
554 EXPECT_EQ(TestLockHandler::STATE_SIGNIN_DONE
, lock_handler_
->state());
556 #endif // defined(OS_CHROMEOS)