Skip to content

Commit 06d53a2

Browse files
ncooke3paulb777
andauthored
feat(appcheck): implement RecaptchaEnterpriseProvider and tests (#16155)
Co-authored-by: Paul Beusterien <paulbeusterien@google.com>
1 parent 57e4e51 commit 06d53a2

36 files changed

Lines changed: 1372 additions & 52 deletions

.github/workflows/infra.samples.client_app.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ on:
2121

2222
env:
2323
FIREBASECI_USE_LATEST_GOOGLEAPPMEASUREMENT: 1
24+
FIREBASE_APP_CHECK_BRANCH: main
2425

2526
concurrency:
2627
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
@@ -44,6 +45,7 @@ jobs:
4445
method: xcodebuild
4546
os: ${{ matrix.os }}
4647
xcode: ${{ matrix.xcode }}
48+
env_vars: '{"FIREBASE_APP_CHECK_BRANCH": "main"}'
4749

4850
client-app-spm-source-firestore:
4951
strategy:
@@ -63,6 +65,7 @@ jobs:
6365
os: ${{ matrix.os }}
6466
xcode: ${{ matrix.xcode }}
6567
setup_command: echo "FIREBASE_SOURCE_FIRESTORE=1" >> $GITHUB_ENV
68+
env_vars: '{"FIREBASE_APP_CHECK_BRANCH": "main"}'
6669

6770
client-app-cocoapods:
6871
strategy:
@@ -80,3 +83,4 @@ jobs:
8083
os: ${{ matrix.os }}
8184
xcode: ${{ matrix.xcode }}
8285
setup_command: scripts/install_prereqs.sh ClientApp iOS xcodebuild
86+
env_vars: '{"FIREBASE_APP_CHECK_BRANCH": "main"}'

.github/workflows/infra.spm_global.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ jobs:
2929
spm-package-resolved:
3030
env:
3131
FIREBASECI_USE_LATEST_GOOGLEAPPMEASUREMENT: 1
32+
FIREBASE_APP_CHECK_BRANCH: main
3233
runs-on: macos-26
3334
outputs:
3435
cache_key: ${{ steps.generate_cache_key.outputs.cache_key }}
@@ -55,6 +56,9 @@ jobs:
5556
# Don't run on private repo unless it is a PR.
5657
if: (github.repository == 'Firebase/firebase-ios-sdk' && github.event_name == 'schedule') || github.event_name == 'pull_request'
5758
needs: [spm-package-resolved]
59+
env:
60+
FIREBASECI_USE_LATEST_GOOGLEAPPMEASUREMENT: 1
61+
FIREBASE_APP_CHECK_BRANCH: main
5862
strategy:
5963
matrix:
6064
include:
@@ -105,6 +109,8 @@ jobs:
105109
# Don't run on private repo unless it is a PR.
106110
if: (github.repository == 'Firebase/firebase-ios-sdk' && github.event_name == 'schedule') || github.event_name == 'pull_request'
107111
needs: [spm-package-resolved]
112+
env:
113+
FIREBASE_APP_CHECK_BRANCH: main
108114
strategy:
109115
matrix:
110116
include:
@@ -144,6 +150,8 @@ jobs:
144150
# Don't run on private repo unless it is a PR.
145151
if: (github.repository == 'Firebase/firebase-ios-sdk' && github.event_name == 'schedule') || github.event_name == 'pull_request'
146152
needs: [spm-package-resolved]
153+
env:
154+
FIREBASE_APP_CHECK_BRANCH: main
147155
strategy:
148156
matrix:
149157
# Full set of Firebase-Package tests only run on iOS. Run subset on other platforms.

.github/workflows/sdk.appcheck.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ jobs:
3030
uses: ./.github/workflows/_spm.yml
3131
with:
3232
target: ${{ matrix.target }}
33+
env_vars: '{"FIREBASE_APP_CHECK_BRANCH": "main"}'
3334

3435
catalyst:
3536
uses: ./.github/workflows/_catalyst.yml
@@ -57,6 +58,7 @@ jobs:
5758
method: spm
5859
sanitizers: ${{ matrix.diagnostic }}
5960
setup_command: scripts/setup_spm_tests.sh
61+
env_vars: '{"FIREBASE_APP_CHECK_BRANCH": "main"}'
6062

6163
app_check-cron-only:
6264
needs: pod_lib_lint

.github/workflows/sdk.core.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ jobs:
2828
uses: ./.github/workflows/_spm.yml
2929
with:
3030
target: CoreUnit
31+
env_vars: '{"FIREBASE_APP_CHECK_BRANCH": "main"}'
3132

3233
catalyst:
3334
uses: ./.github/workflows/_catalyst.yml

.github/workflows/sdk.firestore.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,7 @@ jobs:
540540
env:
541541
FIREBASECI_USE_LATEST_GOOGLEAPPMEASUREMENT: 1
542542
FIREBASE_SOURCE_FIRESTORE: 1
543+
FIREBASE_APP_CHECK_BRANCH: main
543544
outputs:
544545
cache_key: ${{ steps.generate_cache_key.outputs.cache_key }}
545546
steps:
@@ -591,6 +592,7 @@ jobs:
591592
runs-on: ${{ matrix.os }}
592593
env:
593594
FIREBASE_SOURCE_FIRESTORE: 1
595+
FIREBASE_APP_CHECK_BRANCH: main
594596
steps:
595597
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
596598
- name: Xcode
@@ -614,6 +616,7 @@ jobs:
614616
with:
615617
target: FirebaseFirestoreTests
616618
platforms: iOS
619+
env_vars: '{"FIREBASE_APP_CHECK_BRANCH": "main"}'
617620

618621
spm-source-cron:
619622
# Don't run on private repo.
@@ -624,6 +627,7 @@ jobs:
624627
target: [tvOS, macOS, catalyst]
625628
env:
626629
FIREBASE_SOURCE_FIRESTORE: 1
630+
FIREBASE_APP_CHECK_BRANCH: main
627631
steps:
628632
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
629633
- name: Xcode
@@ -648,6 +652,8 @@ jobs:
648652
strategy:
649653
matrix:
650654
target: [tvOS, macOS, catalyst]
655+
env:
656+
FIREBASE_APP_CHECK_BRANCH: main
651657
steps:
652658
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
653659
- name: Xcode

FirebaseAppCheck.podspec

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ Pod::Spec.new do |s|
4444
s.osx.weak_framework = 'DeviceCheck'
4545
s.tvos.weak_framework = 'DeviceCheck'
4646

47-
s.dependency 'AppCheckCore', '~> 11.0'
47+
s.dependency 'AppCheckCore', '~> 11.3'
4848
s.dependency 'FirebaseAppCheckInterop', '~> 12.15.0'
4949
s.dependency 'FirebaseCore', '~> 12.15.0'
5050
s.dependency 'GoogleUtilities/Environment', '~> 8.1'
@@ -93,7 +93,11 @@ Pod::Spec.new do |s|
9393
}
9494
swift_unit_tests.source_files = [
9595
base_dir + 'Tests/Unit/Swift/**/*.swift',
96+
'SharedTestUtilities/ExceptionCatcher.[mh]'
9697
]
98+
swift_unit_tests.pod_target_xcconfig = {
99+
'SWIFT_OBJC_BRIDGING_HEADER' => '$(PODS_TARGET_SRCROOT)/FirebaseAppCheck/Tests/Unit/Swift/FirebaseAppCheck-unit-Bridging-Header.h'
100+
}
97101

98102
swift_unit_tests.dependency 'FirebaseCoreExtension', '~> 12.15.0'
99103
end
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
# E2E Testing with FIRAppCheckTestApp
2+
3+
This document provides information on how to configure and run End-to-End (E2E)
4+
tests for App Check providers using this sample app.
5+
6+
## Configurability
7+
8+
The app's behavior can be configured using environment variables passed during
9+
test execution.
10+
11+
### Environment Variables
12+
13+
Starting with Xcode 13, you can pass environment variables directly to the
14+
test runner by prefixing them with `TEST_RUNNER_`. The prefix is stripped when
15+
it reaches the test process.
16+
17+
- **`TEST_RUNNER_RECAPTCHA_SITE_KEY`**: The reCAPTCHA site key used
18+
by the `AppCheckRecaptchaProvider`.
19+
- **Access in Code**: Read via
20+
`ProcessInfo.processInfo.environment["RECAPTCHA_SITE_KEY"]`.
21+
- **`TEST_RUNNER_APP_CHECK_PROVIDER`**: Specifies which App Check provider
22+
factory to use.
23+
- **Supported Values**: `recaptcha` (default), `debug`.
24+
- **Access in Code**: Read via
25+
`ProcessInfo.processInfo.environment["APP_CHECK_PROVIDER"]`.
26+
27+
### Manual Override
28+
29+
For local debugging and manual testing, you can override the environment
30+
variables by setting `manualProviderOverride` in `AppDelegate.swift`:
31+
32+
```swift
33+
let manualProviderOverride: String? = "debug"
34+
```
35+
36+
## Running Tests
37+
38+
The commands below should be run from the **repository root**.
39+
40+
### Prerequisites
41+
- Ensure you have a local checkout of the `app-check` repository if you are
42+
developing it locally. Set `FIREBASE_APP_CHECK_LOCAL_PATH` to point to it.
43+
44+
### Sample Commands
45+
46+
#### Run tests with reCAPTCHA provider
47+
48+
```bash
49+
export TEST_RUNNER_RECAPTCHA_SITE_KEY="your_site_key_here"
50+
export TEST_RUNNER_APP_CHECK_PROVIDER="recaptcha"
51+
export FIREBASE_APP_CHECK_LOCAL_PATH="/path/to/your/local/app-check"
52+
SIM_ID=$(xcrun simctl list devices available | grep "iPhone" | grep -E -o '[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}' | head -n 1)
53+
54+
xcodebuild test \
55+
-workspace FirebaseAppCheck/Apps/FIRAppCheckTestApp/FIRAppCheckTestApp.xcworkspace \
56+
-scheme FIRAppCheckTestApp \
57+
-destination "platform=iOS Simulator,id=$SIM_ID"
58+
```
59+
60+
#### Run tests with Debug provider
61+
62+
```bash
63+
export TEST_RUNNER_APP_CHECK_PROVIDER="debug"
64+
export FIREBASE_APP_CHECK_LOCAL_PATH="/path/to/your/local/app-check"
65+
SIM_ID=$(xcrun simctl list devices available | grep "iPhone" | grep -E -o '[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}' | head -n 1)
66+
67+
xcodebuild test \
68+
-workspace FirebaseAppCheck/Apps/FIRAppCheckTestApp/FIRAppCheckTestApp.xcworkspace \
69+
-scheme FIRAppCheckTestApp \
70+
-destination "platform=iOS Simulator,id=$SIM_ID"
71+
```
72+
*Note: The Debug provider might require you to register the generated debug token in the Firebase Console for the tests to pass if they interact with live services.*
73+
74+
### Running and Testing in Xcode
75+
76+
If you prefer to use the Xcode UI instead of `xcodebuild`, follow these steps
77+
to configure the environment:
78+
79+
#### 1. Resolve Local Dependency
80+
If you are using a local checkout of the `app-check` repository, Xcode must be
81+
launched from the terminal with the `FIREBASE_APP_CHECK_LOCAL_PATH` environment
82+
variable set so that Swift Package Manager can resolve it correctly.
83+
84+
Run the following command from the repository root:
85+
```bash
86+
open --env FIREBASE_APP_CHECK_LOCAL_PATH=/path/to/your/local/app-check FirebaseAppCheck/Apps/FIRAppCheckTestApp/FIRAppCheckTestApp.xcworkspace
87+
```
88+
89+
#### 2. Configure Provider and Site Key
90+
You have two options to configure the provider when running or testing in Xcode:
91+
92+
**Option A: Via Manual Override in Code (Easiest for Running the App)**
93+
If you just want to quickly run the app with a specific provider without
94+
changing scheme settings:
95+
1. Open `AppDelegate.swift`.
96+
2. Locate `manualProviderOverride` in `application(_:didFinishLaunchingWithOptions:)`.
97+
3. Set it to your desired provider:
98+
```swift
99+
let manualProviderOverride: String? = "recaptcha"
100+
```
101+
*Note: Remember to revert this change before committing.*
102+
103+
**Option B: Via Xcode Scheme (Recommended for Tests)**
104+
This avoids modifying code and works for both running and testing.
105+
1. In Xcode, go to **Product > Scheme > Edit Scheme...** (or press `⌘<`).
106+
2. Select the **Run** or **Test** action in the left sidebar, depending on
107+
what you are doing.
108+
3. Go to the **Arguments** tab.
109+
4. In the **Environment Variables** section, add:
110+
* `APP_CHECK_PROVIDER`: Set to `recaptcha` or `debug`.
111+
* `RECAPTCHA_SITE_KEY`: Set to your reCAPTCHA site key (required for
112+
`recaptcha`).
113+
114+
### Running and Testing with CocoaPods
115+
116+
If you prefer to use the CocoaPods workflow instead of SPM:
117+
118+
#### 0. Clean Up State (Optional but Recommended)
119+
If you are switching from the SPM workflow or encounter issues, it is
120+
recommended to clean up the CocoaPods state first:
121+
```bash
122+
pod deintegrate FirebaseAppCheck/Apps/FIRAppCheckTestApp/FIRAppCheckTestApp.xcodeproj
123+
rm -rf FirebaseAppCheck/Apps/FIRAppCheckTestApp/FIRAppCheckTestApp.xcworkspace
124+
rm -f FirebaseAppCheck/Apps/FIRAppCheckTestApp/Podfile.lock
125+
```
126+
127+
#### 1. Install Dependencies
128+
To ensure a clean update and avoid conflicts with local development paths or
129+
stale state, it is recommended to remove the existing `Pods` directory and
130+
`Podfile.lock` before updating.
131+
132+
Run the following command from the repository root:
133+
```bash
134+
rm -rf FirebaseAppCheck/Apps/FIRAppCheckTestApp/Pods
135+
rm -f FirebaseAppCheck/Apps/FIRAppCheckTestApp/Podfile.lock
136+
FIREBASE_APP_CHECK_LOCAL_PATH="/path/to/your/local/app-check" pod update --repo-update --project-directory=FirebaseAppCheck/Apps/FIRAppCheckTestApp/
137+
```
138+
139+
#### 2. Open Workspace
140+
Open the generated CocoaPods workspace instead of the project file:
141+
```bash
142+
open FirebaseAppCheck/Apps/FIRAppCheckTestApp/FIRAppCheckTestApp.xcworkspace
143+
```
144+
145+
#### 3. Remove SPM Dependencies (If needed)
146+
By default, the project file is configured for SPM. To avoid duplicate symbol
147+
issues or conflicting resolutions when using CocoaPods:
148+
1. In Xcode, select the project in the file navigator.
149+
2. Select the project file at the top (not a target).
150+
3. Go to the **Package Dependencies** tab.
151+
4. Remove the `firebase-ios-sdk` or `app-check` package references if they
152+
appear there.
153+
5. Also, select the `FIRAppCheckTestApp` target, go to the **General** tab,
154+
and scroll down to **Frameworks, Libraries, and Embedded Content**.
155+
6. Remove any SPM-resolved frameworks from this list.
156+
157+
#### 4. Configure and Run
158+
You can configure the provider and site key either via the Xcode Scheme or by
159+
passing environment variables to `xcodebuild`.
160+
161+
**Via Xcode Scheme:**
162+
Follow the instructions in **[Running and Testing in Xcode](#running-and-testing-in-xcode)**.
163+
164+
**Via `xcodebuild` (Command Line):**
165+
Run the following command from the repository root, replacing the site key with
166+
your own:
167+
```bash
168+
export TEST_RUNNER_RECAPTCHA_SITE_KEY="your_site_key_here"
169+
export TEST_RUNNER_APP_CHECK_PROVIDER="recaptcha"
170+
SIM_ID=$(xcrun simctl list devices available | grep "iPhone" | grep -E -o '[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}' | head -n 1)
171+
172+
xcodebuild test \
173+
-workspace FirebaseAppCheck/Apps/FIRAppCheckTestApp/FIRAppCheckTestApp.xcworkspace \
174+
-scheme FIRAppCheckTestApp \
175+
-destination "platform=iOS Simulator,id=$SIM_ID"
176+
```
177+
*(Note: See [Running Tests](#running-tests) for how to dynamically find a valid
178+
simulator destination).*
179+
180+
## Project Structure
181+
182+
- **`FIRAppCheckTestAppTests`**: A hosted unit test target containing the test cases. It runs inside the app process to have access to the full app context.

0 commit comments

Comments
 (0)