// 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 "peridot/lib/firebase_auth/testing/service_account_token_minter.h"

#include <time.h>

#include <lib/fidl/cpp/clone.h>
#include <lib/fidl/cpp/optional.h>
#include <lib/fsl/vmo/strings.h>
#include <lib/fxl/arraysize.h>
#include <lib/fxl/files/file.h>
#include <lib/fxl/logging.h>
#include <lib/fxl/strings/string_number_conversions.h>
#include <lib/fxl/strings/string_view.h>
#include <openssl/bio.h>
#include <openssl/digest.h>
#include <openssl/hmac.h>
#include <openssl/pem.h>
#include <rapidjson/document.h>
#include <rapidjson/schema.h>
#include <rapidjson/stringbuffer.h>
#include <rapidjson/writer.h>

#include "peridot/lib/base64url/base64url.h"
#include "peridot/lib/convert/convert.h"
#include "peridot/lib/firebase_auth/testing/json_schema.h"

namespace service_account {

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

namespace {
constexpr fxl::StringView kIdentityResponseSchema = R"({
  "type": "object",
  "additionalProperties": true,
  "properties": {
    "idToken": {
      "type": "string"
    },
    "expiresIn": {
      "type": "string"
    }
  },
  "required": ["idToken", "expiresIn"]
})";

rapidjson::SchemaDocument& GetResponseSchema() {
  static auto schema = json_schema::InitSchema(kIdentityResponseSchema);
  FXL_DCHECK(schema);
  return *schema;
}

std::string GetHeader() {
  rapidjson::StringBuffer string_buffer;
  rapidjson::Writer<rapidjson::StringBuffer> writer(string_buffer);

  writer.StartObject();

  writer.Key("typ");
  writer.String("JWT");

  writer.Key("alg");
  writer.String("RS256");

  writer.EndObject();

  return base64url::Base64UrlEncode(
      fxl::StringView(string_buffer.GetString(), string_buffer.GetSize()));
}

}  // namespace

struct ServiceAccountTokenMinter::CachedToken {
  std::string id_token;
  // TODO: Use zx::time for expiration_time.
  time_t expiration_time;
};

ServiceAccountTokenMinter::GetTokenResponse
ServiceAccountTokenMinter::GetErrorResponse(Status status,
                                            const std::string& error_msg) {
  GetTokenResponse response = {status, /* response status */
                               "",     /* id_token */
                               "",     /* local_id */
                               "",     /* email */
                               error_msg /* detailed error msg */};
  return response;
}

ServiceAccountTokenMinter::GetTokenResponse
ServiceAccountTokenMinter::GetSuccessResponse(const std::string& id_token) {
  GetTokenResponse response = {Status::OK,                /* success status */
                               id_token,                  /* token */
                               user_id_,                  /* local_id */
                               user_id_ + "@example.com", /* email */
                               "OK" /* success msg */};
  return response;
}

ServiceAccountTokenMinter::ServiceAccountTokenMinter(
    network_wrapper::NetworkWrapper* network_wrapper,
    std::unique_ptr<Credentials> credentials, std::string user_id)
    : network_wrapper_(network_wrapper),
      credentials_(std::move(credentials)),
      user_id_(std::move(user_id)) {}

ServiceAccountTokenMinter::~ServiceAccountTokenMinter() {
  for (const auto& pair : in_progress_callbacks_) {
    ResolveCallbacks(
        pair.first,
        GetErrorResponse(Status::INTERNAL_ERROR,
                         "Account provider deleted with requests in flight."));
  }
}

void ServiceAccountTokenMinter::GetFirebaseToken(
    fidl::StringPtr firebase_api_key, GetFirebaseTokenCallback callback) {
  // A request is in progress to get a token. Registers the callback that will
  // be called when the request ends.
  if (!in_progress_callbacks_[firebase_api_key].empty()) {
    in_progress_callbacks_[firebase_api_key].push_back(std::move(callback));
    return;
  }

  // Check if a token is currently cached.
  if (cached_tokens_[firebase_api_key]) {
    auto& cached_token = cached_tokens_[firebase_api_key];
    if (time(nullptr) < cached_token->expiration_time) {
      callback(GetSuccessResponse(cached_token->id_token));
      return;
    }

    // The token expired. Falls back to fetch a new one.
    cached_tokens_.erase(firebase_api_key);
  }

  // Build the custom token to exchange for an id token.
  std::string custom_token;
  if (!GetCustomToken(&custom_token)) {
    callback(
        GetErrorResponse(Status::INTERNAL_ERROR,
                         "Unable to compute custom authentication token."));
    return;
  }

  in_progress_callbacks_[firebase_api_key].push_back(std::move(callback));

  in_progress_requests_.emplace(network_wrapper_->Request(
      [this, firebase_api_key = firebase_api_key.get(),
       custom_token = std::move(custom_token)] {
        return GetIdentityRequest(firebase_api_key, custom_token);
      },
      [this,
       firebase_api_key = firebase_api_key.get()](http::URLResponse response) {
        HandleIdentityResponse(firebase_api_key, std::move(response));
      }));
}

std::string ServiceAccountTokenMinter::GetClientId() {
  return credentials_->client_id();
}

std::string ServiceAccountTokenMinter::GetClaims() {
  rapidjson::StringBuffer string_buffer;
  rapidjson::Writer<rapidjson::StringBuffer> writer(string_buffer);

  writer.StartObject();

  writer.Key("iss");
  writer.String(credentials_->client_email());

  writer.Key("sub");
  writer.String(credentials_->client_email());

  writer.Key("aud");
  writer.String(
      "https://identitytoolkit.googleapis.com/"
      "google.identity.identitytoolkit.v1.IdentityToolkit");

  time_t current_time = time(nullptr);
  writer.Key("iat");
  writer.Int(current_time);

  writer.Key("exp");
  writer.Int(current_time + 3600);

  writer.Key("uid");
  writer.String(user_id_);

  writer.EndObject();

  return base64url::Base64UrlEncode(
      fxl::StringView(string_buffer.GetString(), string_buffer.GetSize()));
}

bool ServiceAccountTokenMinter::GetCustomToken(std::string* custom_token) {
  std::string message = GetHeader() + "." + GetClaims();

  bssl::ScopedEVP_MD_CTX md_ctx;
  if (EVP_DigestSignInit(md_ctx.get(), nullptr, EVP_sha256(), nullptr,
                         credentials_->private_key().get()) != 1) {
    FXL_LOG(ERROR) << ERR_reason_error_string(ERR_get_error());
    return false;
  }

  if (EVP_DigestSignUpdate(md_ctx.get(), message.c_str(), message.size()) !=
      1) {
    FXL_LOG(ERROR) << ERR_reason_error_string(ERR_get_error());
    return false;
  }

  size_t result_length;
  if (EVP_DigestSignFinal(md_ctx.get(), nullptr, &result_length) != 1) {
    FXL_LOG(ERROR) << ERR_reason_error_string(ERR_get_error());
    return false;
  }

  char result[result_length];
  if (EVP_DigestSignFinal(md_ctx.get(), reinterpret_cast<uint8_t*>(result),
                          &result_length) != 1) {
    FXL_LOG(ERROR) << ERR_reason_error_string(ERR_get_error());
    return false;
  }

  std::string signature =
      base64url::Base64UrlEncode(fxl::StringView(result, result_length));

  *custom_token = message + "." + signature;
  return true;
}

http::URLRequest ServiceAccountTokenMinter::GetIdentityRequest(
    const std::string& api_key, const std::string& custom_token) {
  http::URLRequest request;
  request.url =
      "https://www.googleapis.com/identitytoolkit/v3/relyingparty/"
      "verifyCustomToken?key=" +
      api_key;
  request.method = "POST";
  request.auto_follow_redirects = true;
  request.response_body_mode = http::ResponseBodyMode::BUFFER;

  // content-type header.
  http::HttpHeader content_type_header;
  content_type_header.name = "content-type";
  content_type_header.value = "application/json";
  request.headers.push_back(std::move(content_type_header));

  // set accept header
  http::HttpHeader accept_header;
  accept_header.name = "accept";
  accept_header.value = "application/json";
  request.headers.push_back(std::move(accept_header));

  fsl::SizedVmo data;
  bool result = fsl::VmoFromString(GetIdentityRequestBody(custom_token), &data);
  FXL_DCHECK(result);

  request.body = http::URLBody::New();
  request.body->set_buffer(std::move(data).ToTransport());

  return request;
}

std::string ServiceAccountTokenMinter::GetIdentityRequestBody(
    const std::string& custom_token) {
  rapidjson::StringBuffer string_buffer;
  rapidjson::Writer<rapidjson::StringBuffer> writer(string_buffer);

  writer.StartObject();

  writer.Key("token");
  writer.String(custom_token);

  writer.Key("returnSecureToken");
  writer.Bool(true);

  writer.EndObject();

  return std::string(string_buffer.GetString(), string_buffer.GetSize());
}

void ServiceAccountTokenMinter::HandleIdentityResponse(
    const std::string& api_key, http::URLResponse response) {
  if (response.error) {
    ResolveCallbacks(api_key, GetErrorResponse(Status::NETWORK_ERROR,
                                               response.error->description));
    return;
  }

  std::string response_body;
  if (response.body) {
    FXL_DCHECK(response.body->is_buffer());
    if (!fsl::StringFromVmo(response.body->buffer(), &response_body)) {
      ResolveCallbacks(api_key, GetErrorResponse(Status::INTERNAL_ERROR,
                                                 "Unable to read from VMO."));
      return;
    }
  }

  if (response.status_code != 200) {
    ResolveCallbacks(
        api_key, GetErrorResponse(Status::AUTH_SERVER_ERROR, response_body));
    return;
  }

  rapidjson::Document document;
  document.Parse(response_body.c_str(), response_body.size());
  if (document.HasParseError() || !document.IsObject()) {
    ResolveCallbacks(api_key, GetErrorResponse(Status::BAD_RESPONSE,
                                               "Unable to parse response: " +
                                                   response_body));
    return;
  }

  if (!json_schema::ValidateSchema(document, GetResponseSchema())) {
    ResolveCallbacks(api_key,
                     GetErrorResponse(Status::BAD_RESPONSE,
                                      "Malformed response: " + response_body));
    return;
  }

  auto cached_token = std::make_unique<CachedToken>();
  cached_token->id_token = convert::ToString(document["idToken"]);
  cached_token->expiration_time =
      time(nullptr) + (9u *
                       fxl::StringToNumber<time_t>(
                           convert::ToStringView(document["expiresIn"])) /
                       10u);
  const auto& id_token = cached_token->id_token;
  cached_tokens_[api_key] = std::move(cached_token);
  ResolveCallbacks(api_key, GetSuccessResponse(id_token));
}

void ServiceAccountTokenMinter::ResolveCallbacks(const std::string& api_key,
                                                 GetTokenResponse response) {
  auto callbacks = std::move(in_progress_callbacks_[api_key]);
  in_progress_callbacks_[api_key].clear();
  for (const auto& callback : callbacks) {
    callback(std::move(response));
  }
}

}  // namespace service_account
