[auth] Remove oauth_token_manager prototype.

oauth_token_manager is replaced by fuchsia::auth::TokenManager for all
auth/token operations.

TEST = Manual user login, CQ.

Change-Id: I704c0ad8870e957b19e80515f6d1de484ddf27c2
diff --git a/examples/oauth_token_manager/BUILD.gn b/examples/oauth_token_manager/BUILD.gn
deleted file mode 100644
index df81c82..0000000
--- a/examples/oauth_token_manager/BUILD.gn
+++ /dev/null
@@ -1,55 +0,0 @@
-# Copyright 2017 The Fuchsia Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//build/package.gni")
-import("//third_party/flatbuffers/flatbuffer.gni")
-
-flatbuffer("credentials") {
-  sources = [
-    "credentials.fbs",
-  ]
-}
-
-executable("bin") {
-  output_name = "oauth_token_manager"
-
-  sources = [
-    "oauth_token_manager.cc",
-  ]
-
-  deps = [
-    ":credentials",
-    "//garnet/public/lib/component/cpp",
-    "//garnet/public/lib/fidl/cpp",
-    "//garnet/public/lib/fsl",
-    "//garnet/public/lib/fxl",
-    "//garnet/public/fidl/fuchsia.net.oldhttp",
-    "//garnet/public/fidl/fuchsia.ui.viewsv1",
-    "//peridot/public/fidl/fuchsia.modular.auth",
-    "//peridot/public/lib/async/cpp:operation",
-    "//third_party/rapidjson",
-    "//topaz/runtime/web_runner/services",
-    "//zircon/public/lib/async-loop-cpp",
-    "//zircon/public/lib/trace-provider",
-  ]
-}
-
-package("oauth_token_manager") {
-  deps = [
-    ":bin",
-  ]
-
-  binaries = [
-    {
-      name = "oauth_token_manager"
-    },
-  ]
-
-  meta = [
-    {
-      path = rebase_path("meta/oauth_token_manager.cmx")
-      dest = "oauth_token_manager.cmx"
-    },
-  ]
-}
diff --git a/examples/oauth_token_manager/credentials.fbs b/examples/oauth_token_manager/credentials.fbs
deleted file mode 100644
index 3fbb623..0000000
--- a/examples/oauth_token_manager/credentials.fbs
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2017 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Schema to store user's long lived credentials from different Identity
-// Providers.
-
-namespace modular;
-namespace auth;
-
-// List of supported identity providers.
-enum IdentityProvider : byte { GOOGLE }
-
-// IdpCredential is used to store refresh token from each identity provider
-// after user's consent.
-table IdpCredential {
-  identity_provider: IdentityProvider;
-  refresh_token: string;
-}
-
-// UserCredential stores a list of authentication credentials from various
-// identity providers for each unique user.
-table UserCredential {
-  account_id: string;
-  tokens: [IdpCredential];
-}
-
-// Stores authentication credentials for all users.
-table CredentialStore {
-  creds: [UserCredential];
-}
-
-root_type CredentialStore;
diff --git a/examples/oauth_token_manager/meta/oauth_token_manager.cmx b/examples/oauth_token_manager/meta/oauth_token_manager.cmx
deleted file mode 100644
index 318922c..0000000
--- a/examples/oauth_token_manager/meta/oauth_token_manager.cmx
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-    "program": {
-        "binary": "bin/oauth_token_manager"
-    },
-    "sandbox": {
-        "features": [ "persistent-storage" ],
-        "services": [
-            "fuchsia.tracelink.Registry",
-            "fuchsia.sys.Launcher",
-            "fuchsia.net.oldhttp.HttpService",
-            "fuchsia.net.oldhttp.UrlLoader",
-            "fuchsia.ui.viewsv1.ViewProvider",
-            "fuchsia.webview.WebView"
-        ]
-    }
-}
diff --git a/examples/oauth_token_manager/oauth_token_manager.cc b/examples/oauth_token_manager/oauth_token_manager.cc
deleted file mode 100644
index f034ed7..0000000
--- a/examples/oauth_token_manager/oauth_token_manager.cc
+++ /dev/null
@@ -1,1604 +0,0 @@
-// Copyright 2017 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// OAuthTokenManagerApp is a simple auth service hack for fetching user OAuth
-// tokens to talk programmatically to backend apis. These apis are hosted or
-// integrated with Identity providers such as Google, Twitter, Spotify etc.
-
-#include <iomanip>
-#include <iostream>
-#include <map>
-#include <memory>
-#include <utility>
-
-#include <fuchsia/modular/auth/cpp/fidl.h>
-#include <fuchsia/net/oldhttp/cpp/fidl.h>
-#include <fuchsia/ui/viewsv1/cpp/fidl.h>
-#include <fuchsia/webview/cpp/fidl.h>
-#include <lib/async-loop/cpp/loop.h>
-#include <trace-provider/provider.h>
-
-#include "lib/async/cpp/operation.h"
-#include "lib/component/cpp/connect.h"
-#include "lib/component/cpp/startup_context.h"
-#include "lib/fidl/cpp/interface_request.h"
-#include "lib/fidl/cpp/optional.h"
-#include "lib/fidl/cpp/string.h"
-#include "lib/fsl/socket/strings.h"
-#include "lib/fsl/vmo/strings.h"
-#include "lib/fxl/command_line.h"
-#include "lib/fxl/files/directory.h"
-#include "lib/fxl/files/file.h"
-#include "lib/fxl/files/path.h"
-#include "lib/fxl/functional/make_copyable.h"
-#include "lib/fxl/log_settings_command_line.h"
-#include "lib/fxl/macros.h"
-#include "lib/fxl/strings/join_strings.h"
-#include "lib/fxl/strings/string_number_conversions.h"
-#include "lib/fxl/time/time_point.h"
-#include "lib/svc/cpp/services.h"
-#include "rapidjson/document.h"
-#include "rapidjson/error/en.h"
-#include "rapidjson/pointer.h"
-#include "rapidjson/prettywriter.h"
-#include "rapidjson/stringbuffer.h"
-#include "rapidjson/writer.h"
-#include "topaz/examples/oauth_token_manager/credentials_generated.h"
-
-namespace {
-
-namespace http = ::fuchsia::net::oldhttp;
-
-using ShortLivedTokenCallback =
-    fit::function<void(std::string, fuchsia::modular::auth::AuthErr)>;
-
-using FirebaseTokenCallback = fit::function<void(
-    fuchsia::modular::auth::FirebaseTokenPtr, fuchsia::modular::auth::AuthErr)>;
-
-namespace {
-
-// TODO(alhaad/ukode): Move the following to a configuration file.
-// NOTE: We are currently using a single client-id in Fuchsia. This is temporary
-// and will change in the future.
-constexpr char kClientId[] =
-    "934259141868-rejmm4ollj1bs7th1vg2ur6antpbug79.apps.googleusercontent.com";
-constexpr char kGoogleOAuthAuthEndpoint[] =
-    "https://accounts.google.com/o/oauth2/v2/auth";
-constexpr char kGoogleOAuthGlifParam[] = "false";
-constexpr char kGoogleOAuthTokenEndpoint[] =
-    "https://www.googleapis.com/oauth2/v4/token";
-constexpr char kGoogleRevokeTokenEndpoint[] =
-    "https://accounts.google.com/o/oauth2/revoke";
-constexpr char kGooglePeopleGetEndpoint[] =
-    "https://www.googleapis.com/plus/v1/people/me";
-constexpr char kFirebaseAuthEndpoint[] =
-    "https://www.googleapis.com/identitytoolkit/v3/relyingparty/"
-    "verifyAssertion";
-constexpr char kRedirectUri[] = "com.google.fuchsia.auth:/oauth2redirect";
-constexpr char kCredentialsFile[] = "/data/v2/creds.db";
-constexpr char kWebViewUrl[] = "web_view";
-
-constexpr auto kScopes = {
-    "openid",
-    "email",
-    "https://www.googleapis.com/auth/admin.directory.user.readonly",
-    "https://www.googleapis.com/auth/assistant",
-    "https://www.googleapis.com/auth/userinfo.email",
-    "https://www.googleapis.com/auth/userinfo.profile",
-    "https://www.googleapis.com/auth/youtube.readonly",
-    "https://www.googleapis.com/auth/contacts",
-    "https://www.googleapis.com/auth/drive.file",
-    "https://www.googleapis.com/auth/plus.login",
-    "https://www.googleapis.com/auth/calendar.readonly"};
-
-// Type of token requested.
-enum TokenType {
-  ACCESS_TOKEN = 0,
-  ID_TOKEN = 1,
-  FIREBASE_JWT_TOKEN = 2,
-};
-
-// Adjusts the token expiration window by a small amount to proactively refresh
-// tokens before the expiry time limit has reached.
-const uint64_t kPaddingForTokenExpiryInS = 600;
-
-template <typename T>
-inline std::string JsonValueToPrettyString(const T& v) {
-  rapidjson::StringBuffer buffer;
-  rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buffer);
-  v.Accept(writer);
-  return buffer.GetString();
-}
-
-// TODO(alhaad/ukode): Don't use a hand-rolled version of this.
-std::string UrlEncode(const std::string& value) {
-  std::ostringstream escaped;
-  escaped.fill('0');
-  escaped << std::hex;
-
-  for (char c : value) {
-    // Keep alphanumeric and other accepted characters intact
-    if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '=' ||
-        c == '&' || c == '+') {
-      escaped << c;
-      continue;
-    }
-
-    // Any other characters are percent-encoded
-    escaped << std::uppercase;
-    escaped << '%' << std::setw(2) << int(static_cast<unsigned char>(c));
-    escaped << std::nouppercase;
-  }
-
-  return escaped.str();
-}
-
-// Checks the supplied Google authentication URL. If the URL indicated the user
-// has aborted the flow or an error occured these are reported as error
-// statuses, otherwise a status of OK is returned. If the URL contains an auth
-// code query parameter, this will be returned in |auth_code|.
-fuchsia::modular::auth::Status ParseAuthCodeFromUrl(const std::string& url,
-                                                    std::string& auth_code) {
-  static const std::string success_prefix =
-      std::string{kRedirectUri} + "?code=";
-  static const std::string cancel_prefix =
-      std::string{kRedirectUri} + "?error=access_denied";
-
-  if (url.find(cancel_prefix) == 0) {
-    return fuchsia::modular::auth::Status::USER_CANCELLED;
-  }
-  if (url.find(success_prefix) != 0) {
-    // The authentication process is still ongoing.
-    return fuchsia::modular::auth::Status::OK;
-  }
-
-  // Take everything up to the next query parameter or hash fragment.
-  auto end_char = url.find_first_of("#&", success_prefix.size());
-  auto length = end_char == std::string::npos
-                    ? std::string::npos
-                    : end_char - success_prefix.size();
-  auto code = url.substr(success_prefix.size(), length);
-
-  // Note: The full auth stack normalizes the code here since the GLIF endpoint
-  // URL-encodes the slash prefix. We omit this normalization since our endpoint
-  // doesn't have that behavior.
-
-  if (code.empty()) {
-    return fuchsia::modular::auth::Status::OAUTH_SERVER_ERROR;
-  } else {
-    auth_code = code;
-    return fuchsia::modular::auth::Status::OK;
-  }
-}
-
-// Read the contents of |kCredentialsFile| into the supplied buffer, validates
-// that these contents are a valid credentials file, and then returns a
-// |::auth::CredentialStore| pointer to the contents.
-const ::auth::CredentialStore* ParseCredsFile(std::string* buffer) {
-  if (!files::IsFile(kCredentialsFile)) {
-    return nullptr;
-  }
-
-  if (!files::ReadFileToString(kCredentialsFile, buffer)) {
-    FXL_LOG(WARNING) << "Unable to read user credential file at: "
-                     << kCredentialsFile;
-    return nullptr;
-  }
-
-  flatbuffers::Verifier verifier(
-      reinterpret_cast<const unsigned char*>(buffer->data()), buffer->size());
-  if (!::auth::VerifyCredentialStoreBuffer(verifier)) {
-    FXL_LOG(WARNING) << "Unable to verify credentials buffer";
-    return nullptr;
-  }
-
-  return ::auth::GetCredentialStore(buffer->data());
-}
-
-// Serializes |::auth::CredentialStore| to the |kCredentialsFIle| on disk.
-bool WriteCredsFile(const std::string& serialized_creds) {
-  // verify file before saving
-  flatbuffers::Verifier verifier(
-      reinterpret_cast<const unsigned char*>(serialized_creds.data()),
-      serialized_creds.size());
-  if (!::auth::VerifyCredentialStoreBuffer(verifier)) {
-    FXL_LOG(ERROR) << "Unable to verify credentials buffer:"
-                   << serialized_creds.data();
-    return false;
-  }
-
-  if (!files::CreateDirectory(files::GetDirectoryName(kCredentialsFile))) {
-    FXL_LOG(ERROR) << "Unable to create directory for " << kCredentialsFile;
-    return false;
-  }
-
-  if (!files::WriteFile(kCredentialsFile, serialized_creds.data(),
-                        serialized_creds.size())) {
-    FXL_LOG(ERROR) << "Unable to write file " << kCredentialsFile;
-    return false;
-  }
-
-  return true;
-}
-
-// Fetch user's refresh token from local credential store. In case of errors
-// or account not found, an empty token is returned.
-std::string GetRefreshTokenFromCredsFile(const std::string& account_id) {
-  if (account_id.empty()) {
-    FXL_LOG(ERROR) << "Account id is empty.";
-    return "";
-  }
-
-  std::string file_buffer;
-  const ::auth::CredentialStore* credentials_storage =
-      ParseCredsFile(&file_buffer);
-  if (credentials_storage == nullptr) {
-    FXL_LOG(ERROR) << "Failed to parse credentials.";
-    return "";
-  }
-
-  for (const auto* credential : *credentials_storage->creds()) {
-    if (credential->account_id()->str() == account_id) {
-      for (const auto* token : *credential->tokens()) {
-        switch (token->identity_provider()) {
-          case ::auth::IdentityProvider_GOOGLE:
-            return token->refresh_token()->str();
-          default:
-            FXL_LOG(WARNING) << "Unrecognized IdentityProvider"
-                             << token->identity_provider();
-        }
-      }
-    }
-  }
-  return "";
-}
-
-// Exactly one of success_callback and failure_callback is ever invoked.
-void Post(const std::string& request_body, http::URLLoader* const url_loader,
-          const std::string& url, const std::function<void()>& success_callback,
-          const std::function<void(fuchsia::modular::auth::Status,
-                                   std::string)>& failure_callback,
-          const std::function<bool(rapidjson::Document)>& set_token_callback) {
-  std::string encoded_request_body(request_body);
-  if (url.find(kFirebaseAuthEndpoint) == std::string::npos) {
-    encoded_request_body = UrlEncode(request_body);
-  }
-
-  fsl::SizedVmo data;
-  auto result = fsl::VmoFromString(encoded_request_body, &data);
-  FXL_VLOG(1) << "Post Data:" << encoded_request_body;
-  FXL_DCHECK(result);
-
-  http::URLRequest request;
-  request.url = url;
-  request.method = "POST";
-  request.auto_follow_redirects = true;
-
-  // Content-length header.
-  http::HttpHeader content_length_header;
-  content_length_header.name = "Content-length";
-  uint64_t data_size = encoded_request_body.length();
-  content_length_header.value = fxl::NumberToString(data_size);
-  request.headers.push_back(std::move(content_length_header));
-
-  // content-type header.
-  http::HttpHeader content_type_header;
-  content_type_header.name = "content-type";
-  if (url.find("identitytoolkit") != std::string::npos) {
-    // set accept header
-    http::HttpHeader accept_header;
-    accept_header.name = "accept";
-    accept_header.value = "application/json";
-    request.headers.push_back(std::move(accept_header));
-
-    // set content_type header
-    content_type_header.value = "application/json";
-  } else {
-    content_type_header.value = "application/x-www-form-urlencoded";
-  }
-  request.headers.push_back(std::move(content_type_header));
-
-  request.body = http::URLBody::New();
-  request.body->set_buffer(std::move(data).ToTransport());
-
-  url_loader->Start(std::move(request), [success_callback, failure_callback,
-                                         set_token_callback](
-                                            http::URLResponse response) {
-    FXL_VLOG(1) << "URL Loader response:"
-                << std::to_string(response.status_code);
-
-    if (response.error) {
-      failure_callback(
-          fuchsia::modular::auth::Status::NETWORK_ERROR,
-          "POST error: " + std::to_string(response.error->code) +
-              " , with description: " + response.error->description->data());
-      return;
-    }
-
-    std::string response_body;
-    if (response.body) {
-      FXL_DCHECK(response.body->is_stream());
-      // TODO(alhaad/ukode): Use non-blocking variant.
-      if (!fsl::BlockingCopyToString(std::move(response.body->stream()),
-                                     &response_body)) {
-        failure_callback(fuchsia::modular::auth::Status::NETWORK_ERROR,
-                         "Failed to read response from socket with status:" +
-                             std::to_string(response.status_code));
-        return;
-      }
-    }
-
-    if (response.status_code != 200) {
-      failure_callback(
-          fuchsia::modular::auth::Status::OAUTH_SERVER_ERROR,
-          "Received status code:" + std::to_string(response.status_code) +
-              ", and response body:" + response_body);
-      return;
-    }
-
-    rapidjson::Document doc;
-    rapidjson::ParseResult ok = doc.Parse(response_body);
-    if (!ok) {
-      std::string error_msg = GetParseError_En(ok.Code());
-      failure_callback(fuchsia::modular::auth::Status::BAD_RESPONSE,
-                       "JSON parse error: " + error_msg);
-      return;
-    };
-    auto result = set_token_callback(std::move(doc));
-    if (result) {
-      success_callback();
-    } else {
-      failure_callback(fuchsia::modular::auth::Status::BAD_RESPONSE,
-                       "Invalid response: " + JsonValueToPrettyString(doc));
-    }
-    return;
-  });
-}
-
-// Exactly one of success_callback and failure_callback is ever invoked.
-void Get(http::URLLoader* const url_loader, const std::string& url,
-         const std::string& access_token,
-         const std::function<void()>& success_callback,
-         const std::function<void(fuchsia::modular::auth::Status status,
-                                  std::string)>& failure_callback,
-         const std::function<bool(rapidjson::Document)>& set_token_callback) {
-  http::URLRequest request;
-  request.url = url;
-  request.method = "GET";
-  request.auto_follow_redirects = true;
-
-  // Set Authorization header.
-  http::HttpHeader auth_header;
-  auth_header.name = "Authorization";
-  auth_header.value = "Bearer " + access_token;
-  request.headers.push_back(std::move(auth_header));
-
-  // set content-type header to json.
-  http::HttpHeader content_type_header;
-  content_type_header.name = "content-type";
-  content_type_header.value = "application/json";
-
-  // set accept header to json
-  http::HttpHeader accept_header;
-  accept_header.name = "accept";
-  accept_header.value = "application/json";
-  request.headers.push_back(std::move(accept_header));
-
-  url_loader->Start(std::move(request), [success_callback, failure_callback,
-                                         set_token_callback](
-                                            http::URLResponse response) {
-    if (response.error) {
-      failure_callback(
-          fuchsia::modular::auth::Status::NETWORK_ERROR,
-          "GET error: " + std::to_string(response.error->code) +
-              " ,with description: " + response.error->description->data());
-      return;
-    }
-
-    std::string response_body;
-    if (response.body) {
-      FXL_DCHECK(response.body->is_stream());
-      // TODO(alhaad/ukode): Use non-blocking variant.
-      if (!fsl::BlockingCopyToString(std::move(response.body->stream()),
-                                     &response_body)) {
-        failure_callback(fuchsia::modular::auth::Status::NETWORK_ERROR,
-                         "Failed to read response from socket with status:" +
-                             std::to_string(response.status_code));
-        return;
-      }
-    }
-
-    if (response.status_code != 200) {
-      failure_callback(
-          fuchsia::modular::auth::Status::OAUTH_SERVER_ERROR,
-          "Status code: " + std::to_string(response.status_code) +
-              " while fetching tokens with error description:" + response_body);
-      return;
-    }
-
-    rapidjson::Document doc;
-    rapidjson::ParseResult ok = doc.Parse(response_body);
-    if (!ok) {
-      std::string error_msg = GetParseError_En(ok.Code());
-      failure_callback(fuchsia::modular::auth::Status::BAD_RESPONSE,
-                       "JSON parse error: " + error_msg);
-      return;
-    };
-    auto result = set_token_callback(std::move(doc));
-    if (result) {
-      success_callback();
-    } else {
-      failure_callback(fuchsia::modular::auth::Status::BAD_RESPONSE,
-                       "Invalid response: " + JsonValueToPrettyString(doc));
-    }
-  });
-}
-
-}  // namespace
-
-// Implementation of the OAuth Token Manager app.
-class OAuthTokenManagerApp : fuchsia::modular::auth::AccountProvider {
- public:
-  OAuthTokenManagerApp(async::Loop* loop);
-
- private:
-  // |AccountProvider|
-  void Initialize(
-      fidl::InterfaceHandle<fuchsia::modular::auth::AccountProviderContext>
-          provider) override;
-
-  // |AccountProvider|
-  void Terminate() override;
-
-  // |AccountProvider|
-  void AddAccount(fuchsia::modular::auth::IdentityProvider identity_provider,
-                  AddAccountCallback callback) override;
-
-  // |AccountProvider|
-  void RemoveAccount(fuchsia::modular::auth::Account account, bool revoke_all,
-                     RemoveAccountCallback callback) override;
-
-  // |AccountProvider|
-  void GetTokenProviderFactory(
-      fidl::StringPtr account_id,
-      fidl::InterfaceRequest<fuchsia::modular::auth::TokenProviderFactory>
-          request) override;
-
-  // Generate a random account id.
-  std::string GenerateAccountId();
-
-  // Refresh access and id tokens.
-  void RefreshToken(const std::string& account_id, const TokenType& token_type,
-                    ShortLivedTokenCallback callback);
-
-  // Refresh firebase tokens.
-  void RefreshFirebaseToken(const std::string& account_id,
-                            const std::string& firebase_api_key,
-                            const std::string& id_token,
-                            FirebaseTokenCallback callback);
-  async::Loop* const loop_;
-
-  std::shared_ptr<component::StartupContext> startup_context_;
-
-  fuchsia::modular::auth::AccountProviderContextPtr account_provider_context_;
-
-  fidl::Binding<fuchsia::modular::auth::AccountProvider> binding_;
-
-  class TokenProviderFactoryImpl;
-  // account_id -> TokenProviderFactoryImpl
-  std::unordered_map<std::string, std::unique_ptr<TokenProviderFactoryImpl>>
-      token_provider_factory_impls_;
-
-  // In-memory cache for short lived firebase auth id tokens. These tokens get
-  // reset on system reboots. Tokens are cached based on the expiration time
-  // set by the Firebase servers. Cache is indexed by firebase api keys.
-  struct FirebaseAuthToken {
-    uint64_t creation_ts;
-    uint64_t expires_in;
-    std::string id_token;
-    std::string local_id;
-    std::string email;
-  };
-
-  // In-memory cache for short lived oauth tokens that resets on system reboots.
-  // Tokens are cached based on the expiration time set by the Identity
-  // provider. Cache is indexed by unique account_ids.
-  struct ShortLivedToken {
-    uint64_t creation_ts;
-    uint64_t expires_in;
-    std::string access_token;
-    std::string id_token;
-    std::map<std::string, FirebaseAuthToken> fb_tokens_;
-  };
-  std::map<std::string, ShortLivedToken> oauth_tokens_;
-
-  // We are using operations here not to guard state across asynchronous calls
-  // but rather to clean up state after an 'operation' is done.
-  // TODO(ukode): All operations are running in a queue now which is
-  // inefficient because we block on operations that could be done in parallel.
-  // Instead we may want to create an operation for what
-  // TokenProviderFactoryImpl::GetFirebaseAuthToken() is doing in an sub
-  // operation queue.
-  modular::OperationQueue operation_queue_;
-
-  class GoogleFirebaseTokensCall;
-  class GoogleOAuthTokensCall;
-  class GoogleUserCredsCall;
-  class GoogleRevokeTokensCall;
-  class GoogleProfileAttributesCall;
-
-  FXL_DISALLOW_COPY_AND_ASSIGN(OAuthTokenManagerApp);
-};
-
-class OAuthTokenManagerApp::TokenProviderFactoryImpl
-    : fuchsia::modular::auth::TokenProviderFactory,
-      fuchsia::modular::auth::TokenProvider {
- public:
-  TokenProviderFactoryImpl(
-      const fidl::StringPtr& account_id, OAuthTokenManagerApp* const app,
-      fidl::InterfaceRequest<fuchsia::modular::auth::TokenProviderFactory>
-          request)
-      : account_id_(account_id), binding_(this, std::move(request)), app_(app) {
-    binding_.set_error_handler([this](zx_status_t status) {
-      app_->token_provider_factory_impls_.erase(account_id_);
-    });
-  }
-
- private:
-  // |TokenProviderFactory|
-  void GetTokenProvider(
-      fidl::StringPtr /*application_url*/,
-      fidl::InterfaceRequest<fuchsia::modular::auth::TokenProvider> request)
-      override {
-    // TODO(alhaad/ukode): Current implementation is agnostic about which
-    // agent is requesting what token. Fix this.
-    token_provider_bindings_.AddBinding(this, std::move(request));
-  }
-
-  // |TokenProvider|
-  void GetAccessToken(GetAccessTokenCallback callback) override {
-    FXL_DCHECK(app_);
-    app_->RefreshToken(account_id_, ACCESS_TOKEN, std::move(callback));
-  }
-
-  // |TokenProvider|
-  void GetIdToken(GetIdTokenCallback callback) override {
-    FXL_DCHECK(app_);
-    app_->RefreshToken(account_id_, ID_TOKEN, std::move(callback));
-  }
-
-  // |TokenProvider|
-  void GetFirebaseAuthToken(fidl::StringPtr firebase_api_key,
-                            GetFirebaseAuthTokenCallback callback) override {
-    FXL_DCHECK(app_);
-
-    // Oauth id token is used as input to fetch firebase auth token.
-    GetIdToken([this, firebase_api_key = firebase_api_key,
-                callback = std::move(callback)](
-                   const std::string id_token,
-                   const fuchsia::modular::auth::AuthErr auth_err) mutable {
-      if (auth_err.status != fuchsia::modular::auth::Status::OK) {
-        FXL_LOG(ERROR) << "Error in refreshing Idtoken.";
-        callback(nullptr, std::move(auth_err));
-        return;
-      }
-
-      app_->RefreshFirebaseToken(account_id_, firebase_api_key, id_token,
-                                 std::move(callback));
-    });
-  }
-
-  // |TokenProvider|
-  void GetClientId(GetClientIdCallback callback) override {
-    callback(kClientId);
-  }
-
-  std::string account_id_;
-  fidl::Binding<fuchsia::modular::auth::TokenProviderFactory> binding_;
-  fidl::BindingSet<fuchsia::modular::auth::TokenProvider>
-      token_provider_bindings_;
-
-  OAuthTokenManagerApp* const app_;
-
-  FXL_DISALLOW_COPY_AND_ASSIGN(TokenProviderFactoryImpl);
-};
-
-class OAuthTokenManagerApp::GoogleFirebaseTokensCall
-    : public modular::Operation<fuchsia::modular::auth::FirebaseTokenPtr,
-                                fuchsia::modular::auth::AuthErr> {
- public:
-  GoogleFirebaseTokensCall(std::string account_id, std::string firebase_api_key,
-                           std::string id_token,
-                           OAuthTokenManagerApp* const app,
-                           FirebaseTokenCallback callback)
-      : Operation("OAuthTokenManagerApp::GoogleFirebaseTokensCall",
-                  fxl::MakeCopyable(std::move(callback))),
-        account_id_(std::move(account_id)),
-        firebase_api_key_(std::move(firebase_api_key)),
-        id_token_(std::move(id_token)),
-        app_(app) {}
-
- private:
-  void Run() override {
-    FlowToken flow{this, &firebase_token_, &auth_err_};
-
-    if (account_id_.empty()) {
-      Failure(flow, fuchsia::modular::auth::Status::BAD_REQUEST,
-              "Account id is empty");
-      return;
-    }
-
-    if (firebase_api_key_.empty()) {
-      Failure(flow, fuchsia::modular::auth::Status::BAD_REQUEST,
-              "Firebase Api key is empty");
-      return;
-    }
-
-    if (id_token_.empty()) {
-      // TODO(ukode): Need to differentiate between deleted users, users that
-      // are not provisioned and Guest mode users. For now, return empty
-      // response in such cases as there is no clear way to differentiate
-      // between regular users and guest users.
-      Success(flow);
-      return;
-    }
-
-    // check cache for existing firebase tokens.
-    bool cacheValid = IsCacheValid();
-    if (!cacheValid) {
-      FetchFirebaseToken(flow);
-    } else {
-      Success(flow);
-    }
-  }
-
-  // Fetch fresh firebase auth token by exchanging idToken from Google.
-  void FetchFirebaseToken(FlowToken flow) {
-    FXL_DCHECK(!id_token_.empty());
-    FXL_DCHECK(!firebase_api_key_.empty());
-
-    // JSON post request body
-    const std::string json_request_body =
-        R"({  "postBody": "id_token=)" + id_token_ +
-        "&providerId=google.com\"," + "   \"returnIdpCredential\": true," +
-        "   \"returnSecureToken\": true," +
-        R"(   "requestUri": "http://localhost")" + "}";
-
-    app_->startup_context_->ConnectToEnvironmentService(
-        http_service_.NewRequest());
-    http_service_->CreateURLLoader(url_loader_.NewRequest());
-
-    std::string url(kFirebaseAuthEndpoint);
-    url += "?key=" + UrlEncode(firebase_api_key_);
-
-    // This flow branches below, so we need to put it in a shared
-    // container from which it can be removed once for all branches.
-    FlowTokenHolder branch{flow};
-
-    Post(json_request_body, url_loader_.get(), url,
-         [this, branch] {
-           std::unique_ptr<FlowToken> flow = branch.Continue();
-           FXL_CHECK(flow);
-           Success(*flow);
-         },
-         [this, branch](const fuchsia::modular::auth::Status status,
-                        const std::string error_message) {
-           std::unique_ptr<FlowToken> flow = branch.Continue();
-           FXL_CHECK(flow);
-           Failure(*flow, status, error_message);
-         },
-         [this](rapidjson::Document doc) {
-           return GetFirebaseToken(std::move(doc));
-         });
-  }
-
-  // Parses firebase jwt auth token from firebase auth endpoint response and
-  // saves it to local token in-memory cache.
-  bool GetFirebaseToken(rapidjson::Document jwt_token) {
-    FXL_VLOG(1) << "Firebase Token: " << JsonValueToPrettyString(jwt_token);
-
-    if (!jwt_token.HasMember("idToken") || !jwt_token.HasMember("localId") ||
-        !jwt_token.HasMember("email") || !jwt_token.HasMember("expiresIn")) {
-      FXL_LOG(ERROR)
-          << "Firebase Token returned from server is missing "
-          << "either idToken or email or localId fields. Returned token: "
-          << JsonValueToPrettyString(jwt_token);
-      return false;
-    }
-
-    uint64_t expiresIn;
-    std::istringstream(jwt_token["expiresIn"].GetString()) >> expiresIn;
-
-    app_->oauth_tokens_[account_id_].fb_tokens_[firebase_api_key_] = {
-        static_cast<uint64_t>(fxl::TimePoint::Now().ToEpochDelta().ToSeconds()),
-        expiresIn,
-        jwt_token["idToken"].GetString(),
-        jwt_token["localId"].GetString(),
-        jwt_token["email"].GetString(),
-    };
-    return true;
-  }
-
-  // Returns true if the firebase tokens stored in cache are still valid and
-  // not expired.
-  bool IsCacheValid() {
-    FXL_DCHECK(app_);
-    FXL_DCHECK(!account_id_.empty());
-    FXL_DCHECK(!firebase_api_key_.empty());
-
-    if (app_->oauth_tokens_[account_id_].fb_tokens_.find(firebase_api_key_) ==
-        app_->oauth_tokens_[account_id_].fb_tokens_.end()) {
-      FXL_VLOG(1) << "Firebase api key: [" << firebase_api_key_
-                  << "] not found in cache.";
-      return false;
-    }
-
-    uint64_t current_ts = fxl::TimePoint::Now().ToEpochDelta().ToSeconds();
-    auto fb_token =
-        app_->oauth_tokens_[account_id_].fb_tokens_[firebase_api_key_];
-    uint64_t creation_ts = fb_token.creation_ts;
-    uint64_t token_expiry = fb_token.expires_in;
-    if ((current_ts - creation_ts) <
-        (token_expiry - kPaddingForTokenExpiryInS)) {
-      FXL_VLOG(1) << "Returning firebase token for api key ["
-                  << firebase_api_key_ << "] from cache. ";
-      return true;
-    }
-
-    return false;
-  }
-
-  void Success(FlowToken /*flow*/) {
-    // Set firebase token
-    firebase_token_ = fuchsia::modular::auth::FirebaseToken::New();
-    if (id_token_.empty()) {
-      firebase_token_->id_token = "";
-      firebase_token_->local_id = "";
-      firebase_token_->email = "";
-    } else {
-      auto fb_token =
-          app_->oauth_tokens_[account_id_].fb_tokens_[firebase_api_key_];
-      firebase_token_->id_token = fb_token.id_token;
-      firebase_token_->local_id = fb_token.local_id;
-      firebase_token_->email = fb_token.email;
-    }
-
-    // Set status to success
-    auth_err_.status = fuchsia::modular::auth::Status::OK;
-    auth_err_.message = "";
-  }
-
-  void Failure(FlowToken /*flow*/, const fuchsia::modular::auth::Status& status,
-               const std::string& error_message) {
-    FXL_LOG(ERROR) << "Failed with error status:" << fidl::ToUnderlying(status)
-                   << " ,and message:" << error_message;
-    auth_err_.status = status;
-    auth_err_.message = error_message;
-  }
-
-  const std::string account_id_;
-  const std::string firebase_api_key_;
-  const std::string id_token_;
-  OAuthTokenManagerApp* const app_;
-
-  fuchsia::modular::auth::FirebaseTokenPtr firebase_token_;
-  fuchsia::modular::auth::AuthErr auth_err_;
-
-  http::HttpServicePtr http_service_;
-  http::URLLoaderPtr url_loader_;
-
-  FXL_DISALLOW_COPY_AND_ASSIGN(GoogleFirebaseTokensCall);
-};
-
-class OAuthTokenManagerApp::GoogleOAuthTokensCall
-    : public modular::Operation<fidl::StringPtr,
-                                fuchsia::modular::auth::AuthErr> {
- public:
-  GoogleOAuthTokensCall(std::string account_id, const TokenType& token_type,
-                        OAuthTokenManagerApp* const app,
-                        ShortLivedTokenCallback callback)
-      : Operation("OAuthTokenManagerApp::GoogleOAuthTokensCall",
-                  fxl::MakeCopyable(std::move(callback))),
-        account_id_(std::move(account_id)),
-        token_type_(token_type),
-        app_(app) {}
-
- private:
-  void Run() override {
-    FlowToken flow{this, &result_, &auth_err_};
-
-    if (account_id_.empty()) {
-      Failure(flow, fuchsia::modular::auth::Status::BAD_REQUEST,
-              "Account id is empty.");
-      return;
-    }
-
-    FXL_VLOG(1) << "Fetching access/id tokens for Account_ID:" << account_id_;
-
-    // Use an entry from the cache if one exists
-    bool cacheValid = IsCacheValid();
-    if (cacheValid) {
-      Success(flow);  // fetching tokens from local cache.
-      return;
-    }
-
-    // Check if the user has a stored refesh token
-    const std::string refresh_token = GetRefreshTokenFromCredsFile(account_id_);
-    if (refresh_token.empty()) {
-      // TODO(ukode): Need to differentiate between deleted users, users that
-      // are not provisioned and Guest mode users. For now, return empty
-      // response in such cases as there is no clear way to differentiate
-      // between regular users and guest users.
-      Success(flow);
-    } else {
-      // Use this refresh token to generate and cache new short lived tokens.
-      FetchAccessAndIdToken(refresh_token, flow);
-    }
-  }
-
-  // Fetch fresh access and id tokens by exchanging refresh token from Google
-  // token endpoint.
-  void FetchAccessAndIdToken(const std::string& refresh_token, FlowToken flow) {
-    FXL_CHECK(!refresh_token.empty());
-
-    const std::string request_body = "refresh_token=" + refresh_token +
-                                     "&client_id=" + kClientId +
-                                     "&grant_type=refresh_token";
-
-    app_->startup_context_->ConnectToEnvironmentService(
-        http_service_.NewRequest());
-    http_service_->CreateURLLoader(url_loader_.NewRequest());
-
-    // This flow exlusively branches below, so we need to put it in a shared
-    // container from which it can be removed once for all branches.
-    FlowTokenHolder branch{flow};
-
-    Post(request_body, url_loader_.get(), kGoogleOAuthTokenEndpoint,
-         [this, branch] {
-           std::unique_ptr<FlowToken> flow = branch.Continue();
-           FXL_CHECK(flow);
-           Success(*flow);
-         },
-         [this, branch](const fuchsia::modular::auth::Status status,
-                        const std::string error_message) {
-           std::unique_ptr<FlowToken> flow = branch.Continue();
-           FXL_CHECK(flow);
-           Failure(*flow, status, error_message);
-         },
-         [this](rapidjson::Document doc) {
-           return GetShortLivedTokens(std::move(doc));
-         });
-  }
-
-  // Parse access and id tokens from OAUth endpoints into local token in-memory
-  // cache.
-  bool GetShortLivedTokens(rapidjson::Document tokens) {
-    if (!tokens.HasMember("access_token")) {
-      FXL_LOG(ERROR) << "Tokens returned from server does not contain "
-                     << "access_token. Returned token: "
-                     << JsonValueToPrettyString(tokens);
-      return false;
-    };
-
-    if ((token_type_ == ID_TOKEN) && !tokens.HasMember("id_token")) {
-      FXL_LOG(ERROR) << "Tokens returned from server does not contain "
-                     << "id_token. Returned token: "
-                     << JsonValueToPrettyString(tokens);
-      return false;
-    }
-
-    // Add the token generation timestamp to |tokens| for caching.
-    uint64_t creation_ts = fxl::TimePoint::Now().ToEpochDelta().ToSeconds();
-    app_->oauth_tokens_[account_id_] = {
-        creation_ts,
-        tokens["expires_in"].GetUint64(),
-        tokens["access_token"].GetString(),
-        tokens["id_token"].GetString(),
-        std::map<std::string, FirebaseAuthToken>(),
-    };
-
-    return true;
-  }
-
-  // Returns true if the access and idtokens stored in cache are still valid and
-  // not expired.
-  bool IsCacheValid() {
-    FXL_DCHECK(app_);
-    FXL_DCHECK(!account_id_.empty());
-
-    if (app_->oauth_tokens_.find(account_id_) == app_->oauth_tokens_.end()) {
-      FXL_VLOG(1) << "Account: [" << account_id_ << "] not found in cache.";
-      return false;
-    }
-
-    uint64_t current_ts = fxl::TimePoint::Now().ToEpochDelta().ToSeconds();
-    uint64_t creation_ts = app_->oauth_tokens_[account_id_].creation_ts;
-    uint64_t token_expiry = app_->oauth_tokens_[account_id_].expires_in;
-    if ((current_ts - creation_ts) <
-        (token_expiry - kPaddingForTokenExpiryInS)) {
-      FXL_VLOG(1) << "Returning access/id tokens for account [" << account_id_
-                  << "] from cache. ";
-      return true;
-    }
-
-    return false;
-  }
-
-  void Success(FlowToken flow) {
-    if (app_->oauth_tokens_.find(account_id_) == app_->oauth_tokens_.end()) {
-      // In guest mode, return empty tokens.
-      result_ = "";
-    } else {
-      switch (token_type_) {
-        case ACCESS_TOKEN:
-          result_ = app_->oauth_tokens_[account_id_].access_token;
-          break;
-        case ID_TOKEN:
-          result_ = app_->oauth_tokens_[account_id_].id_token;
-          break;
-        case FIREBASE_JWT_TOKEN:
-          Failure(flow, fuchsia::modular::auth::Status::INTERNAL_ERROR,
-                  "invalid token type");
-      }
-    }
-
-    // Set status to success
-    auth_err_.status = fuchsia::modular::auth::Status::OK;
-    auth_err_.message = "";
-  }
-
-  void Failure(FlowToken /*flow*/, const fuchsia::modular::auth::Status& status,
-               const std::string& error_message) {
-    FXL_LOG(ERROR) << "Failed with error status:" << fidl::ToUnderlying(status)
-                   << " ,and message:" << error_message;
-    auth_err_.status = status;
-    auth_err_.message = error_message;
-  }
-
-  const std::string account_id_;
-  const std::string firebase_api_key_;
-  TokenType token_type_;
-  OAuthTokenManagerApp* const app_;
-
-  http::HttpServicePtr http_service_;
-  http::URLLoaderPtr url_loader_;
-
-  fidl::StringPtr result_;
-  fuchsia::modular::auth::AuthErr auth_err_;
-
-  FXL_DISALLOW_COPY_AND_ASSIGN(GoogleOAuthTokensCall);
-};
-
-// TODO(alhaad): Use variadic template in |Operation|. That way, parameters to
-// |callback| can be returned as parameters to |Done()|.
-class OAuthTokenManagerApp::GoogleUserCredsCall
-    : public modular::Operation<>,
-      fuchsia::webview::WebRequestDelegate {
- public:
-  GoogleUserCredsCall(fuchsia::modular::auth::AccountPtr account,
-                      OAuthTokenManagerApp* const app,
-                      AddAccountCallback callback)
-      : Operation("OAuthTokenManagerApp::GoogleUserCredsCall", [] {}),
-        account_(std::move(account)),
-        app_(app),
-        callback_(std::move(callback)) {}
-
- private:
-  // |Operation|
-  void Run() override {
-    // No FlowToken used here; calling Done() directly is more suitable,
-    // because of the flow of control through
-    // fuchsia::webview::WebRequestDelegate.
-
-    auto view_owner = SetupWebView();
-
-    // Set a delegate which will parse incoming URLs for authorization code.
-    // TODO(alhaad/ukode): We need to set a timout here in-case we do not get
-    // the code.
-    fuchsia::webview::WebRequestDelegatePtr web_request_delegate;
-    web_request_delegate_bindings_.AddBinding(
-        this, web_request_delegate.NewRequest());
-    web_view_->SetWebRequestDelegate(std::move(web_request_delegate));
-
-    web_view_->ClearCookies();
-
-    const std::vector<std::string> scopes(kScopes.begin(), kScopes.end());
-    std::string joined_scopes = fxl::JoinStrings(scopes, "+");
-
-    std::string url = kGoogleOAuthAuthEndpoint;
-    url += "?scope=" + joined_scopes;
-    url += "&response_type=code&redirect_uri=";
-    url += kRedirectUri;
-    url += "&glif=";
-    url += kGoogleOAuthGlifParam;
-    url += "&client_id=";
-    url += kClientId;
-
-    web_view_->SetUrl(url);
-
-    app_->account_provider_context_->GetAuthenticationContext(
-        account_->id, auth_context_.NewRequest());
-
-    auth_context_.set_error_handler([this](zx_status_t status) {
-      callback_(nullptr, "Overlay cancelled by base shell.");
-      Done();
-    });
-    auth_context_->StartOverlay(std::move(view_owner));
-  }
-
-  // |fuchsia::webview::WebRequestDelegate|
-  void WillSendRequest(fidl::StringPtr incoming_url) override {
-    std::string auth_code;
-    fuchsia::modular::auth::Status status =
-        ParseAuthCodeFromUrl(incoming_url.get(), auth_code);
-
-    if (status != fuchsia::modular::auth::Status::OK) {
-      Failure(status, "User cancelled OAuth flow");
-    } else if (auth_code.empty()) {
-      // Authentication is ongoing.
-      return;
-    }
-
-    // User accepted OAuth permissions - close the webview and exchange auth
-    // code to long lived credential.
-    // Also, de-register previously registered error callbacks since calling
-    // StopOverlay() might cause this connection to be closed.
-    auth_context_.set_error_handler([](zx_status_t status) {});
-    auth_context_->StopOverlay();
-
-    const std::string request_body =
-        "code=" + auth_code + "&redirect_uri=" + kRedirectUri +
-        "&client_id=" + kClientId + "&grant_type=authorization_code";
-
-    app_->startup_context_->ConnectToEnvironmentService(
-        http_service_.NewRequest());
-    http_service_->CreateURLLoader(url_loader_.NewRequest());
-
-    Post(request_body, url_loader_.get(), kGoogleOAuthTokenEndpoint,
-         [this] { Success(); },
-         [this](const fuchsia::modular::auth::Status status,
-                const std::string error_message) {
-           Failure(status, error_message);
-         },
-         [this](rapidjson::Document doc) {
-           return ProcessCredentials(std::move(doc));
-         });
-  }
-
-  // Parses refresh tokens from auth endpoint response and persists it in
-  // |kCredentialsFile|.
-  bool ProcessCredentials(rapidjson::Document tokens) {
-    if (!tokens.HasMember("refresh_token") ||
-        !tokens.HasMember("access_token")) {
-      FXL_LOG(ERROR) << "Tokens returned from server does not contain "
-                     << "refresh_token or access_token. Returned token: "
-                     << JsonValueToPrettyString(tokens);
-      return false;
-    };
-
-    if (!SaveCredentials(tokens["refresh_token"].GetString())) {
-      return false;
-    }
-
-    // Store short lived tokens local in-memory cache.
-    uint64_t creation_ts = fxl::TimePoint::Now().ToEpochDelta().ToSeconds();
-    app_->oauth_tokens_[account_->id] = {
-        creation_ts,
-        tokens["expires_in"].GetUint64(),
-        tokens["access_token"].GetString(),
-        tokens["id_token"].GetString(),
-        std::map<std::string, FirebaseAuthToken>(),
-    };
-    return true;
-  }
-
-  // Saves new credentials to the persistent creds storage file.
-  bool SaveCredentials(const std::string& refresh_token) {
-    flatbuffers::FlatBufferBuilder builder;
-    std::vector<flatbuffers::Offset<::auth::UserCredential>> creds;
-
-    std::string file_buffer;
-    const ::auth::CredentialStore* file_creds = ParseCredsFile(&file_buffer);
-    if (file_creds != nullptr) {
-      // Reserialize existing users.
-      for (const auto* cred : *file_creds->creds()) {
-        if (cred->account_id()->str() == account_->id) {
-          // Update existing credentials
-          continue;
-        }
-
-        std::vector<flatbuffers::Offset<::auth::IdpCredential>> idp_creds;
-        for (const auto* idp_cred : *cred->tokens()) {
-          idp_creds.push_back(::auth::CreateIdpCredential(
-              builder, idp_cred->identity_provider(),
-              builder.CreateString(idp_cred->refresh_token())));
-        }
-
-        creds.push_back(::auth::CreateUserCredential(
-            builder, builder.CreateString(cred->account_id()),
-            builder.CreateVector<flatbuffers::Offset<::auth::IdpCredential>>(
-                idp_creds)));
-      }
-    }
-
-    // add the new credential for |account_->id|.
-    std::vector<flatbuffers::Offset<::auth::IdpCredential>> new_idp_creds;
-    new_idp_creds.push_back(
-        ::auth::CreateIdpCredential(builder, ::auth::IdentityProvider_GOOGLE,
-                                    builder.CreateString(refresh_token)));
-
-    creds.push_back(::auth::CreateUserCredential(
-        builder, builder.CreateString(account_->id),
-        builder.CreateVector<flatbuffers::Offset<::auth::IdpCredential>>(
-            new_idp_creds)));
-
-    builder.Finish(
-        ::auth::CreateCredentialStore(builder, builder.CreateVector(creds)));
-
-    std::string new_serialized_creds = std::string(
-        reinterpret_cast<const char*>(builder.GetCurrentBufferPointer()),
-        builder.GetSize());
-
-    return WriteCredsFile(new_serialized_creds);
-  }
-
-  void Success() {
-    callback_(std::move(account_), nullptr);
-    Done();
-  }
-
-  void Failure(const fuchsia::modular::auth::Status& status,
-               const std::string& error_message) {
-    FXL_LOG(ERROR) << "Failed with error status:" << fidl::ToUnderlying(status)
-                   << " ,and message:" << error_message;
-    callback_(nullptr, error_message);
-    auth_context_.set_error_handler([](zx_status_t status) {});
-    auth_context_->StopOverlay();
-    Done();
-  }
-
-  fuchsia::ui::viewsv1token::ViewOwnerPtr SetupWebView() {
-    component::Services web_view_services;
-    fuchsia::sys::LaunchInfo web_view_launch_info;
-    web_view_launch_info.url = kWebViewUrl;
-    web_view_launch_info.directory_request = web_view_services.NewRequest();
-    app_->startup_context_->launcher()->CreateComponent(
-        std::move(web_view_launch_info), web_view_controller_.NewRequest());
-    web_view_controller_.set_error_handler([this](zx_status_t status) {
-      FXL_CHECK(false) << "web_view not found at " << kWebViewUrl << ".";
-    });
-
-    fuchsia::ui::viewsv1token::ViewOwnerPtr view_owner;
-    fuchsia::ui::viewsv1::ViewProviderPtr view_provider;
-    web_view_services.ConnectToService(view_provider.NewRequest());
-    fuchsia::sys::ServiceProviderPtr web_view_moz_services;
-    view_provider->CreateView(view_owner.NewRequest(),
-                              web_view_moz_services.NewRequest());
-
-    component::ConnectToService(web_view_moz_services.get(),
-                                web_view_.NewRequest());
-
-    return view_owner;
-  }
-
-  fuchsia::modular::auth::AccountPtr account_;
-  OAuthTokenManagerApp* const app_;
-  const AddAccountCallback callback_;
-
-  fuchsia::modular::auth::AuthenticationContextPtr auth_context_;
-
-  fuchsia::webview::WebViewPtr web_view_;
-  fuchsia::sys::ComponentControllerPtr web_view_controller_;
-
-  http::HttpServicePtr http_service_;
-  http::URLLoaderPtr url_loader_;
-
-  fidl::BindingSet<fuchsia::webview::WebRequestDelegate>
-      web_request_delegate_bindings_;
-
-  FXL_DISALLOW_COPY_AND_ASSIGN(GoogleUserCredsCall);
-};
-
-class OAuthTokenManagerApp::GoogleRevokeTokensCall
-    : public modular::Operation<fuchsia::modular::auth::AuthErr> {
- public:
-  GoogleRevokeTokensCall(fuchsia::modular::auth::AccountPtr account,
-                         bool revoke_all, OAuthTokenManagerApp* const app,
-                         RemoveAccountCallback callback)
-      : Operation("OAuthTokenManagerApp::GoogleRevokeTokensCall",
-                  fxl::MakeCopyable(callback.share())),
-        account_(std::move(account)),
-        revoke_all_(revoke_all),
-        app_(app),
-        callback_(callback.share()) {}
-
- private:
-  // |Operation|
-  void Run() override {
-    FlowToken flow{this, &auth_err_};
-
-    if (!account_) {
-      Failure(flow, fuchsia::modular::auth::Status::BAD_REQUEST,
-              "Account is null.");
-      return;
-    }
-
-    switch (account_->identity_provider) {
-      case fuchsia::modular::auth::IdentityProvider::DEV:
-        Success(flow);  // guest mode
-        return;
-      case fuchsia::modular::auth::IdentityProvider::GOOGLE:
-        break;
-      default:
-        Failure(flow, fuchsia::modular::auth::Status::BAD_REQUEST,
-                "Unsupported IDP.");
-        return;
-    }
-
-    // If there is a cache entry always ensure its deleted
-    app_->oauth_tokens_.erase(account_->id);
-
-    // If no credentials exist in the database we are now done.
-    const std::string refresh_token =
-        GetRefreshTokenFromCredsFile(account_->id);
-    if (refresh_token.empty()) {
-      FXL_LOG(ERROR) << "Account: " << account_->id << " not found.";
-      Success(flow);  // Maybe a guest account.
-      return;
-    }
-
-    // Delete user credentials from local persistent storage.
-    if (!DeleteCredentials()) {
-      Failure(flow, fuchsia::modular::auth::Status::INTERNAL_ERROR,
-              "Unable to delete persistent credentials for account:" +
-                  std::string(account_->id));
-      return;
-    }
-
-    if (!revoke_all_) {
-      Success(flow);
-      return;
-    }
-
-    // Revoke persistent tokens on backend IDP server.
-    app_->startup_context_->ConnectToEnvironmentService(
-        http_service_.NewRequest());
-    http_service_->CreateURLLoader(url_loader_.NewRequest());
-
-    std::string url = kGoogleRevokeTokenEndpoint + std::string("?token=");
-    url += refresh_token;
-
-    std::string request_body;
-
-    // This flow branches below, so we need to put it in a shared container
-    // from which it can be removed once for all branches.
-    FlowTokenHolder branch{flow};
-
-    Post(request_body, url_loader_.get(), url,
-         [this, branch] {
-           std::unique_ptr<FlowToken> flow = branch.Continue();
-           FXL_CHECK(flow);
-           Success(*flow);
-         },
-         [this, branch](const fuchsia::modular::auth::Status status,
-                        const std::string error_message) {
-           std::unique_ptr<FlowToken> flow = branch.Continue();
-           FXL_CHECK(flow);
-           Failure(*flow, status, error_message);
-         },
-         [this](rapidjson::Document doc) {
-           return RevokeAllTokens(std::move(doc));
-         });
-  }
-
-  // Deletes existing user credentials for |account_->id|.
-  bool DeleteCredentials() {
-    std::string file_buffer;
-    const ::auth::CredentialStore* credentials_storage =
-        ParseCredsFile(&file_buffer);
-    if (credentials_storage == nullptr) {
-      FXL_LOG(ERROR) << "Failed to parse credentials.";
-      return false;
-    }
-
-    // Delete |account_->id| credentials and reserialize existing users.
-    flatbuffers::FlatBufferBuilder builder;
-    std::vector<flatbuffers::Offset<::auth::UserCredential>> creds;
-
-    for (const auto* cred : *credentials_storage->creds()) {
-      if (cred->account_id()->str() == account_->id) {
-        // Delete existing credentials
-        continue;
-      }
-
-      std::vector<flatbuffers::Offset<::auth::IdpCredential>> idp_creds;
-      for (const auto* idp_cred : *cred->tokens()) {
-        idp_creds.push_back(::auth::CreateIdpCredential(
-            builder, idp_cred->identity_provider(),
-            builder.CreateString(idp_cred->refresh_token())));
-      }
-
-      creds.push_back(::auth::CreateUserCredential(
-          builder, builder.CreateString(cred->account_id()),
-          builder.CreateVector<flatbuffers::Offset<::auth::IdpCredential>>(
-              idp_creds)));
-    }
-
-    builder.Finish(
-        ::auth::CreateCredentialStore(builder, builder.CreateVector(creds)));
-
-    std::string new_serialized_creds = std::string(
-        reinterpret_cast<const char*>(builder.GetCurrentBufferPointer()),
-        builder.GetSize());
-
-    return WriteCredsFile(new_serialized_creds);
-  }
-
-  // Invalidate both refresh and access tokens on backend IDP server.
-  // If the revocation is successfully processed, then the status code of the
-  // response is 200. For error conditions, a status code 400 is returned along
-  // with an error code in the response body.
-  bool RevokeAllTokens(rapidjson::Document status) {
-    FXL_VLOG(1) << "Revoke token api response: "
-                << JsonValueToPrettyString(status);
-
-    return true;
-  }
-
-  void Success(FlowToken /*flow*/) {
-    // Set status to success
-    auth_err_.status = fuchsia::modular::auth::Status::OK;
-    auth_err_.message = "";
-  }
-
-  void Failure(FlowToken /*flow*/, const fuchsia::modular::auth::Status& status,
-               const std::string& error_message) {
-    FXL_LOG(ERROR) << "Failed with error status:" << fidl::ToUnderlying(status)
-                   << " ,and message:" << error_message;
-    auth_err_.status = status;
-    auth_err_.message = error_message;
-  }
-
-  fuchsia::modular::auth::AccountPtr account_;
-  // By default, RemoveAccount deletes account only from the device where the
-  // user performed the operation.
-  bool revoke_all_ = false;
-  OAuthTokenManagerApp* const app_;
-  const RemoveAccountCallback callback_;
-
-  http::HttpServicePtr http_service_;
-  http::URLLoaderPtr url_loader_;
-
-  fuchsia::modular::auth::AuthErr auth_err_;
-
-  FXL_DISALLOW_COPY_AND_ASSIGN(GoogleRevokeTokensCall);
-};
-
-class OAuthTokenManagerApp::GoogleProfileAttributesCall
-    : public modular::Operation<> {
- public:
-  GoogleProfileAttributesCall(fuchsia::modular::auth::AccountPtr account,
-                              OAuthTokenManagerApp* const app,
-                              AddAccountCallback callback)
-      : Operation("OAuthTokenManagerApp::GoogleProfileAttributesCall", [] {}),
-        account_(std::move(account)),
-        app_(app),
-        callback_(std::move(callback)) {}
-
- private:
-  // |Operation|
-  void Run() override {
-    if (!account_) {
-      Failure(fuchsia::modular::auth::Status::BAD_REQUEST, "Account is null.");
-      return;
-    }
-
-    if (app_->oauth_tokens_.find(account_->id) == app_->oauth_tokens_.end()) {
-      FXL_LOG(ERROR) << "Account: " << account_->id << " not found.";
-      Success();  // Maybe a guest account.
-      return;
-    }
-
-    const std::string access_token =
-        app_->oauth_tokens_[account_->id].access_token;
-    app_->startup_context_->ConnectToEnvironmentService(
-        http_service_.NewRequest());
-    http_service_->CreateURLLoader(url_loader_.NewRequest());
-
-    // Fetch profile atrributes for the provisioned user using
-    // https://developers.google.com/+/web/api/rest/latest/people/get api.
-    Get(url_loader_.get(), kGooglePeopleGetEndpoint, access_token,
-        [this] { Success(); },
-        [this](const fuchsia::modular::auth::Status status,
-               const std::string error_message) {
-          Failure(status, error_message);
-        },
-        [this](rapidjson::Document doc) {
-          return SetAccountAttributes(std::move(doc));
-        });
-  }
-
-  // Populate profile urls and display name for the account.
-  bool SetAccountAttributes(rapidjson::Document attributes) {
-    FXL_VLOG(1) << "People:get api response: "
-                << JsonValueToPrettyString(attributes);
-
-    if (!account_) {
-      return false;
-    }
-
-    if (attributes.HasMember("id")) {
-      account_->profile_id = attributes["id"].GetString();
-    }
-    if (account_->profile_id.is_null()) {
-      account_->profile_id = "";
-    }
-
-    if (attributes.HasMember("displayName")) {
-      account_->display_name = attributes["displayName"].GetString();
-    }
-    if (account_->display_name.is_null()) {
-      account_->display_name = "";
-    }
-
-    if (attributes.HasMember("url")) {
-      account_->url = attributes["url"].GetString();
-    } else {
-      account_->url = "";
-    }
-
-    if (attributes.HasMember("image")) {
-      account_->image_url = attributes["image"]["url"].GetString();
-    } else {
-      account_->image_url = "";
-    }
-
-    return true;
-  }
-
-  void Success() {
-    callback_(std::move(account_), nullptr);
-    Done();
-  }
-
-  void Failure(const fuchsia::modular::auth::Status& status,
-               const std::string& error_message) {
-    FXL_LOG(ERROR) << "Failed with error status:" << fidl::ToUnderlying(status)
-                   << " ,and message:" << error_message;
-
-    // Account is missing profile attributes, but still valid.
-    callback_(std::move(account_), error_message);
-    Done();
-  }
-
-  fuchsia::modular::auth::AccountPtr account_;
-  OAuthTokenManagerApp* const app_;
-  const AddAccountCallback callback_;
-
-  http::HttpServicePtr http_service_;
-  http::URLLoaderPtr url_loader_;
-
-  FXL_DISALLOW_COPY_AND_ASSIGN(GoogleProfileAttributesCall);
-};
-
-OAuthTokenManagerApp::OAuthTokenManagerApp(async::Loop* loop)
-    : loop_(loop),
-      startup_context_(component::StartupContext::CreateFromStartupInfo()),
-      binding_(this) {
-  startup_context_->outgoing().AddPublicService<AccountProvider>(
-      [this](fidl::InterfaceRequest<AccountProvider> request) {
-        binding_.Bind(std::move(request));
-      });
-  // Log an error if the existing credential file is invalid.
-  if (files::IsFile(kCredentialsFile)) {
-    std::string file_buffer;
-    if (ParseCredsFile(&file_buffer) == nullptr) {
-      FXL_LOG(WARNING) << "Error in parsing existing credentials from: "
-                       << kCredentialsFile;
-    }
-  }
-}
-
-void OAuthTokenManagerApp::Initialize(
-    fidl::InterfaceHandle<fuchsia::modular::auth::AccountProviderContext>
-        provider) {
-  FXL_VLOG(1) << "OAuthTokenManagerApp::Initialize()";
-  account_provider_context_.Bind(std::move(provider));
-}
-
-void OAuthTokenManagerApp::Terminate() {
-  FXL_LOG(INFO) << "OAuthTokenManagerApp::Terminate()";
-  loop_->Quit();
-}
-
-// TODO(alhaad): Check if account id already exists.
-std::string OAuthTokenManagerApp::GenerateAccountId() {
-  uint32_t random_number = 0;
-  zx_cprng_draw(&random_number, sizeof(random_number));
-  return std::to_string(random_number);
-}
-
-void OAuthTokenManagerApp::AddAccount(
-    fuchsia::modular::auth::IdentityProvider identity_provider,
-    AddAccountCallback callback) {
-  FXL_VLOG(1) << "OAuthTokenManagerApp::AddAccount()";
-  auto account = fuchsia::modular::auth::Account::New();
-  account->id = GenerateAccountId();
-  account->identity_provider = identity_provider;
-  account->profile_id = "";
-  account->display_name = "";
-  account->url = "";
-  account->image_url = "";
-
-  switch (identity_provider) {
-    case fuchsia::modular::auth::IdentityProvider::DEV:
-      callback(std::move(account), nullptr);
-      return;
-    case fuchsia::modular::auth::IdentityProvider::GOOGLE:
-      operation_queue_.Add(new GoogleUserCredsCall(
-          std::move(account), this,
-          [this, callback = std::move(callback)](
-              fuchsia::modular::auth::AccountPtr account,
-              const fidl::StringPtr error_msg) mutable {
-            if (error_msg) {
-              callback(nullptr, error_msg);
-              return;
-            }
-
-            operation_queue_.Add(new GoogleProfileAttributesCall(
-                std::move(account), this, std::move(callback)));
-          }));
-      return;
-    default:
-      callback(nullptr, "Unrecognized Identity Provider");
-  }
-}
-
-void OAuthTokenManagerApp::RemoveAccount(
-    fuchsia::modular::auth::Account account, bool revoke_all,
-    RemoveAccountCallback callback) {
-  FXL_VLOG(1) << "OAuthTokenManagerApp::RemoveAccount()";
-  operation_queue_.Add(
-      new GoogleRevokeTokensCall(fidl::MakeOptional(std::move(account)),
-                                 revoke_all, this, std::move(callback)));
-}
-
-void OAuthTokenManagerApp::GetTokenProviderFactory(
-    fidl::StringPtr account_id,
-    fidl::InterfaceRequest<fuchsia::modular::auth::TokenProviderFactory>
-        request) {
-  new TokenProviderFactoryImpl(account_id, this, std::move(request));
-}
-
-void OAuthTokenManagerApp::RefreshToken(const std::string& account_id,
-                                        const TokenType& token_type,
-                                        ShortLivedTokenCallback callback) {
-  FXL_VLOG(1) << "OAuthTokenManagerApp::RefreshToken()";
-  operation_queue_.Add(new GoogleOAuthTokensCall(account_id, token_type, this,
-                                                 std::move(callback)));
-}
-
-void OAuthTokenManagerApp::RefreshFirebaseToken(
-    const std::string& account_id, const std::string& firebase_api_key,
-    const std::string& id_token, FirebaseTokenCallback callback) {
-  FXL_VLOG(1) << "OAuthTokenManagerApp::RefreshFirebaseToken()";
-  operation_queue_.Add(new GoogleFirebaseTokensCall(
-      account_id, firebase_api_key, id_token, this, std::move(callback)));
-}
-
-}  // namespace
-
-int main(int argc, const char** argv) {
-  auto command_line = fxl::CommandLineFromArgcArgv(argc, argv);
-  if (!fxl::SetLogSettingsFromCommandLine(command_line)) {
-    return 1;
-  }
-
-  async::Loop loop(&kAsyncLoopConfigAttachToThread);
-  trace::TraceProvider trace_provider(loop.dispatcher());
-
-  OAuthTokenManagerApp app(&loop);
-  loop.Run();
-  return 0;
-}
diff --git a/packages/prod/all b/packages/prod/all
index 085daa6..7b23308 100644
--- a/packages/prod/all
+++ b/packages/prod/all
@@ -25,7 +25,6 @@
         "topaz/packages/prod/maxwell",
         "topaz/packages/prod/modules_index",
         "topaz/packages/prod/mondrian",
-        "topaz/packages/prod/oauth_token_manager",
         "topaz/packages/prod/perspective",
         "topaz/packages/prod/skottie_viewer",
         "topaz/packages/prod/spotify_auth_provider",
diff --git a/packages/prod/oauth_token_manager b/packages/prod/oauth_token_manager
deleted file mode 100644
index aa38316..0000000
--- a/packages/prod/oauth_token_manager
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-    "packages": [
-        "//topaz/examples/oauth_token_manager"
-    ]
-}
diff --git a/packages/products/ermine b/packages/products/ermine
index ac0ffa1..d828258 100644
--- a/packages/products/ermine
+++ b/packages/products/ermine
@@ -10,7 +10,6 @@
         "topaz/packages/config/ermine",
         "topaz/packages/examples/noodles",
         "topaz/packages/prod/dashboard",
-        "topaz/packages/prod/oauth_token_manager",
         "topaz/packages/prod/sysui",
         "topaz/packages/prod/term",
         "topaz/packages/prod/web_runner_prototype"