Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 32 additions & 2 deletions auth/src/desktop/auth_desktop.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#include "auth/src/desktop/auth_desktop.h"

#include <algorithm>
#include <cassert>
#include <cstdint>
#include <cstring>
Expand Down Expand Up @@ -92,6 +93,19 @@ void* CreatePlatformAuth(App* const app) {
AuthImpl* const auth = new AuthImpl();
auth->api_key = app->options().api_key();
auth->app_name = app->name();

// Check environment variables for emulator if set.
if (std::getenv("USE_AUTH_EMULATOR") != nullptr) {
auth->assigned_emulator_url.append(kEmulatorLocalHost);
auth->assigned_emulator_url.append(":");
if (std::getenv("AUTH_EMULATOR_PORT") == nullptr) {
auth->assigned_emulator_url.append(kEmulatorPort);
} else {
auth->assigned_emulator_url.append(std::getenv("AUTH_EMULATOR_PORT"));
}
LogInfo("Using Auth Emulator: %s", auth->assigned_emulator_url.c_str());
}
Comment thread
AustinBenoit marked this conversation as resolved.

return auth;
}

Expand Down Expand Up @@ -576,6 +590,7 @@ void Auth::UseEmulator(std::string host, uint32_t port) {
auth_impl->assigned_emulator_url.append(host);
auth_impl->assigned_emulator_url.append(":");
auth_impl->assigned_emulator_url.append(std::to_string(port));
LogInfo("Using Auth Emulator: %s", auth_impl->assigned_emulator_url.c_str());
}

void InitializeTokenRefresher(AuthData* auth_data) {
Expand Down Expand Up @@ -667,6 +682,8 @@ void IdTokenRefreshThread::Initialize(AuthData* auth_data) {
thread_ = firebase::Thread(
[](IdTokenRefreshThread* refresh_thread) {
Auth* auth = refresh_thread->auth;
int retry_backoff_ms = kMinRetryBackoffMs;

while (!refresh_thread->is_shutting_down()) {
// Note: Make sure to always make future_impl.mutex the innermost
// lock, to prevent deadlocks!
Expand Down Expand Up @@ -700,8 +717,21 @@ void IdTokenRefreshThread::Initialize(AuthData* auth_data) {
// is completed.
future_sem.Wait();

// (We don't actually care about the results of the token request.
// The token listener will handle that.)
if (future.error() != 0) {
// Token refresh failed (e.g. network outage). Wait with
// exponential backoff to prevent tight retry loops and avoid
// overloading backend servers upon reconnect. Matches Android
// DefaultTokenRefresher (30s initial, doubling up to 16m max).
if (!refresh_thread->is_shutting_down()) {
refresh_thread->wakeup_sem_.TimedWait(retry_backoff_ms);
retry_backoff_ms =
std::min(kMaxRetryBackoffMs, retry_backoff_ms * 2);
}
continue;
} else {
// Refresh succeeded! Reset backoff to minimum interval.
retry_backoff_ms = kMinRetryBackoffMs;
}
} else {
auth->auth_data_->future_impl.mutex().Release();
refresh_thread->ref_count_mutex_.Release();
Expand Down
3 changes: 3 additions & 0 deletions auth/src/desktop/auth_desktop.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,9 @@ struct AuthImpl {
const int kMinutesPerTokenRefresh = 58;
const int kMsPerTokenRefresh =
kMinutesPerTokenRefresh * internal::kMillisecondsPerMinute;
// Exponential backoff parameters when token refresh fails (e.g. network outage), matching Android DefaultTokenRefresher.
const int kMinRetryBackoffMs = 30 * 1000; // 30 seconds base delay
const int kMaxRetryBackoffMs = 16 * 60 * 1000; // 16 minutes max delay

void InitializeUserDataPersist(AuthData* auth_data);
void DestroyUserDataPersist(AuthData* auth_data);
Expand Down
35 changes: 2 additions & 33 deletions auth/src/desktop/rpcs/auth_request.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,6 @@ const char* kHeaderFirebaseLocale = "X-Firebase-Locale";
AuthRequest::AuthRequest(::firebase::App& app, const char* schema,
bool deliver_heartbeat)
: RequestJson(schema), app(app) {
CheckEnvEmulator();

if (deliver_heartbeat) {
std::shared_ptr<heartbeat::HeartbeatController> heartbeat_controller =
app.GetHeartbeatController();
Expand Down Expand Up @@ -76,52 +74,23 @@ AuthRequest::AuthRequest(::firebase::App& app, const char* schema,
}

std::string AuthRequest::GetUrl() {
std::string emulator_url;
Auth* auth_ptr = Auth::GetAuth(&app);
std::string assigned_emulator_url =
static_cast<AuthImpl*>(auth_ptr->auth_data_->auth_impl)
->assigned_emulator_url;
if (assigned_emulator_url.empty()) {
emulator_url = env_emulator_url;
} else {
emulator_url = assigned_emulator_url;
}

if (emulator_url.empty()) {
if (assigned_emulator_url.empty()) {
std::string url(kHttps);
url += kServerURL;
return url;
} else {
std::string url(kHttp);
url += emulator_url;
url += assigned_emulator_url;
url += "/";
url += kServerURL;
return url;
}
}

void AuthRequest::CheckEnvEmulator() {
if (!env_emulator_url.empty()) {
LogInfo("Environment Emulator Url already set: %s",
env_emulator_url.c_str());
return;
}

// Use emulator as long as this env variable is set, regardless its value.
if (std::getenv("USE_AUTH_EMULATOR") == nullptr) {
LogInfo("USE_AUTH_EMULATOR not set.");
return;
}
env_emulator_url.append(kEmulatorLocalHost);
env_emulator_url.append(":");
// Use AUTH_EMULATOR_PORT if it is set to non empty string,
// otherwise use the default port.
if (std::getenv("AUTH_EMULATOR_PORT") == nullptr) {
env_emulator_url.append(kEmulatorPort);
} else {
env_emulator_url.append(std::getenv("AUTH_EMULATOR_PORT"));
}
}

} // namespace auth
} // namespace firebase
2 changes: 0 additions & 2 deletions auth/src/desktop/rpcs/auth_request.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,6 @@ class AuthRequest
std::string GetUrl();

private:
void CheckEnvEmulator();
std::string env_emulator_url;
::firebase::App& app;
};

Expand Down
1 change: 1 addition & 0 deletions release_build_files/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,7 @@ code.
## Release Notes
### Upcoming
- Changes
- Auth (Desktop): Fixed log spam and high CPU utilization when offline by moving `USE_AUTH_EMULATOR` environment variable check to initialization and eliminating per-request logging (#1629).
- Realtime Database (Desktop): Fixed an intermittent use-after-free crash (`ACCESS_VIOLATION`) when detaching a listener while a WebSocket listen response is pending.

### 13.10.0
Expand Down
Loading