Skip to content

add UseEmulator api to auth #1437

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Merged
merged 31 commits into from
Aug 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
352ba83
add auth emulator support
Jul 19, 2023
6ccf941
fix ios number parse
Jul 20, 2023
b1a8d27
update the documentation part
Jul 21, 2023
64fd592
reduce lint warning
Jul 21, 2023
4d012dc
more lint warnings
Jul 21, 2023
ce63a9e
code format
Jul 24, 2023
1e1a9ce
use environment to decide using emulator or not
Jul 25, 2023
14ebb5d
fix a typo
Jul 25, 2023
62d5c3f
Merge branch 'main' into cj_rest
cynthiajoan Jul 25, 2023
c2e952a
add readme entry for FirebaseApp.GetApps()
Jul 28, 2023
90f2f2d
Merge branch 'main' into cj_rest
cynthiajoan Jul 28, 2023
9e5c7a8
update for review comment
Aug 6, 2023
79ee455
add missing `
Aug 6, 2023
26547d6
Merge branch 'main' into cj_rest
cynthiajoan Aug 6, 2023
472fbb3
make json request always do restrict json
Aug 9, 2023
c459351
Merge https://github.com/firebase/firebase-cpp-sdk into cj_rest
Aug 9, 2023
5dfcd36
add readme info
Aug 9, 2023
49ca0fc
Merge branch 'cj_rest' of https://github.com/firebase/firebase-cpp-sd…
Aug 9, 2023
f3894bf
prepare for review
Aug 9, 2023
e6c7bdb
some minor tweak
Aug 9, 2023
e08a598
code format
Aug 9, 2023
fee091a
update review comments
Aug 9, 2023
ac867c1
update the unit test after request json change
Aug 10, 2023
2d7a50d
remove platform logging v1 code
Aug 21, 2023
9b1492a
Merge https://github.com/firebase/firebase-cpp-sdk into cj_rest
Aug 21, 2023
bb40854
add useEmulator api
Aug 29, 2023
13196a7
test with emulator
Aug 30, 2023
e4887cb
clean up for review
Aug 30, 2023
b07e0ce
tweak for review
Aug 30, 2023
7f510ae
update with comments
Aug 30, 2023
cd3c0ef
put back necessary heartbeat blocks
Aug 30, 2023
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
23 changes: 15 additions & 8 deletions auth/src/android/auth_android.cc
Original file line number Diff line number Diff line change
Expand Up @@ -188,11 +188,19 @@ void UpdateCurrentUser(AuthData* auth_data) {
}
}

void SetEmulatorJni(AuthData* auth_data, const char* host, uint32_t port) {
JNIEnv* env = Env(auth_data);

jstring j_host = env->NewStringUTF(host);
env->CallVoidMethod(AuthImpl(auth_data),
auth::GetMethodId(auth::kUseEmulator), j_host, port);
env->DeleteLocalRef(j_host);
firebase::util::CheckAndClearJniExceptions(env);
}

const char* const kEmulatorLocalHost = "10.0.2.2";
const char* const kEmulatorPort = "9099";
void CheckEmulator(AuthData* auth_data) {
JNIEnv* env = Env(auth_data);

// Use emulator as long as this env variable is set, regardless its value.
if (std::getenv("USE_AUTH_EMULATOR") == nullptr) {
LogInfo("Using Auth Prod for testing.");
Expand All @@ -207,12 +215,7 @@ void CheckEmulator(AuthData* auth_data) {
if (std::getenv("AUTH_EMULATOR_PORT") != nullptr) {
port = std::stoi(std::getenv("AUTH_EMULATOR_PORT"));
}

jstring j_host = env->NewStringUTF(kEmulatorLocalHost);
env->CallVoidMethod(AuthImpl(auth_data),
auth::GetMethodId(auth::kUseEmulator), j_host, port);
env->DeleteLocalRef(j_host);
firebase::util::CheckAndClearJniExceptions(env);
SetEmulatorJni(auth_data, kEmulatorLocalHost, port);
}

// Release cached Java classes.
Expand Down Expand Up @@ -828,6 +831,10 @@ Future<void> Auth::SendPasswordResetEmail(const char* email) {
return MakeFuture(&futures, handle);
}

void Auth::UseEmulator(std::string host, uint32_t port) {
SetEmulatorJni(auth_data_, host.c_str(), port);
}

// Not implemented for Android.
void EnableTokenAutoRefresh(AuthData* auth_data) {}
void DisableTokenAutoRefresh(AuthData* auth_data) {}
Expand Down
8 changes: 8 additions & 0 deletions auth/src/desktop/auth_desktop.cc
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,14 @@ void Auth::UseAppLanguage() {
auth_impl->language_code.assign(empty_string);
}

void Auth::UseEmulator(std::string host, uint32_t port) {
auto auth_impl = static_cast<AuthImpl*>(auth_data_->auth_impl);
auth_impl->assigned_emulator_url = "";
auth_impl->assigned_emulator_url.append(host);
auth_impl->assigned_emulator_url.append(":");
auth_impl->assigned_emulator_url.append(std::to_string(port));
}

void InitializeTokenRefresher(AuthData* auth_data) {
auto auth_impl = static_cast<AuthImpl*>(auth_data->auth_impl);
auth_impl->token_refresh_thread.Initialize(auth_data);
Expand Down
2 changes: 2 additions & 0 deletions auth/src/desktop/auth_desktop.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,8 @@ struct AuthImpl {
// The current user language code. This can be set to the app’s current
// language by calling SetLanguageCode.
std::string language_code;

std::string assigned_emulator_url;
};

// Constant, describing how often we automatically fetch a new auth token.
Expand Down
66 changes: 25 additions & 41 deletions auth/src/desktop/rpcs/auth_request.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
#include "app/src/heartbeat/heartbeat_controller_desktop.h"
#include "app/src/include/firebase/app.h"
#include "app/src/include/firebase/internal/mutex.h"
#include "auth/src/desktop/auth_desktop.h"
#include "auth/src/include/firebase/auth.h"
#include "firebase/log.h"

namespace firebase {
Expand All @@ -33,39 +35,9 @@ const char* kHeaderFirebaseLocale = "X-Firebase-Locale";

AuthRequest::AuthRequest(::firebase::App& app, const char* schema,
bool deliver_heartbeat)
: RequestJson(schema) {
// The user agent strings are cached in static variables here to avoid
// dependencies upon other parts of this library. This complication is due to
// the way the tests are currently configured where each library has minimal
// dependencies.
: RequestJson(schema), app(app) {
CheckEnvEmulator();

CheckEmulator();
static std::string auth_user_agent; // NOLINT
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm guessing the user_agent stuff should not be getting removed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I consulted with Shawn and they are actually not needed anymore. Include Shawn to review to confirm

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of the user-agent stuffs are not used, at least by Platform Logging pipeline, at all, except for the section I commented below. Therefore it is safe to remove.

However, I wonder if this should be in this particular PR.

If you are planning to bundle this change along with emulator support, please make sure you include this information in the commit message, so it does not look like an accident change.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

static std::string extended_auth_user_agent; // NOLINT
static Mutex* user_agent_mutex = new Mutex();
MutexLock lock(*user_agent_mutex);
if (auth_user_agent.empty()) {
std::string sdk;
std::string version;
app_common::GetOuterMostSdkAndVersion(&sdk, &version);
// Set the user agent similar to the iOS SDK. Format:
// FirebaseAuth.<platform>/<sdk_version>
assert(!(sdk.empty() || version.empty()));
std::string sdk_type(sdk.substr(sizeof(FIREBASE_USER_AGENT_PREFIX) - 1));
auth_user_agent = std::string("FirebaseAuth.") + sdk_type + "/" + version;
// Generage the extended header to set the format specified by b/28531026
// and b/64693042 to include the platform and framework.
// <environment>/<sdk_implementation>/<sdk_version>/<framework>
// where <framework> is '(FirebaseCore|FirebaseUI)'.
extended_auth_user_agent = std::string(app_common::kOperatingSystem) + "/" +
sdk + "/" + version + "/" + "FirebaseCore-" +
sdk_type;
}
// TODO(b/244643516): Remove the User-Agent and X-Client-Version headers.
if (!auth_user_agent.empty()) {
add_header("User-Agent", auth_user_agent.c_str());
add_header("X-Client-Version", extended_auth_user_agent.c_str());
}
if (deliver_heartbeat) {
std::shared_ptr<heartbeat::HeartbeatController> heartbeat_controller =
app.GetHeartbeatController();
Expand All @@ -81,6 +53,17 @@ 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()) {
std::string url(kHttps);
url += kServerURL;
Expand All @@ -94,25 +77,26 @@ std::string AuthRequest::GetUrl() {
}
}

void AuthRequest::CheckEmulator() {
if (!emulator_url.empty()) {
LogInfo("Emulator Url already set: %s", emulator_url.c_str());
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("Using Auth Prod for testing.");
LogInfo("USE_AUTH_EMULATOR not set.");
return;
}
LogInfo("Using Auth Emulator.");
emulator_url.append(kEmulatorLocalHost);
emulator_url.append(":");
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) {
emulator_url.append(kEmulatorPort);
env_emulator_url.append(kEmulatorPort);
} else {
emulator_url.append(std::getenv("AUTH_EMULATOR_PORT"));
env_emulator_url.append(std::getenv("AUTH_EMULATOR_PORT"));
}
}

Expand Down
5 changes: 3 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,9 @@ class AuthRequest
std::string GetUrl();

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

} // namespace auth
Expand Down
10 changes: 10 additions & 0 deletions auth/src/include/firebase/auth.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ struct AuthData;
class AuthStateListener;
class IdTokenListener;
class PhoneAuthProvider;
class AuthRequest;
struct AuthCompletionHandle;
struct AuthResultCompletionHandle;
class FederatedAuthProvider;
Expand Down Expand Up @@ -631,6 +632,14 @@ class Auth {
void RemoveIdTokenListener(IdTokenListener* listener);
#endif // not SWIG

#if !defined(DOXYGEN) && !defined(SWIG)
///
/// Modify this Auth instance to communicate with the Firebase Authentication
/// emulator.
///
void UseEmulator(std::string host, uint32_t port);
#endif //! defined(DOXYGEN), to hide the api from public documentation.

/// Gets the App this auth object is connected to.
App& app();

Expand All @@ -653,6 +662,7 @@ class Auth {
/// @cond FIREBASE_APP_INTERNAL
friend class ::firebase::App;
friend class ::firebase::auth::PhoneAuthProvider;
friend class ::firebase::auth::AuthRequest;
friend class IdTokenRefreshListener;
friend class IdTokenRefreshThread;
friend class UserDataPersist;
Expand Down
12 changes: 10 additions & 2 deletions auth/src/ios/auth_ios.mm
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,11 @@ void UpdateCurrentUser(AuthData *auth_data) {
SetUserImpl(auth_data, user);
}

void SetEmulatorJni(AuthData *auth_data, const char *host, uint32_t port) {
NSUInteger ns_port = port;
[AuthImpl(auth_data) useEmulatorWithHost:@(host) port:ns_port];
}

void CheckEmulator(AuthData *auth_data) {
// Use emulator as long as this env variable is set, regardless its value.
if (std::getenv("USE_AUTH_EMULATOR") == nullptr) {
Expand All @@ -171,8 +176,7 @@ void CheckEmulator(AuthData *auth_data) {
port = std::stoi(std::getenv("AUTH_EMULATOR_PORT"));
}

NSUInteger ns_port = port;
[AuthImpl(auth_data) useEmulatorWithHost:@(kEmulatorLocalHost) port:ns_port];
SetEmulatorJni(auth_data, kEmulatorLocalHost, port);
}

// Platform-specific method to initialize AuthData.
Expand Down Expand Up @@ -699,6 +703,10 @@ void SignInResultCallback(FIRAuthDataResult *_Nullable auth_result, NSError *_Nu
return MakeFuture(&futures, handle);
}

void Auth::UseEmulator(std::string host, uint32_t port) {
SetEmulatorJni(auth_data_, host.c_str(), port);
}

// Remap iOS SDK errors reported by the UIDelegate. While these errors seem like
// user interaction errors, they are actually caused by bad provider ids.
NSError *RemapBadProviderIDErrors(NSError *_Nonnull error) {
Expand Down