Skip to content

Commit 888e725

Browse files
authored
Add ability to set the App Check Debug Factory token (#1288)
* Add a way to set the App Check debug token * Formatting * Update build.gradle * Update debug_provider_ios.h * Change variable name
1 parent 925430a commit 888e725

17 files changed

+180
-49
lines changed

app_check/integration_test/build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ android {
8383
lintOptions {
8484
abortOnError false
8585
}
86+
packagingOptions {
87+
pickFirst 'META-INF/**/coroutines.pro'
88+
}
8689
}
8790

8891
apply from: "$gradle.firebase_cpp_sdk_dir/Android/firebase_dependencies.gradle"

app_check/src/android/app_check_android.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ AppCheckInternal::AppCheckInternal(App* app) : app_(app) {
297297
util::Terminate(env);
298298
} else {
299299
// Each provider is optional as a user may or may not use it.
300-
CacheDebugProviderMethodIds(env, activity);
300+
CacheDebugProviderMethodIds(env, activity, embedded_files);
301301
CachePlayIntegrityProviderMethodIds(env, activity);
302302
g_initialized_count++;
303303
}

app_check/src/android/debug_provider_android.cc

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@
1414

1515
#include "app_check/src/android/debug_provider_android.h"
1616

17+
#include <string>
18+
#include <vector>
19+
1720
#include "app/src/app_common.h"
21+
#include "app/src/embedded_file.h"
1822
#include "app/src/util_android.h"
1923
#include "app_check/src/android/common_android.h"
2024
#include "firebase/app_check/debug_provider.h"
@@ -43,24 +47,45 @@ METHOD_LOOKUP_DEFINITION(
4347
"com/google/firebase/appcheck/debug/DebugAppCheckProviderFactory",
4448
DEBUG_PROVIDER_FACTORY_METHODS)
4549

50+
// clang-format off
51+
#define JNI_APP_CHECK_DEBUG_HELPER_METHODS(X) \
52+
X(SetDebugToken, "SetDebugToken", \
53+
"(Lcom/google/firebase/FirebaseApp;Ljava/lang/String;)V", \
54+
util::kMethodTypeStatic)
55+
// clang-format on
56+
57+
METHOD_LOOKUP_DECLARATION(jni_debug_helper, JNI_APP_CHECK_DEBUG_HELPER_METHODS)
58+
METHOD_LOOKUP_DEFINITION(
59+
jni_debug_helper,
60+
"com/google/firebase/appcheck/internal/cpp/JniAppCheckDebugHelper",
61+
JNI_APP_CHECK_DEBUG_HELPER_METHODS)
62+
4663
static bool g_methods_cached = false;
4764

4865
const char kMethodsNotCachedError[] =
4966
"DebugAppCheckProviderFactory methods were not cached.";
5067

51-
bool CacheDebugProviderMethodIds(JNIEnv* env, jobject activity) {
52-
// Cache the DebugProvider classes.
53-
g_methods_cached = debug_provider_factory::CacheMethodIds(env, activity);
68+
bool CacheDebugProviderMethodIds(
69+
JNIEnv* env, jobject activity,
70+
const std::vector<firebase::internal::EmbeddedFile>& embedded_files) {
71+
// Cache the DebugProvider and JniAppCheckDebugHelper classes.
72+
g_methods_cached =
73+
debug_provider_factory::CacheMethodIds(env, activity) &&
74+
jni_debug_helper::CacheClassFromFiles(env, activity, &embedded_files) &&
75+
jni_debug_helper::CacheMethodIds(env, activity);
5476
return g_methods_cached;
5577
}
5678

5779
void ReleaseDebugProviderClasses(JNIEnv* env) {
5880
debug_provider_factory::ReleaseClass(env);
81+
jni_debug_helper::ReleaseClass(env);
5982
g_methods_cached = false;
6083
}
6184

6285
DebugAppCheckProviderFactoryInternal::DebugAppCheckProviderFactoryInternal()
63-
: created_providers_(), android_provider_factory_(nullptr) {}
86+
: created_providers_(),
87+
android_provider_factory_(nullptr),
88+
debug_token_() {}
6489

6590
DebugAppCheckProviderFactoryInternal::~DebugAppCheckProviderFactoryInternal() {
6691
for (auto it = created_providers_.begin(); it != created_providers_.end();
@@ -98,6 +123,19 @@ AppCheckProvider* DebugAppCheckProviderFactoryInternal::CreateProvider(
98123
env->DeleteLocalRef(j_provider_factory_local);
99124
}
100125
jobject platform_app = app->GetPlatformApp();
126+
127+
// Before making the Provider, which is when Android reads the Debug token,
128+
// if we have a token to override it with, use it.
129+
if (!debug_token_.empty()) {
130+
jstring java_token = env->NewStringUTF(debug_token_.c_str());
131+
env->CallStaticVoidMethod(
132+
jni_debug_helper::GetClass(),
133+
jni_debug_helper::GetMethodId(jni_debug_helper::kSetDebugToken),
134+
platform_app, java_token);
135+
FIREBASE_ASSERT(!util::CheckAndClearJniExceptions(env));
136+
env->DeleteLocalRef(java_token);
137+
}
138+
101139
jobject j_android_provider_local = env->CallObjectMethod(
102140
android_provider_factory_,
103141
debug_provider_factory::GetMethodId(debug_provider_factory::kCreate),
@@ -114,6 +152,12 @@ AppCheckProvider* DebugAppCheckProviderFactoryInternal::CreateProvider(
114152
return cpp_provider;
115153
}
116154

155+
void DebugAppCheckProviderFactoryInternal::SetDebugToken(
156+
const std::string& token) {
157+
// The App may not exist yet, so we save the debug token to use later.
158+
debug_token_ = token;
159+
}
160+
117161
} // namespace internal
118162
} // namespace app_check
119163
} // namespace firebase

app_check/src/android/debug_provider_android.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,20 @@
1616
#define FIREBASE_APP_CHECK_SRC_ANDROID_DEBUG_PROVIDER_ANDROID_H_
1717

1818
#include <map>
19+
#include <string>
20+
#include <vector>
1921

22+
#include "app/src/embedded_file.h"
2023
#include "firebase/app_check.h"
2124

2225
namespace firebase {
2326
namespace app_check {
2427
namespace internal {
2528

2629
// Cache the method ids so we don't have to look up JNI functions by name.
27-
bool CacheDebugProviderMethodIds(JNIEnv* env, jobject activity);
30+
bool CacheDebugProviderMethodIds(
31+
JNIEnv* env, jobject activity,
32+
const std::vector<firebase::internal::EmbeddedFile>& embedded_files);
2833

2934
// Release provider classes cached by CacheDebugProviderMethodIds().
3035
void ReleaseDebugProviderClasses(JNIEnv* env);
@@ -37,10 +42,14 @@ class DebugAppCheckProviderFactoryInternal : public AppCheckProviderFactory {
3742

3843
AppCheckProvider* CreateProvider(App* app) override;
3944

45+
void SetDebugToken(const std::string& token);
46+
4047
private:
4148
jobject android_provider_factory_;
4249

4350
std::map<App*, AppCheckProvider*> created_providers_;
51+
52+
std::string debug_token_;
4453
};
4554

4655
} // namespace internal

app_check/src/android/play_integrity_provider_android.cc

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -120,14 +120,9 @@ AppCheckProvider* PlayIntegrityProviderFactoryInternal::CreateProvider(
120120

121121
} // namespace internal
122122

123-
static PlayIntegrityProviderFactory* g_play_integrity_provider_factory =
124-
nullptr;
125-
126123
PlayIntegrityProviderFactory* PlayIntegrityProviderFactory::GetInstance() {
127-
if (!g_play_integrity_provider_factory) {
128-
g_play_integrity_provider_factory = new PlayIntegrityProviderFactory();
129-
}
130-
return g_play_integrity_provider_factory;
124+
static PlayIntegrityProviderFactory g_play_integrity_provider_factory;
125+
return &g_play_integrity_provider_factory;
131126
}
132127

133128
PlayIntegrityProviderFactory::PlayIntegrityProviderFactory()

app_check/src/common/debug_provider_common.cc

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
#include <string>
16+
1517
#include "firebase/app_check/debug_provider.h"
1618

1719
// Include the header that matches the platform being used.
@@ -27,14 +29,9 @@
2729
namespace firebase {
2830
namespace app_check {
2931

30-
static DebugAppCheckProviderFactory* g_debug_app_check_provider_factory =
31-
nullptr;
32-
3332
DebugAppCheckProviderFactory* DebugAppCheckProviderFactory::GetInstance() {
34-
if (!g_debug_app_check_provider_factory) {
35-
g_debug_app_check_provider_factory = new DebugAppCheckProviderFactory();
36-
}
37-
return g_debug_app_check_provider_factory;
33+
static DebugAppCheckProviderFactory g_debug_app_check_provider_factory;
34+
return &g_debug_app_check_provider_factory;
3835
}
3936

4037
DebugAppCheckProviderFactory::DebugAppCheckProviderFactory()
@@ -54,5 +51,11 @@ AppCheckProvider* DebugAppCheckProviderFactory::CreateProvider(App* app) {
5451
return nullptr;
5552
}
5653

54+
void DebugAppCheckProviderFactory::SetDebugToken(const std::string& token) {
55+
if (internal_) {
56+
return internal_->SetDebugToken(token);
57+
}
58+
}
59+
5760
} // namespace app_check
5861
} // namespace firebase

app_check/src/desktop/debug_provider_desktop.cc

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ namespace internal {
3434

3535
class DebugAppCheckProvider : public AppCheckProvider {
3636
public:
37-
explicit DebugAppCheckProvider(App* app);
37+
DebugAppCheckProvider(App* app, const std::string& token);
3838
~DebugAppCheckProvider() override;
3939

4040
void GetToken(std::function<void(AppCheckToken, int, const std::string&)>
@@ -44,10 +44,12 @@ class DebugAppCheckProvider : public AppCheckProvider {
4444
App* app_;
4545

4646
scheduler::Scheduler scheduler_;
47+
48+
std::string debug_token_;
4749
};
4850

49-
DebugAppCheckProvider::DebugAppCheckProvider(App* app)
50-
: app_(app), scheduler_() {
51+
DebugAppCheckProvider::DebugAppCheckProvider(App* app, const std::string& token)
52+
: app_(app), scheduler_(), debug_token_(token) {
5153
firebase::rest::util::Initialize();
5254
firebase::rest::InitTransportCurl();
5355
}
@@ -90,19 +92,22 @@ void DebugAppCheckProvider::GetToken(
9092
std::function<void(AppCheckToken, int, const std::string&)>
9193
completion_callback) {
9294
// 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");
95+
const char* debug_token_cstr;
96+
if (!debug_token_.empty()) {
97+
debug_token_cstr = debug_token_.c_str();
98+
} else {
99+
debug_token_cstr = std::getenv("APP_CHECK_DEBUG_TOKEN");
100+
}
96101

97-
if (!debug_token) {
102+
if (!debug_token_cstr) {
98103
completion_callback({}, kAppCheckErrorInvalidConfiguration,
99104
"Missing debug token");
100105
return;
101106
}
102107

103108
// Exchange debug token with the backend to get a proper attestation token.
104109
auto request = MakeShared<DebugTokenRequest>(app_);
105-
request->SetDebugToken(debug_token);
110+
request->SetDebugToken(debug_token_cstr);
106111

107112
// Use an async call, since we don't want to block on the server response.
108113
auto async_call =
@@ -111,7 +116,7 @@ void DebugAppCheckProvider::GetToken(
111116
}
112117

113118
DebugAppCheckProviderFactoryInternal::DebugAppCheckProviderFactoryInternal()
114-
: provider_map_() {}
119+
: provider_map_(), debug_token_() {}
115120

116121
DebugAppCheckProviderFactoryInternal::~DebugAppCheckProviderFactoryInternal() {
117122
// Clear the map
@@ -129,11 +134,16 @@ AppCheckProvider* DebugAppCheckProviderFactoryInternal::CreateProvider(
129134
return it->second;
130135
}
131136
// Create a new provider and cache it
132-
AppCheckProvider* provider = new DebugAppCheckProvider(app);
137+
AppCheckProvider* provider = new DebugAppCheckProvider(app, debug_token_);
133138
provider_map_[app] = provider;
134139
return provider;
135140
}
136141

142+
void DebugAppCheckProviderFactoryInternal::SetDebugToken(
143+
const std::string& token) {
144+
debug_token_ = token;
145+
}
146+
137147
} // namespace internal
138148
} // namespace app_check
139149
} // namespace firebase

app_check/src/desktop/debug_provider_desktop.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#define FIREBASE_APP_CHECK_SRC_DESKTOP_DEBUG_PROVIDER_DESKTOP_H_
1717

1818
#include <map>
19+
#include <string>
1920

2021
#include "firebase/app_check.h"
2122

@@ -31,8 +32,12 @@ class DebugAppCheckProviderFactoryInternal : public AppCheckProviderFactory {
3132

3233
AppCheckProvider* CreateProvider(App* app) override;
3334

35+
void SetDebugToken(const std::string& token);
36+
3437
private:
3538
std::map<App*, AppCheckProvider*> provider_map_;
39+
40+
std::string debug_token_;
3641
};
3742

3843
} // namespace internal

app_check/src/include/firebase/app_check/app_attest_provider.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,21 @@ class AppAttestProviderFactoryInternal;
2828
/// AppAttestProviders. This is the default implementation.
2929
class AppAttestProviderFactory : public AppCheckProviderFactory {
3030
public:
31+
AppAttestProviderFactory(const AppAttestProviderFactory&) = delete;
32+
AppAttestProviderFactory& operator=(const AppAttestProviderFactory&) = delete;
33+
3134
/// Gets an instance of this class for installation into a
3235
/// firebase::app_check::AppCheck instance.
3336
static AppAttestProviderFactory* GetInstance();
3437

35-
virtual ~AppAttestProviderFactory();
36-
3738
/// Gets the AppCheckProvider associated with the given
3839
/// {@link App} instance, or creates one if none
3940
/// already exists.
4041
firebase::app_check::AppCheckProvider* CreateProvider(App* app) override;
4142

4243
private:
4344
AppAttestProviderFactory();
45+
~AppAttestProviderFactory() override;
4446

4547
internal::AppAttestProviderFactoryInternal* internal_;
4648
};

app_check/src/include/firebase/app_check/debug_provider.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#ifndef FIREBASE_APP_CHECK_SRC_INCLUDE_FIREBASE_APP_CHECK_DEBUG_PROVIDER_H_
1616
#define FIREBASE_APP_CHECK_SRC_INCLUDE_FIREBASE_APP_CHECK_DEBUG_PROVIDER_H_
1717

18+
#include <string>
19+
1820
#include "firebase/app_check.h"
1921

2022
namespace firebase {
@@ -34,7 +36,9 @@ class DebugAppCheckProviderFactoryInternal;
3436
/// NOTE: Do not use the debug provider in applications used by real users.
3537
class DebugAppCheckProviderFactory : public AppCheckProviderFactory {
3638
public:
37-
~DebugAppCheckProviderFactory() override;
39+
DebugAppCheckProviderFactory(const DebugAppCheckProviderFactory&) = delete;
40+
DebugAppCheckProviderFactory& operator=(const DebugAppCheckProviderFactory&) =
41+
delete;
3842

3943
/// Gets an instance of this class for installation into a
4044
/// firebase::app_check::AppCheck instance.
@@ -45,8 +49,14 @@ class DebugAppCheckProviderFactory : public AppCheckProviderFactory {
4549
/// already exists.
4650
firebase::app_check::AppCheckProvider* CreateProvider(App* app) override;
4751

52+
/// Sets the Debug Token to use when communicating with the backend.
53+
/// This should match a debug token set in the Firebase console for your
54+
/// App.
55+
void SetDebugToken(const std::string& token);
56+
4857
private:
4958
DebugAppCheckProviderFactory();
59+
~DebugAppCheckProviderFactory() override;
5060

5161
internal::DebugAppCheckProviderFactoryInternal* internal_;
5262
};

0 commit comments

Comments
 (0)