Skip to content

Commit 05ac8c3

Browse files
chkuang-ga-maurice
authored andcommitted
Force refresh token when RT DB server reject the auth token
PiperOrigin-RevId: 258455510
1 parent 98a8d57 commit 05ac8c3

File tree

2 files changed

+88
-10
lines changed

2 files changed

+88
-10
lines changed

database/src/desktop/connection/persistent_connection.cc

Lines changed: 73 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,15 @@ PersistentConnection::~PersistentConnection() {
131131
// executing code which requires reference to this.
132132
safe_this_.ClearReference();
133133

134+
// Clear OnCompletion function for pending token future
135+
{
136+
MutexLock future_lock(pending_token_future_mutex_);
137+
if (pending_token_future_.status() != kFutureStatusInvalid) {
138+
pending_token_future_.OnCompletion(nullptr, nullptr);
139+
pending_token_future_ = Future<std::string>();
140+
}
141+
}
142+
134143
// Destroy the client so that no more event will be triggered from this point.
135144
realtime_.reset(nullptr);
136145
}
@@ -487,21 +496,75 @@ void PersistentConnection::TryScheduleReconnect() {
487496
}
488497

489498
assert(connection_state_ == kDisconnected);
490-
499+
bool force_refresh = force_auth_refresh_;
500+
force_auth_refresh_ = false;
491501
LogDebug("%s Scheduling connection attempt", log_id_.c_str());
492502

493-
// TODO(chkuang): Implement Retry
494-
Reconnect();
503+
// TODO(chkuang): Implement Exponential Backoff Retry
504+
connection_state_ = kGettingToken;
505+
LogDebug("%s Trying to fetch auth token", log_id_.c_str());
506+
507+
// Get Token Asynchronously to make sure the token is not expired.
508+
Future<std::string> future;
509+
bool succeeded = app_->function_registry()->CallFunction(
510+
::firebase::internal::FnAuthGetTokenAsync, app_, &force_refresh, &future);
511+
if (succeeded && future.status() != kFutureStatusInvalid) {
512+
// Set pending future
513+
MutexLock future_lock(pending_token_future_mutex_);
514+
pending_token_future_ = future;
515+
future.OnCompletion(OnTokenFutureComplete, this);
516+
} else {
517+
// Auth is not available now. Start the connection anyway.
518+
OpenNetworkConnection();
519+
}
495520
}
496521

497-
void PersistentConnection::Reconnect() {
498-
assert(connection_state_ == kDisconnected);
499-
connection_state_ = kGettingToken;
522+
void PersistentConnection::OnTokenFutureComplete(
523+
const Future<std::string>& result_data, void* user_data) {
524+
assert(user_data);
525+
PersistentConnection* connection =
526+
static_cast<PersistentConnection*>(user_data);
527+
ThisRefLock lock(&connection->safe_this_);
528+
// If the connection is destroyed or being destroyed, do nothing.
529+
if (!lock.GetReference()) return;
530+
531+
{
532+
// Clear pending future
533+
MutexLock future_lock(connection->pending_token_future_mutex_);
534+
connection->pending_token_future_ = Future<std::string>();
535+
}
500536

501-
LogDebug("%s Trying to fetch auth token", log_id_.c_str());
502-
GetAuthToken(&auth_token_);
537+
connection->scheduler_->Schedule(
538+
new callback::CallbackValue2<ThisRef, Future<std::string>>(
539+
connection->safe_this_, result_data,
540+
[](ThisRef ref, Future<std::string> future) {
541+
ThisRefLock lock(&ref);
542+
if (lock.GetReference()) {
543+
lock.GetReference()->HandleTokenFuture(future);
544+
}
545+
}));
546+
}
503547

504-
OpenNetworkConnection();
548+
void PersistentConnection::HandleTokenFuture(Future<std::string> future) {
549+
if (future.error() == 0) {
550+
if (connection_state_ == kGettingToken) {
551+
LogDebug("%s Successfully fetched token, opening connection",
552+
log_id_.c_str());
553+
auth_token_ = *future.result();
554+
OpenNetworkConnection();
555+
} else {
556+
assert(connection_state_ == kDisconnected);
557+
LogDebug(
558+
"%s Not opening connection after token refresh, because "
559+
"connection was set to disconnected",
560+
log_id_.c_str());
561+
}
562+
} else {
563+
connection_state_ = kDisconnected;
564+
LogDebug("%s Error fetching token: %s", log_id_.c_str(),
565+
future.error_message());
566+
TryScheduleReconnect();
567+
}
505568
}
506569

507570
void PersistentConnection::OpenNetworkConnection() {
@@ -945,6 +1008,7 @@ void PersistentConnection::HandleAuthTokenResponse(const Variant& message,
9451008
}
9461009
} else {
9471010
auth_token_.clear();
1011+
force_auth_refresh_ = true;
9481012
event_handler_->OnAuthStatus(false);
9491013

9501014
std::string reason = GetStringValue(message, kServerResponseData);

database/src/desktop/connection/persistent_connection.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "app/memory/shared_ptr.h"
2727
#include "app/memory/unique_ptr.h"
2828
#include "app/src/include/firebase/app.h"
29+
#include "app/src/include/firebase/future.h"
2930
#include "app/src/include/firebase/variant.h"
3031
#include "app/src/optional.h"
3132
#include "app/src/path.h"
@@ -313,8 +314,21 @@ class PersistentConnection : public ConnectionEventHandler {
313314
}
314315

315316
bool ShouldReconnect() { return interrupt_reasons_.empty(); }
317+
318+
// Try to reconnect to RT DB server.
316319
void TryScheduleReconnect();
317-
void Reconnect();
320+
321+
// Callback function when the future to fetch token is complete.
322+
static void OnTokenFutureComplete(const Future<std::string>& result_data,
323+
void* user_data);
324+
void HandleTokenFuture(Future<std::string> future);
325+
326+
// Pending future to fetch the token.
327+
Future<std::string> pending_token_future_;
328+
// Mutex to protect pending_token_future_
329+
Mutex pending_token_future_mutex_;
330+
331+
// Start to establish connection to RT DB server.
318332
void OpenNetworkConnection();
319333

320334
bool CanSendWrites() const { return connection_state_ == kConnected; }

0 commit comments

Comments
 (0)