Commit 0917c680 authored by Jacob Dufault's avatar Jacob Dufault Committed by Commit Bot

cros: Store UserContext in QuickUnlockStorage.

Adding a key to cryptohome requires the associated UserContext. This
adds an AuthToken to quick_unlock which stores the UserContext
instance. The AuthToken automatically expires after a delay.

Bug: 623344
Change-Id: Ife3373599fb560dfe9f9055fcda54a9f001c6ac7
Reviewed-on: https://chromium-review.googlesource.com/980738
Commit-Queue: Jacob Dufault <jdufault@chromium.org>
Reviewed-by: default avatarSteven Bennetts <stevenjb@chromium.org>
Reviewed-by: default avatarAchuith Bhandarkar <achuith@chromium.org>
Cr-Commit-Position: refs/heads/master@{#547785}
parent 097d6507
......@@ -962,6 +962,8 @@ source_set("chromeos") {
"login/oobe_screen.h",
"login/profile_auth_data.cc",
"login/profile_auth_data.h",
"login/quick_unlock/auth_token.cc",
"login/quick_unlock/auth_token.h",
"login/quick_unlock/fingerprint_storage.cc",
"login/quick_unlock/fingerprint_storage.h",
"login/quick_unlock/pin_storage.cc",
......
......@@ -10,6 +10,7 @@
#include "base/stl_util.h"
#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.h"
#include "chrome/browser/chromeos/login/quick_unlock/auth_token.h"
#include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_factory.h"
#include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_storage.h"
#include "chrome/browser/chromeos/login/supervised/supervised_user_authentication.h"
......@@ -40,6 +41,7 @@ using CredentialCheck = quick_unlock_private::CredentialCheck;
using CredentialRequirements = quick_unlock_private::CredentialRequirements;
using QuickUnlockMode = quick_unlock_private::QuickUnlockMode;
using AuthToken = chromeos::quick_unlock::AuthToken;
using QuickUnlockModeList = std::vector<QuickUnlockMode>;
using QuickUnlockStorage = chromeos::quick_unlock::QuickUnlockStorage;
......@@ -253,8 +255,8 @@ void QuickUnlockPrivateGetAuthTokenFunction::OnAuthSuccess(
Profile* profile = Profile::FromBrowserContext(browser_context());
QuickUnlockStorage* quick_unlock_storage =
chromeos::quick_unlock::QuickUnlockFactory::GetForProfile(profile);
result->token = quick_unlock_storage->CreateAuthToken();
result->lifetime_seconds = QuickUnlockStorage::kTokenExpirationSeconds;
result->token = quick_unlock_storage->CreateAuthToken(user_context);
result->lifetime_seconds = AuthToken::kTokenExpirationSeconds;
Respond(ArgumentList(
quick_unlock_private::GetAuthToken::Results::Create(*result)));
......@@ -395,8 +397,8 @@ QuickUnlockPrivateGetCredentialRequirementsFunction::Run() {
QuickUnlockPrivateSetModesFunction::QuickUnlockPrivateSetModesFunction()
: chrome_details_(this) {}
QuickUnlockPrivateSetModesFunction::~QuickUnlockPrivateSetModesFunction() {
}
QuickUnlockPrivateSetModesFunction::~QuickUnlockPrivateSetModesFunction() =
default;
void QuickUnlockPrivateSetModesFunction::SetModesChangedEventHandlerForTesting(
const ModesChangedEventHandler& handler) {
......
......@@ -120,7 +120,7 @@ class QuickUnlockPrivateUnitTest : public ExtensionApiUnittest {
// Generate an auth token.
token_ = quick_unlock::QuickUnlockFactory::GetForProfile(profile())
->CreateAuthToken();
->CreateAuthToken(auth_token_user_context_);
// Ensure that quick unlock is turned off.
RunSetModes(QuickUnlockModeList{}, CredentialList{});
......@@ -395,6 +395,7 @@ class QuickUnlockPrivateUnitTest : public ExtensionApiUnittest {
QuickUnlockPrivateSetModesFunction::ModesChangedEventHandler
modes_changed_handler_;
bool expect_modes_changed_ = false;
chromeos::UserContext auth_token_user_context_;
std::string token_;
DISALLOW_COPY_AND_ASSIGN(QuickUnlockPrivateUnitTest);
......@@ -409,7 +410,7 @@ TEST_F(QuickUnlockPrivateUnitTest, GetAuthTokenValid) {
quick_unlock::QuickUnlockFactory::GetForProfile(profile());
EXPECT_EQ(token_info->token, quick_unlock_storage->GetAuthToken());
EXPECT_EQ(token_info->lifetime_seconds,
quick_unlock::QuickUnlockStorage::kTokenExpirationSeconds);
quick_unlock::AuthToken::kTokenExpirationSeconds);
}
// Verifies that GetAuthTokenValid fails when an invalid password is provided.
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/chromeos/login/quick_unlock/auth_token.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chromeos/login/auth/user_context.h"
namespace chromeos {
namespace quick_unlock {
const int AuthToken::kTokenExpirationSeconds = 5 * 60;
AuthToken::AuthToken(const chromeos::UserContext& user_context)
: identifier_(base::UnguessableToken::Create()),
user_context_(std::make_unique<chromeos::UserContext>(user_context)),
weak_factory_(this) {
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, base::BindOnce(&AuthToken::Reset, weak_factory_.GetWeakPtr()),
base::TimeDelta::FromSeconds(kTokenExpirationSeconds));
}
AuthToken::~AuthToken() = default;
base::Optional<std::string> AuthToken::Identifier() {
if (!user_context_)
return base::nullopt;
return identifier_.ToString();
}
void AuthToken::ResetForTest() {
Reset();
}
void AuthToken::Reset() {
if (user_context_)
user_context_->ClearSecrets();
user_context_.reset();
}
} // namespace quick_unlock
} // namespace chromeos
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_QUICK_UNLOCK_AUTH_TOKEN_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_QUICK_UNLOCK_AUTH_TOKEN_H_
#include <memory>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/unguessable_token.h"
namespace chromeos {
class UserContext;
namespace quick_unlock {
class AuthToken {
public:
// How long the token lives.
static const int kTokenExpirationSeconds;
explicit AuthToken(const chromeos::UserContext& user_context);
~AuthToken();
// An unguessable identifier that can be passed to webui to verify the token
// instance has not changed. Returns nullopt if the token is expired.
base::Optional<std::string> Identifier();
// The UserContext returned here can be null if its time-to-live has expired.
chromeos::UserContext* user_context() { return user_context_.get(); }
// Time the token out - should be used only by tests.
void ResetForTest();
private:
// Times the token out.
void Reset();
base::UnguessableToken identifier_;
std::unique_ptr<chromeos::UserContext> user_context_;
base::WeakPtrFactory<AuthToken> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(AuthToken);
};
} // namespace quick_unlock
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_LOGIN_QUICK_UNLOCK_AUTH_TOKEN_H_
......@@ -14,8 +14,6 @@
namespace chromeos {
namespace quick_unlock {
const int QuickUnlockStorage::kTokenExpirationSeconds = 5 * 60;
QuickUnlockStorage::QuickUnlockStorage(PrefService* pref_service)
: pref_service_(pref_service) {
fingerprint_storage_ = std::make_unique<FingerprintStorage>(pref_service);
......@@ -63,24 +61,21 @@ bool QuickUnlockStorage::TryAuthenticatePin(const std::string& pin,
return HasStrongAuth() && pin_storage()->TryAuthenticatePin(pin, key_type);
}
std::string QuickUnlockStorage::CreateAuthToken() {
auth_token_ = base::UnguessableToken::Create();
auth_token_issue_time_ = base::TimeTicks::Now();
return auth_token_.ToString();
std::string QuickUnlockStorage::CreateAuthToken(
const chromeos::UserContext& user_context) {
auth_token_ = std::make_unique<AuthToken>(user_context);
DCHECK(auth_token_->Identifier().has_value());
return *auth_token_->Identifier();
}
bool QuickUnlockStorage::GetAuthTokenExpired() {
return base::TimeTicks::Now() >=
auth_token_issue_time_ +
base::TimeDelta::FromSeconds(kTokenExpirationSeconds);
return !auth_token_ || !auth_token_->Identifier().has_value();
}
std::string QuickUnlockStorage::GetAuthToken() {
if (GetAuthTokenExpired()) {
auth_token_ = base::UnguessableToken();
return std::string();
}
return auth_token_.is_empty() ? std::string() : auth_token_.ToString();
if (GetAuthTokenExpired())
return "";
return *auth_token_->Identifier();
}
void QuickUnlockStorage::Shutdown() {
......
......@@ -6,9 +6,10 @@
#define CHROME_BROWSER_CHROMEOS_LOGIN_QUICK_UNLOCK_QUICK_UNLOCK_STORAGE_H_
#include "base/memory/ptr_util.h"
#include "base/unguessable_token.h"
#include "chrome/browser/chromeos/login/quick_unlock/auth_token.h"
#include "chrome/browser/chromeos/login/quick_unlock/fingerprint_storage.h"
#include "chrome/browser/chromeos/login/quick_unlock/pin_storage.h"
#include "chromeos/login/auth/user_context.h"
#include "components/keyed_service/core/keyed_service.h"
class PrefService;
......@@ -57,7 +58,7 @@ class QuickUnlockStorage : public KeyedService {
// Creates a new authentication token to be used by the quickSettingsPrivate
// API for authenticating requests. Resets the expiration timer and
// invalidates any previously issued tokens.
std::string CreateAuthToken();
std::string CreateAuthToken(const chromeos::UserContext& user_context);
// Returns true if the current authentication token has expired.
bool GetAuthTokenExpired();
......@@ -71,8 +72,6 @@ class QuickUnlockStorage : public KeyedService {
}
PinStorage* pin_storage() { return pin_storage_.get(); }
static const int kTokenExpirationSeconds;
private:
friend class chromeos::QuickUnlockStorageTestApi;
friend class chromeos::QuickUnlockStorageUnitTest;
......@@ -84,8 +83,7 @@ class QuickUnlockStorage : public KeyedService {
base::TimeTicks last_strong_auth_;
std::unique_ptr<FingerprintStorage> fingerprint_storage_;
std::unique_ptr<PinStorage> pin_storage_;
base::UnguessableToken auth_token_;
base::TimeTicks auth_token_issue_time_;
std::unique_ptr<AuthToken> auth_token_;
DISALLOW_COPY_AND_ASSIGN(QuickUnlockStorage);
};
......
......@@ -17,6 +17,7 @@
namespace chromeos {
using AuthToken = quick_unlock::AuthToken;
using QuickUnlockStorage = quick_unlock::QuickUnlockStorage;
namespace {
......@@ -48,10 +49,7 @@ class QuickUnlockStorageUnitTest : public testing::Test {
void ExpireAuthToken() {
quick_unlock::QuickUnlockFactory::GetForProfile(profile_.get())
->auth_token_issue_time_ =
base::TimeTicks::Now() -
base::TimeDelta::FromSeconds(
QuickUnlockStorage::kTokenExpirationSeconds);
->auth_token_->ResetForTest();
}
content::TestBrowserThreadBundle thread_bundle_;
......@@ -169,7 +167,8 @@ TEST_F(QuickUnlockStorageUnitTest, AuthToken) {
quick_unlock::QuickUnlockFactory::GetForProfile(profile_.get());
EXPECT_EQ(std::string(), quick_unlock_storage->GetAuthToken());
std::string auth_token = quick_unlock_storage->CreateAuthToken();
chromeos::UserContext context;
std::string auth_token = quick_unlock_storage->CreateAuthToken(context);
EXPECT_NE(std::string(), auth_token);
EXPECT_EQ(auth_token, quick_unlock_storage->GetAuthToken());
EXPECT_FALSE(quick_unlock_storage->GetAuthTokenExpired());
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment