|
14 | 14 |
|
15 | 15 | #include "app_check/src/desktop/debug_provider_desktop.h"
|
16 | 16 |
|
| 17 | +#include <map> |
| 18 | +#include <string> |
| 19 | +#include <utility> |
| 20 | + |
| 21 | +#include "app/rest/response.h" |
| 22 | +#include "app/rest/transport_builder.h" |
| 23 | +#include "app/rest/transport_curl.h" |
| 24 | +#include "app/rest/util.h" |
| 25 | +#include "app/src/log.h" |
| 26 | +#include "app/src/scheduler.h" |
| 27 | +#include "app_check/src/desktop/debug_token_request.h" |
| 28 | +#include "app_check/src/desktop/token_response.h" |
17 | 29 | #include "firebase/app_check/debug_provider.h"
|
18 | 30 |
|
19 | 31 | namespace firebase {
|
20 | 32 | namespace app_check {
|
21 | 33 | namespace internal {
|
22 | 34 |
|
23 |
| -DebugAppCheckProviderFactoryInternal::DebugAppCheckProviderFactoryInternal() {} |
| 35 | +class DebugAppCheckProvider : public AppCheckProvider { |
| 36 | + public: |
| 37 | + explicit DebugAppCheckProvider(App* app); |
| 38 | + ~DebugAppCheckProvider() override; |
| 39 | + |
| 40 | + void GetToken(std::function<void(AppCheckToken, int, const std::string&)> |
| 41 | + completion_callback) override; |
| 42 | + |
| 43 | + private: |
| 44 | + App* app_; |
| 45 | + |
| 46 | + scheduler::Scheduler scheduler_; |
| 47 | +}; |
| 48 | + |
| 49 | +DebugAppCheckProvider::DebugAppCheckProvider(App* app) |
| 50 | + : app_(app), scheduler_() { |
| 51 | + firebase::rest::util::Initialize(); |
| 52 | + firebase::rest::InitTransportCurl(); |
| 53 | +} |
| 54 | + |
| 55 | +DebugAppCheckProvider::~DebugAppCheckProvider() { |
| 56 | + firebase::rest::CleanupTransportCurl(); |
| 57 | + firebase::rest::util::Terminate(); |
| 58 | +} |
| 59 | + |
| 60 | +// Performs the given rest request, and calls the callback based on the |
| 61 | +// response. |
| 62 | +void GetTokenAsync(SharedPtr<DebugTokenRequest> request, |
| 63 | + std::function<void(AppCheckToken, int, const std::string&)> |
| 64 | + completion_callback) { |
| 65 | + TokenResponse response; |
| 66 | + firebase::rest::CreateTransport()->Perform(*request, &response); |
24 | 67 |
|
25 |
| -DebugAppCheckProviderFactoryInternal::~DebugAppCheckProviderFactoryInternal() {} |
| 68 | + if (response.status() == firebase::rest::util::HttpSuccess) { |
| 69 | + // Call the callback with the response token |
| 70 | + AppCheckToken token; |
| 71 | + token.token = std::move(response.token()); |
| 72 | + // Expected response is in seconds |
| 73 | + int64_t extra_time = strtol(response.ttl().c_str(), nullptr, 10); |
| 74 | + token.expire_time_millis = (response.fetch_time() + extra_time) * 1000; |
| 75 | + completion_callback(token, kAppCheckErrorNone, ""); |
| 76 | + } else { |
| 77 | + // Create an error message, and pass it along instead. |
| 78 | + AppCheckToken token; |
| 79 | + char error_message[1000]; |
| 80 | + snprintf(error_message, sizeof(error_message), |
| 81 | + "The server responded with an error.\n" |
| 82 | + "HTTP status code: %d \n" |
| 83 | + "Response body: %s\n", |
| 84 | + response.status(), response.GetBody()); |
| 85 | + completion_callback(token, kAppCheckErrorUnknown, error_message); |
| 86 | + } |
| 87 | +} |
| 88 | + |
| 89 | +void DebugAppCheckProvider::GetToken( |
| 90 | + std::function<void(AppCheckToken, int, const std::string&)> |
| 91 | + completion_callback) { |
| 92 | + // Identify the user's debug token |
| 93 | + // TODO(amaurice): For now uses an environment variable, but should use other |
| 94 | + // options. |
| 95 | + const char* debug_token = std::getenv("APP_CHECK_DEBUG_TOKEN"); |
| 96 | + |
| 97 | + // Exchange debug token with the backend to get a proper attestation token. |
| 98 | + auto request = MakeShared<DebugTokenRequest>(app_); |
| 99 | + request->SetDebugToken(debug_token); |
| 100 | + |
| 101 | + // Use an async call, since we don't want to block on the server response. |
| 102 | + auto async_call = |
| 103 | + callback::NewCallback(GetTokenAsync, request, completion_callback); |
| 104 | + scheduler_.Schedule(async_call); |
| 105 | +} |
| 106 | + |
| 107 | +DebugAppCheckProviderFactoryInternal::DebugAppCheckProviderFactoryInternal() |
| 108 | + : provider_map_() {} |
| 109 | + |
| 110 | +DebugAppCheckProviderFactoryInternal::~DebugAppCheckProviderFactoryInternal() { |
| 111 | + // Clear the map |
| 112 | + for (auto it : provider_map_) { |
| 113 | + delete it.second; |
| 114 | + } |
| 115 | + provider_map_.clear(); |
| 116 | +} |
26 | 117 |
|
27 | 118 | AppCheckProvider* DebugAppCheckProviderFactoryInternal::CreateProvider(
|
28 | 119 | App* app) {
|
29 |
| - return nullptr; |
| 120 | + // Check the map |
| 121 | + std::map<App*, AppCheckProvider*>::iterator it = provider_map_.find(app); |
| 122 | + if (it != provider_map_.end()) { |
| 123 | + return it->second; |
| 124 | + } |
| 125 | + // Create a new provider and cache it |
| 126 | + AppCheckProvider* provider = new DebugAppCheckProvider(app); |
| 127 | + provider_map_[app] = provider; |
| 128 | + return provider; |
30 | 129 | }
|
31 | 130 |
|
32 | 131 | } // namespace internal
|
|
0 commit comments