Skip to content
Open
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
1 change: 1 addition & 0 deletions app/src/function_registry.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ enum FunctionId {
FnAppCheckGetTokenAsync,
FnAppCheckAddListener,
FnAppCheckRemoveListener,
FnAppCheckGetLimitedUseTokenAsync,
};

// Class for providing a generic way for firebase libraries to expose their
Expand Down
1 change: 1 addition & 0 deletions app_check/src/common/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ enum AppCheckFn {
kAppCheckFnGetAppCheckToken = 0,
kAppCheckFnGetAppCheckStringInternal,
kAppCheckFnGetLimitedUseAppCheckToken,
kAppCheckFnGetLimitedUseAppCheckStringInternal,
kAppCheckFnCount,
};

Expand Down
47 changes: 47 additions & 0 deletions app_check/src/desktop/app_check_desktop.cc
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,31 @@ Future<std::string> AppCheckInternal::GetAppCheckTokenStringInternal() {
return MakeFuture(future(), handle);
}

Future<std::string>
AppCheckInternal::GetLimitedUseAppCheckTokenStringInternal() {
auto handle = future()->SafeAlloc<std::string>(
kAppCheckFnGetLimitedUseAppCheckStringInternal);

AppCheckProvider* provider = GetProvider();
if (provider != nullptr) {
auto token_callback{[this, handle](firebase::app_check::AppCheckToken token,
int error_code,
const std::string& error_message) {
if (error_code == firebase::app_check::kAppCheckErrorNone) {
future()->CompleteWithResult(handle, 0, token.token);
} else {
future()->Complete(handle, error_code, error_message.c_str());
}
}};
provider->GetLimitedUseToken(token_callback);
} else {
future()->Complete(handle,
firebase::app_check::kAppCheckErrorInvalidConfiguration,
"No AppCheckProvider installed.");
}
return MakeFuture(future(), handle);
}

void AppCheckInternal::AddAppCheckListener(AppCheckListener* listener) {
if (listener) {
token_listeners_.push_back(listener);
Expand All @@ -211,6 +236,9 @@ void AppCheckInternal::InitRegistryCalls() {
app_->function_registry()->RegisterFunction(
::firebase::internal::FnAppCheckGetTokenAsync,
AppCheckInternal::GetAppCheckTokenAsyncForRegistry);
app_->function_registry()->RegisterFunction(
::firebase::internal::FnAppCheckGetLimitedUseTokenAsync,
AppCheckInternal::GetLimitedUseAppCheckTokenAsyncForRegistry);
app_->function_registry()->RegisterFunction(
::firebase::internal::FnAppCheckAddListener,
AppCheckInternal::AddAppCheckListenerForRegistry);
Expand All @@ -226,6 +254,8 @@ void AppCheckInternal::CleanupRegistryCalls() {
if (g_app_check_registry_count == 0) {
app_->function_registry()->UnregisterFunction(
::firebase::internal::FnAppCheckGetTokenAsync);
app_->function_registry()->UnregisterFunction(
::firebase::internal::FnAppCheckGetLimitedUseTokenAsync);
app_->function_registry()->UnregisterFunction(
::firebase::internal::FnAppCheckAddListener);
app_->function_registry()->UnregisterFunction(
Expand All @@ -250,6 +280,23 @@ bool AppCheckInternal::GetAppCheckTokenAsyncForRegistry(App* app,
return false;
}

// static
bool AppCheckInternal::GetLimitedUseAppCheckTokenAsyncForRegistry(
App* app, void* /*unused*/, void* out) {
Future<std::string>* out_future = static_cast<Future<std::string>*>(out);
if (!app || !out_future) {
return false;
}

AppCheck* app_check = AppCheck::GetInstance(app);
if (app_check && app_check->internal_) {
*out_future =
app_check->internal_->GetLimitedUseAppCheckTokenStringInternal();
return true;
}
return false;
}

void FunctionRegistryAppCheckListener::AddListener(
FunctionRegistryCallback callback, void* context) {
callbacks_.emplace_back(callback, context);
Expand Down
8 changes: 8 additions & 0 deletions app_check/src/desktop/app_check_desktop.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ class AppCheckInternal {
// internal methods to not conflict with the publicly returned future.
Future<std::string> GetAppCheckTokenStringInternal();

// Gets the limited-use App Check token as just the string, to be used by
// internal methods to not conflict with the publicly returned future.
Future<std::string> GetLimitedUseAppCheckTokenStringInternal();

void AddAppCheckListener(AppCheckListener* listener);

void RemoveAppCheckListener(AppCheckListener* listener);
Expand Down Expand Up @@ -100,6 +104,10 @@ class AppCheckInternal {
static bool GetAppCheckTokenAsyncForRegistry(App* app, void* /*unused*/,
void* out_future);

static bool GetLimitedUseAppCheckTokenAsyncForRegistry(App* app,
void* /*unused*/,
void* out_future);

static bool AddAppCheckListenerForRegistry(App* app, void* callback,
void* context);

Expand Down
2 changes: 1 addition & 1 deletion functions/integration_test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ endif()
# Add the Firebase libraries to the target using the function from the SDK.
add_subdirectory(${FIREBASE_CPP_SDK_DIR} bin/ EXCLUDE_FROM_ALL)
# Note that firebase_app needs to be last in the list.
set(firebase_libs firebase_functions firebase_auth firebase_app)
set(firebase_libs firebase_app_check firebase_functions firebase_auth firebase_app)
set(gtest_libs gtest gmock)
target_link_libraries(${integration_test_target_name} ${firebase_libs}
${gtest_libs} ${ADDITIONAL_LIBS})
2 changes: 2 additions & 0 deletions functions/integration_test/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ use_frameworks! :linkage => :static

target 'integration_test' do
platform :ios, '15.0'
pod 'Firebase/AppCheck', '12.10.0'
pod 'Firebase/Functions', '12.10.0'
pod 'Firebase/Auth', '12.10.0'
end

target 'integration_test_tvos' do
platform :tvos, '15.0'
pod 'Firebase/AppCheck', '12.10.0'
pod 'Firebase/Functions', '12.10.0'
pod 'Firebase/Auth', '12.10.0'
end
Expand Down
1 change: 1 addition & 0 deletions functions/integration_test/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ android {

apply from: "$gradle.firebase_cpp_sdk_dir/Android/firebase_dependencies.gradle"
firebaseCpp.dependencies {
appCheck
auth
functions
}
Expand Down
5 changes: 5 additions & 0 deletions functions/integration_test/functions/.firebaserc
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think we should remove this too

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"projects": {
"default": "functions-test-app"
}
}
4 changes: 4 additions & 0 deletions functions/integration_test/functions/firebase.json
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think this can be removed too

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"functions": {
}
}
52 changes: 52 additions & 0 deletions functions/integration_test/functions/functions/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright 2026 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.


/**
* Import function triggers from their respective submodules:
*
* const {onCall} = require("firebase-functions/v1/https"); // wait, V1 doesn't have /v1/https
*
* See a full list of supported triggers at https://firebase.google.com/docs/functions
*/

const functions = require("firebase-functions");

// Creates a function that consumes limited-use App Check tokens
exports.addtwowithlimiteduse = functions.runWith({
enforceAppCheck: true,
consumeAppCheckToken: true,
maxInstances: 10 // Setting maxInstances the V1 way
}).https.onCall((data, context) => {
// context.app will be defined if a valid App Check token was provided
if (context.app === undefined) {
throw new functions.https.HttpsError(
'failed-precondition',
'The function must be called from an App Check verified app.');
}

const firstNumber = data.firstNumber;
const secondNumber = data.secondNumber;

if (firstNumber === undefined || secondNumber === undefined) {
throw new functions.https.HttpsError('invalid-argument', 'The function must be called with "firstNumber" and "secondNumber".');
}

return {
firstNumber: firstNumber,
secondNumber: secondNumber,
operator: '+',
operationResult: Number(firstNumber) + Number(secondNumber),
};
});
Loading
Loading