// Copyright 2018 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.

#include "topaz/auth_providers/google/google_auth_provider_impl.h"

#include <fuchsia/net/oldhttp/cpp/fidl.h>
#include <fuchsia/ui/app/cpp/fidl.h>
#include <lib/fdio/util.h>
#include <lib/fit/function.h>
#include <lib/syslog/global.h>

#include "lib/component/cpp/connect.h"
#include "lib/component/cpp/startup_context.h"
#include "lib/fidl/cpp/interface_request.h"
#include "lib/fxl/strings/join_strings.h"
#include "lib/svc/cpp/services.h"
#include "peridot/lib/rapidjson/rapidjson.h"
#include "rapidjson/document.h"
#include "topaz/auth_providers/google/constants.h"
#include "topaz/auth_providers/oauth/oauth_request_builder.h"
#include "topaz/auth_providers/oauth/oauth_response.h"

namespace google_auth_provider {

namespace http = ::fuchsia::net::oldhttp;

namespace {

std::string GetClientId(const std::string& app_client_id) {
  // By default, use the client_id of the invoking application.
  std::string client_id = app_client_id;

  // Use hard-coded Fuchsia client_id for downscoped tokens, if |app_client_id|
  // is missing.
  if (app_client_id.empty()) {
    client_id = kFuchsiaClientId;
  }

  return client_id;
}

// Outputs information from a failing OAuthResponse to the syslog.
void LogOauthResponse(const char* operation,
                      const auth_providers::oauth::OAuthResponse& response) {
  FX_LOGF(WARNING, NULL,
          "OAuthResponse error during %s: %s (Full response: %s)",
          operation, response.error_description.c_str(),
          modular::JsonValueToPrettyString(response.json_response).c_str());
}

// Sometimes auth codes contain non alpha characters such as a slash. When we
// receive these in a url parameter they are Hex encoded, but they need to be
// translated back to UTF-8 before using the auth code.
//
// TODO(jsankey): Remove this once we migrate to cookie delivery, or use a
// common encoding/decoding library if that arrives earlier.
void NormalizeAuthCode(std::string* code) {
  // This function uses the following literals:
  //   1 - The length of '%'
  //   2 - The length of a hex byte, e.g. '2F'
  //   3 - The length of a %-prefixed hex byte, e.g. '%2F'
  //  16 - The base of hexadecimal
  //  32 - The smallest printable character, i.e. the space character
  // 127 - The largest single byte UTF-8 codepoint
  std::string::size_type pos = 0;
  while ((pos = code->find("%", pos)) != std::string::npos &&
         pos <= code->length() - 3) {
    int codepoint = strtol(code->substr(pos + 1, 2).c_str(), nullptr, 16);
    if (codepoint >= 33 && codepoint <= 127) {
      code->replace(pos, 3, std::string(1, codepoint));
    }
    pos += 3;
  }
}

// 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::auth::AuthProviderStatus 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::auth::AuthProviderStatus::USER_CANCELLED;
  }
  if (url.find(success_prefix) != 0) {
    // The authentication process is still ongoing.
    return fuchsia::auth::AuthProviderStatus::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);
  NormalizeAuthCode(&code);

  if (code.empty()) {
    return fuchsia::auth::AuthProviderStatus::OAUTH_SERVER_ERROR;
  } else {
    auth_code = code;
    return fuchsia::auth::AuthProviderStatus::OK;
  }
}

}  // namespace

using auth_providers::oauth::OAuthRequestBuilder;
using auth_providers::oauth::ParseOAuthResponse;
using fuchsia::auth::AuthenticationUIContext;
using fuchsia::auth::AuthProviderStatus;
using fuchsia::auth::AuthTokenPtr;
using fuchsia::auth::FirebaseTokenPtr;
using modular::JsonValueToPrettyString;

GoogleAuthProviderImpl::GoogleAuthProviderImpl(
    async_dispatcher_t* const main_dispatcher,
    component::StartupContext* context,
    network_wrapper::NetworkWrapper* network_wrapper, Settings settings,
    fidl::InterfaceRequest<fuchsia::auth::AuthProvider> request)
    : main_dispatcher_(main_dispatcher),
      context_(context),
      network_wrapper_(network_wrapper),
      settings_(std::move(settings)),
      binding_(this, std::move(request)) {
  FXL_DCHECK(main_dispatcher_);
  FXL_DCHECK(network_wrapper_);

  // The class shuts down when the client connection is disconnected.
  binding_.set_error_handler([this](zx_status_t status) {
    if (on_empty_) {
      on_empty_();
    }
  });
}

GoogleAuthProviderImpl::~GoogleAuthProviderImpl() {}

void GoogleAuthProviderImpl::GetPersistentCredential(
    fidl::InterfaceHandle<AuthenticationUIContext> auth_ui_context,
    fidl::StringPtr user_profile_id, GetPersistentCredentialCallback callback) {
  FXL_DCHECK(auth_ui_context);
  get_persistent_credential_callback_ = std::move(callback);

  std::string url = GetAuthorizeUrl(user_profile_id);
  zx::eventpair view_holder_token;
  view_holder_token = SetupChromium();
  if (!view_holder_token) {
    return;
  }
  chromium::web::NavigationControllerPtr controller;
  chromium_frame_->GetNavigationController(controller.NewRequest());
  controller->LoadUrl(url, {});
  FX_LOGF(INFO, NULL, "Loading URL: %s", url.c_str());

  auth_ui_context_ = auth_ui_context.Bind();
  auth_ui_context_.set_error_handler([this](zx_status_t status) {
    FX_LOG(INFO, NULL, "Overlay cancelled by the caller");
    ReleaseResources();
    get_persistent_credential_callback_(AuthProviderStatus::INTERNAL_ERROR,
                                        nullptr, nullptr);
    return;
  });

  auth_ui_context_->StartOverlay2(std::move(view_holder_token));
}

void GoogleAuthProviderImpl::GetAppAccessToken(
    std::string credential, fidl::StringPtr app_client_id,
    const std::vector<std::string> app_scopes,
    GetAppAccessTokenCallback callback) {
  if (credential.empty()) {
    callback(AuthProviderStatus::BAD_REQUEST, nullptr);
    return;
  }

  auto request =
      OAuthRequestBuilder(kGoogleOAuthTokenEndpoint, "POST")
          .SetUrlEncodedBody("refresh_token=" + credential +
                             "&client_id=" + GetClientId(app_client_id.get()) +
                             "&grant_type=refresh_token");

  auto request_factory = [request = std::move(request)] {
    return request.Build();
  };

  Request(std::move(request_factory),
          [callback = std::move(callback)](http::URLResponse response) {
            auto oauth_response = ParseOAuthResponse(std::move(response));
            if (oauth_response.status != AuthProviderStatus::OK) {
              LogOauthResponse("GetAppAccessToken", oauth_response);
              callback(oauth_response.status, nullptr);
              return;
            }

            AuthTokenPtr access_token = fuchsia::auth::AuthToken::New();
            access_token->token_type = fuchsia::auth::TokenType::ACCESS_TOKEN;
            access_token->token =
                oauth_response.json_response["access_token"].GetString();
            access_token->expires_in =
                oauth_response.json_response["expires_in"].GetUint64();

            callback(AuthProviderStatus::OK, std::move(access_token));
          });
}

void GoogleAuthProviderImpl::GetAppIdToken(std::string credential,
                                           fidl::StringPtr audience,
                                           GetAppIdTokenCallback callback) {
  if (credential.empty()) {
    callback(AuthProviderStatus::BAD_REQUEST, nullptr);
    return;
  }

  auto request =
      OAuthRequestBuilder(kGoogleOAuthTokenEndpoint, "POST")
          .SetUrlEncodedBody("refresh_token=" + credential +
                             "&client_id=" + GetClientId(audience.get()) +
                             "&grant_type=refresh_token");

  auto request_factory = [request = std::move(request)] {
    return request.Build();
  };
  Request(std::move(request_factory),
          [callback = std::move(callback)](http::URLResponse response) {
            auto oauth_response = ParseOAuthResponse(std::move(response));
            if (oauth_response.status != AuthProviderStatus::OK) {
              LogOauthResponse("GetAppIdToken", oauth_response);
              callback(oauth_response.status, nullptr);
              return;
            }

            AuthTokenPtr id_token = fuchsia::auth::AuthToken::New();
            id_token->token =
                oauth_response.json_response["id_token"].GetString();
            id_token->token_type = fuchsia::auth::TokenType::ID_TOKEN;
            id_token->expires_in =
                oauth_response.json_response["expires_in"].GetUint64();

            callback(AuthProviderStatus::OK, std::move(id_token));
          });
}

void GoogleAuthProviderImpl::GetAppFirebaseToken(
    std::string id_token, std::string firebase_api_key,
    GetAppFirebaseTokenCallback callback) {
  if (id_token.empty() || firebase_api_key.empty()) {
    callback(AuthProviderStatus::BAD_REQUEST, nullptr);
    return;
  }

  std::map<std::string, std::string> query_params;
  query_params["key"] = firebase_api_key;
  auto request = OAuthRequestBuilder(kFirebaseAuthEndpoint, "POST")
                     .SetQueryParams(query_params)
                     .SetJsonBody(R"({"postBody": "id_token=)" + id_token +
                                  R"(&providerId=google.com",)" +
                                  R"("returnIdpCredential": true,)" +
                                  R"("returnSecureToken": true,)" +
                                  R"("requestUri": "http://localhost"})");

  // Exchange credential to access token at Google OAuth token endpoint
  auto request_factory = [request = std::move(request)] {
    return request.Build();
  };
  Request(std::move(request_factory), [callback = std::move(callback)](
                                          http::URLResponse response) {
    auto oauth_response = ParseOAuthResponse(std::move(response));
    if (oauth_response.status != AuthProviderStatus::OK) {
      LogOauthResponse("GetAppFirebaseToken", oauth_response);
      callback(oauth_response.status, nullptr);
      return;
    }

    FirebaseTokenPtr fb_token = fuchsia::auth::FirebaseToken::New();
    fb_token->id_token = oauth_response.json_response["id_token"].GetString();
    fb_token->email = oauth_response.json_response["email"].GetString();
    fb_token->local_id = oauth_response.json_response["local_id"].GetString();
    fb_token->expires_in =
        oauth_response.json_response["expires_in"].GetUint64();

    callback(AuthProviderStatus::OK, std::move(fb_token));
  });
}

void GoogleAuthProviderImpl::RevokeAppOrPersistentCredential(
    std::string credential, RevokeAppOrPersistentCredentialCallback callback) {
  if (credential.empty()) {
    callback(AuthProviderStatus::BAD_REQUEST);
    return;
  }

  std::string url =
      kGoogleRevokeTokenEndpoint + std::string("?token=") + credential;
  auto request = OAuthRequestBuilder(url, "POST").SetUrlEncodedBody("");

  auto request_factory = [request = std::move(request)] {
    return request.Build();
  };

  Request(std::move(request_factory),
          [callback = std::move(callback)](http::URLResponse response) {
            auto oauth_response = ParseOAuthResponse(std::move(response));
            if (oauth_response.status != AuthProviderStatus::OK) {
              LogOauthResponse("RevokeToken", oauth_response);
              callback(oauth_response.status);
              return;
            }

            callback(AuthProviderStatus::OK);
          });
}

void GoogleAuthProviderImpl::GetPersistentCredentialFromAttestationJWT(
    fidl::InterfaceHandle<AttestationSigner> attestation_signer,
    AttestationJWTParams jwt_params,
    fidl::InterfaceHandle<AuthenticationUIContext> auth_ui_context,
    fidl::StringPtr user_profile_id,
    GetPersistentCredentialFromAttestationJWTCallback callback) {
  // Remote attestation flow not supported for traditional OAuth.
  callback(AuthProviderStatus::BAD_REQUEST, nullptr, nullptr, nullptr, nullptr);
}

void GoogleAuthProviderImpl::GetAppAccessTokenFromAssertionJWT(
    fidl::InterfaceHandle<AttestationSigner> attestation_signer,
    AssertionJWTParams jwt_params, std::string credential,
    const std::vector<std::string> scopes,
    GetAppAccessTokenFromAssertionJWTCallback callback) {
  // Remote attestation flow not supported for traditional OAuth.
  callback(AuthProviderStatus::BAD_REQUEST, nullptr, nullptr, nullptr);
}

void GoogleAuthProviderImpl::OnNavigationStateChanged(
    NavigationEvent change, OnNavigationStateChangedCallback callback) {
  FXL_CHECK(get_persistent_credential_callback_);

  // Not all events change the URL, those that don't can be ignored.
  if (change.url.is_null()) {
    callback();
    return;
  }

  std::string auth_code;
  AuthProviderStatus status = ParseAuthCodeFromUrl(change.url.get(), auth_code);

  // If either an error occured or the user successfully received an auth code
  // we need to close the browser instance.
  if (status != AuthProviderStatus::OK || !auth_code.empty()) {
    ReleaseResources();
    if (status != AuthProviderStatus::OK) {
      FX_LOGF(INFO, NULL, "Failed to capture auth code: Status %d", status);
      get_persistent_credential_callback_(status, nullptr, nullptr);
    } else if (!auth_code.empty()) {
      FX_LOGF(INFO, NULL, "Captured auth code of length %d", auth_code.size());
      ExchangeAuthCode(auth_code);
    }
  }

  callback();
}

std::string GoogleAuthProviderImpl::GetAuthorizeUrl(
    fidl::StringPtr user_profile) {
  // TODO(ukode,jsankey): use app_scopes instead of |kScopes|.
  const std::vector<std::string> scopes(kScopes.begin(), kScopes.end());
  std::string scopes_str = fxl::JoinStrings(scopes, "+");

  std::string url = settings_.use_dedicated_endpoint ? kGoogleFuchsiaEndpoint
                                                     : kGoogleOAuthAuthEndpoint;
  url += "?scope=" + scopes_str;
  url += "&glif=";
  url += settings_.use_glif ? "true" : "false";
  url += "&response_type=code&redirect_uri=";
  url += kRedirectUri;
  url += "&client_id=";
  url += kFuchsiaClientId;
  // TODO(ukode,jsankey): Set user_profile_id in the state query arg for re-auth
  // This probably involves moving the current implementation of UrlEncoding in
  // OAuthRequestBuilder to a reusable library and using this to urlencode the
  // supplied user_profile into the login_hint query parameter.
  return url;
}

void GoogleAuthProviderImpl::ExchangeAuthCode(std::string auth_code) {
  auto request = OAuthRequestBuilder(kGoogleOAuthTokenEndpoint, "POST")
                     .SetUrlEncodedBody("code=" + auth_code +
                                        "&redirect_uri=" + kRedirectUri +
                                        "&client_id=" + kFuchsiaClientId +
                                        "&grant_type=authorization_code");

  auto request_factory = [request = std::move(request)] {
    return request.Build();
  };

  Request(std::move(request_factory), [this](http::URLResponse response) {
    auto oauth_response = ParseOAuthResponse(std::move(response));
    if (oauth_response.status != AuthProviderStatus::OK) {
      LogOauthResponse("ExchangeAuthCode", oauth_response);
      get_persistent_credential_callback_(oauth_response.status, nullptr,
                                          nullptr);
      return;
    }

    if (!oauth_response.json_response.HasMember("refresh_token") ||
        (!oauth_response.json_response.HasMember("access_token"))) {
      FX_LOGF(WARNING, NULL,
              "Got response without refresh and access tokens: %s",
              JsonValueToPrettyString(oauth_response.json_response).c_str());
      get_persistent_credential_callback_(
          AuthProviderStatus::OAUTH_SERVER_ERROR, nullptr, nullptr);
    }

    auto refresh_token =
        oauth_response.json_response["refresh_token"].GetString();
    auto access_token =
        oauth_response.json_response["access_token"].GetString();
    FX_LOGF(INFO, NULL, "Received refresh token of length %d",
            strlen(refresh_token));

    GetUserProfile(refresh_token, access_token);
  });
}

void GoogleAuthProviderImpl::GetUserProfile(fidl::StringPtr credential,
                                            fidl::StringPtr access_token) {
  FXL_DCHECK(credential.get().size() > 0);
  FXL_DCHECK(access_token.get().size() > 0);

  auto request = OAuthRequestBuilder(kGooglePeopleGetEndpoint, "GET")
                     .SetAuthorizationHeader(access_token.get());

  auto request_factory = [request = std::move(request)] {
    return request.Build();
  };

  Request(std::move(request_factory), [this,
                                       credential](http::URLResponse response) {
    fuchsia::auth::UserProfileInfoPtr user_profile_info =
        fuchsia::auth::UserProfileInfo::New();

    auto oauth_response = ParseOAuthResponse(std::move(response));
    if (oauth_response.status != AuthProviderStatus::OK) {
      LogOauthResponse("GetUserProfile", oauth_response);
      get_persistent_credential_callback_(oauth_response.status, credential,
                                          std::move(user_profile_info));
      return;
    }

    if (oauth_response.json_response.HasMember("id")) {
      user_profile_info->id = oauth_response.json_response["id"].GetString();
    }

    if (oauth_response.json_response.HasMember("displayName")) {
      user_profile_info->display_name =
          oauth_response.json_response["displayName"].GetString();
    }

    if (oauth_response.json_response.HasMember("url")) {
      user_profile_info->url = oauth_response.json_response["url"].GetString();
    }

    if (oauth_response.json_response.HasMember("image")) {
      user_profile_info->image_url =
          oauth_response.json_response["image"]["url"].GetString();
    }

    FX_LOG(INFO, NULL, "Received valid UserProfile");
    get_persistent_credential_callback_(oauth_response.status, credential,
                                        std::move(user_profile_info));
  });
}

zx::eventpair GoogleAuthProviderImpl::SetupChromium() {
  // Connect to the Chromium service and create a new frame.
  auto context_provider =
      context_->ConnectToEnvironmentService<chromium::web::ContextProvider>();

  zx_handle_t incoming_service_clone =
      fdio_service_clone(context_->incoming_services()->directory().get());
  if (incoming_service_clone == ZX_HANDLE_INVALID) {
    FX_LOG(ERROR, NULL, "Failed to clone service directory");
    return zx::eventpair();
  }

  chromium::web::CreateContextParams params;
  params.service_directory = zx::channel(incoming_service_clone);
  context_provider->Create(std::move(params), chromium_context_.NewRequest());
  chromium_context_->CreateFrame(chromium_frame_.NewRequest());

  // Bind ourselves as a NavigationEventObserver on this frame.
  chromium::web::NavigationEventObserverPtr navigation_event_observer;
  navigation_event_observer_bindings_.AddBinding(
      this, navigation_event_observer.NewRequest());
  chromium_frame_->SetNavigationEventObserver(
      std::move(navigation_event_observer));

  // And create a view for the frame.
  zx::eventpair view_token, view_holder_token;
  if (zx::eventpair::create(0u, &view_token, &view_holder_token) != ZX_OK) {
    FX_LOG(ERROR, NULL, "Failed to create view tokens");
    return zx::eventpair();
  }
  chromium_frame_->CreateView2(std::move(view_token), nullptr, nullptr);

  return view_holder_token;
}

void GoogleAuthProviderImpl::ReleaseResources() {
  // Close any open view
  if (auth_ui_context_) {
    FX_LOG(INFO, NULL, "Releasing Auth UI Context");
    auth_ui_context_.set_error_handler(nullptr);
    auth_ui_context_->StopOverlay();
    auth_ui_context_ = nullptr;
  }
  // Release all smart pointers for Chromium resources.
  chromium_frame_ = nullptr;
  chromium_context_ = nullptr;
}

void GoogleAuthProviderImpl::Request(
    fit::function<http::URLRequest()> request_factory,
    fit::function<void(http::URLResponse response)> callback) {
  requests_.emplace(network_wrapper_->Request(std::move(request_factory),
                                              std::move(callback)));
}

}  // namespace google_auth_provider
