diff options
Diffstat (limited to 'chromium/components/policy/core/common/cloud/cloud_policy_client_registration_helper.cc')
-rw-r--r-- | chromium/components/policy/core/common/cloud/cloud_policy_client_registration_helper.cc | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/chromium/components/policy/core/common/cloud/cloud_policy_client_registration_helper.cc b/chromium/components/policy/core/common/cloud/cloud_policy_client_registration_helper.cc new file mode 100644 index 00000000000..0c9a8237fc5 --- /dev/null +++ b/chromium/components/policy/core/common/cloud/cloud_policy_client_registration_helper.cc @@ -0,0 +1,212 @@ +// Copyright 2013 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 "components/policy/core/common/cloud/cloud_policy_client_registration_helper.h" + +#include <memory> + +#include "base/bind.h" +#include "base/callback_helpers.h" +#include "base/logging.h" +#include "base/time/time.h" +#include "base/values.h" +#include "build/build_config.h" +#include "components/policy/core/common/cloud/client_data_delegate.h" +#include "components/policy/core/common/cloud/dm_auth.h" +#include "components/signin/public/identity_manager/access_token_fetcher.h" +#include "components/signin/public/identity_manager/access_token_info.h" +#include "components/signin/public/identity_manager/identity_manager.h" +#include "components/signin/public/identity_manager/scope_set.h" +#include "google_apis/gaia/gaia_constants.h" +#include "google_apis/gaia/gaia_urls.h" +#include "google_apis/gaia/google_service_auth_error.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" + +namespace policy { + +// The key under which the hosted-domain value is stored in the UserInfo +// response. +const char kGetHostedDomainKey[] = "hd"; + +typedef base::OnceCallback<void(const std::string&)> StringCallback; + +// This class fetches an OAuth2 token scoped for the userinfo and DM services. +class CloudPolicyClientRegistrationHelper::IdentityManagerHelper { + public: + IdentityManagerHelper() = default; + + void FetchAccessToken(signin::IdentityManager* identity_manager, + const CoreAccountId& account_id, + StringCallback callback); + + private: + void OnAccessTokenFetchComplete(GoogleServiceAuthError error, + signin::AccessTokenInfo token_info); + + StringCallback callback_; + std::unique_ptr<signin::AccessTokenFetcher> access_token_fetcher_; +}; + +void CloudPolicyClientRegistrationHelper::IdentityManagerHelper:: + FetchAccessToken(signin::IdentityManager* identity_manager, + const CoreAccountId& account_id, + StringCallback callback) { + DCHECK(!access_token_fetcher_); + // The caller must supply a username. + DCHECK(!account_id.empty()); + DCHECK(identity_manager->HasAccountWithRefreshToken(account_id)); + + callback_ = std::move(callback); + + signin::ScopeSet scopes; + scopes.insert(GaiaConstants::kDeviceManagementServiceOAuth); + scopes.insert(GaiaConstants::kGoogleUserInfoEmail); + + access_token_fetcher_ = identity_manager->CreateAccessTokenFetcherForAccount( + account_id, "cloud_policy", scopes, + base::BindOnce(&CloudPolicyClientRegistrationHelper:: + IdentityManagerHelper::OnAccessTokenFetchComplete, + base::Unretained(this)), + signin::AccessTokenFetcher::Mode::kImmediate); +} + +void CloudPolicyClientRegistrationHelper::IdentityManagerHelper:: + OnAccessTokenFetchComplete(GoogleServiceAuthError error, + signin::AccessTokenInfo token_info) { + DCHECK(access_token_fetcher_); + access_token_fetcher_.reset(); + + if (error.state() == GoogleServiceAuthError::NONE) + std::move(callback_).Run(token_info.token); + else + std::move(callback_).Run(""); +} + +CloudPolicyClientRegistrationHelper::CloudPolicyClientRegistrationHelper( + CloudPolicyClient* client, + enterprise_management::DeviceRegisterRequest::Type registration_type) + : client_(client), registration_type_(registration_type) { + DCHECK(client_); +} + +CloudPolicyClientRegistrationHelper::~CloudPolicyClientRegistrationHelper() { + // Clean up any pending observers in case the browser is shutdown while + // trying to register for policy. + if (client_) + client_->RemoveObserver(this); +} + +void CloudPolicyClientRegistrationHelper::StartRegistration( + signin::IdentityManager* identity_manager, + const CoreAccountId& account_id, + base::OnceClosure callback) { + DVLOG(1) << "Starting registration process with account_id"; + DCHECK(!client_->is_registered()); + callback_ = std::move(callback); + client_->AddObserver(this); + + identity_manager_helper_ = std::make_unique<IdentityManagerHelper>(); + identity_manager_helper_->FetchAccessToken( + identity_manager, account_id, + base::BindOnce(&CloudPolicyClientRegistrationHelper::OnTokenFetched, + base::Unretained(this))); +} + +void CloudPolicyClientRegistrationHelper::StartRegistrationWithEnrollmentToken( + const std::string& token, + const std::string& client_id, + const ClientDataDelegate& client_data_delegate, + base::OnceClosure callback) { + DVLOG(1) << "Starting registration process with enrollment token"; + DCHECK(!client_->is_registered()); + callback_ = std::move(callback); + client_->AddObserver(this); + client_->RegisterWithToken(token, client_id, client_data_delegate); +} + +void CloudPolicyClientRegistrationHelper::OnTokenFetched( + const std::string& access_token) { + identity_manager_helper_.reset(); + + if (access_token.empty()) { + DLOG(WARNING) << "Could not fetch access token for " + << GaiaConstants::kDeviceManagementServiceOAuth; + RequestCompleted(); + return; + } + + // Cache the access token to be used after the GetUserInfo call. + oauth_access_token_ = access_token; + DVLOG(1) << "Fetched new scoped OAuth token:" << oauth_access_token_; + // Now we've gotten our access token - contact GAIA to see if this is a + // hosted domain. + user_info_fetcher_ = + std::make_unique<UserInfoFetcher>(this, client_->GetURLLoaderFactory()); + user_info_fetcher_->Start(oauth_access_token_); +} + +void CloudPolicyClientRegistrationHelper::OnGetUserInfoFailure( + const GoogleServiceAuthError& error) { + DVLOG(1) << "Failed to fetch user info from GAIA: " << error.state(); + user_info_fetcher_.reset(); + RequestCompleted(); +} + +void CloudPolicyClientRegistrationHelper::OnGetUserInfoSuccess( + const base::DictionaryValue* data) { + user_info_fetcher_.reset(); + if (!data->FindKey(kGetHostedDomainKey)) { + DVLOG(1) << "User not from a hosted domain - skipping registration"; + RequestCompleted(); + return; + } + DVLOG(1) << "Registering CloudPolicyClient for user from hosted domain"; + // The user is from a hosted domain, so it's OK to register the + // CloudPolicyClient and make requests to DMServer. + if (client_->is_registered()) { + // Client should not be registered yet. + NOTREACHED(); + RequestCompleted(); + return; + } + + // Kick off registration of the CloudPolicyClient with our newly minted + // oauth_access_token_. + client_->Register( + CloudPolicyClient::RegistrationParameters( + registration_type_, enterprise_management::DeviceRegisterRequest:: + FLAVOR_USER_REGISTRATION), + std::string() /* client_id */, oauth_access_token_); +} + +void CloudPolicyClientRegistrationHelper::OnPolicyFetched( + CloudPolicyClient* client) { + // Ignored. +} + +void CloudPolicyClientRegistrationHelper::OnRegistrationStateChanged( + CloudPolicyClient* client) { + DVLOG(1) << "Client registration succeeded"; + DCHECK_EQ(client, client_); + DCHECK(client->is_registered()); + RequestCompleted(); +} + +void CloudPolicyClientRegistrationHelper::OnClientError( + CloudPolicyClient* client) { + DVLOG(1) << "Client registration failed"; + DCHECK_EQ(client, client_); + RequestCompleted(); +} + +void CloudPolicyClientRegistrationHelper::RequestCompleted() { + if (client_) { + client_->RemoveObserver(this); + // |client_| may be freed by the callback so clear it now. + client_ = nullptr; + std::move(callback_).Run(); + } +} + +} // namespace policy |