Skip to content

Commit 3c63826

Browse files
feat(app-check): Debug token support for the activate method (#17723)
* feat(app-check): Debug token support for the activate method * feat(app-check): Refactor activate method to use new provider classes * feat(app-check): Update debug provider usage and parameters in documentation * chore: remove deprecated AndroidSafetyNetProvider and update documentation * chore: rename webProvider to providerWeb for consistency across the codebase * chore: add webProvider parameter to MockFirebaseAppCheck.activate method --------- Co-authored-by: Furkan KURT <[email protected]>
1 parent 0b6b13d commit 3c63826

File tree

25 files changed

+463
-65
lines changed

25 files changed

+463
-65
lines changed

docs/app-check/debug-provider.md

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ To use the debug provider while running your app in a simulator interactively
3737
WidgetsFlutterBinding.ensureInitialized();
3838
await Firebase.initializeApp();
3939
await FirebaseAppCheck.instance.activate(
40-
// Set appleProvider to `AppleProvider.debug`
41-
appleProvider: AppleProvider.debug,
40+
// Set providerApple to use AppleDebugProvider
41+
providerApple: AppleDebugProvider('123a4567-b89c-12d3-e456-789012345678'),
4242
);
4343
runApp(App());
4444
}
@@ -83,9 +83,9 @@ Future<void> main() async {
8383
WidgetsFlutterBinding.ensureInitialized();
8484
await Firebase.initializeApp();
8585
await FirebaseAppCheck.instance.activate(
86-
webRecaptchaSiteKey: 'recaptcha-v3-site-key',
87-
// Set androidProvider to `AndroidProvider.debug`
88-
androidProvider: AndroidProvider.debug,
86+
webProvider: ReCaptchaV3Provider('recaptcha-v3-site-key'),
87+
// Set providerAndroid to use AndroidDebugProvider
88+
providerAndroid: AndroidDebugProvider('123a4567-b89c-12d3-e456-789012345678'),
8989
);
9090
runApp(App());
9191
}
@@ -146,3 +146,44 @@ Because this token allows access to your Firebase resources without a
146146
valid device, it is crucial that you keep it private. Don't commit it to a
147147
public repository, and if a registered token is ever compromised, revoke it
148148
immediately in the Firebase console.
149+
150+
## Manually setting up the App Check Debug Token for CI environment or development
151+
152+
If you want to use the debug provider in a testing environment or CI, you can
153+
manually set the debug token in your app. This is useful when you want to run
154+
your app in an environment where the debug token is not automatically generated.
155+
156+
To manually set the debug token, pass your debug token directly to the debug provider
157+
classes when activating App Check. For example:
158+
159+
```dart
160+
import 'package:flutter/material.dart';
161+
import 'package:firebase_core/firebase_core.dart';
162+
163+
// Import the firebase_app_check plugin
164+
import 'package:firebase_app_check/firebase_app_check.dart';
165+
166+
Future<void> main() async {
167+
WidgetsFlutterBinding.ensureInitialized();
168+
await Firebase.initializeApp();
169+
await FirebaseAppCheck.instance.activate(
170+
webProvider: ReCaptchaV3Provider('recaptcha-v3-site-key'),
171+
// Set providerAndroid with debug token
172+
providerAndroid: AndroidDebugProvider('123a4567-b89c-12d3-e456-789012345678'),
173+
// Set providerApple with debug token
174+
providerApple: AppleDebugProvider('123a4567-b89c-12d3-e456-789012345678'),
175+
);
176+
runApp(App());
177+
}
178+
179+
```
180+
181+
{# Google-internal common file: #}
182+
<<../_includes/manage-debug-tokens.md>>
183+
184+
After you register the token, Firebase backend services will accept it as valid.
185+
186+
Because this token allows access to your Firebase resources without a
187+
valid device, it is crucial that you keep it private. Don't commit it to a
188+
public repository, and if a registered token is ever compromised, revoke it
189+
immediately in the Firebase console.

docs/app-check/default-providers.md

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -81,19 +81,18 @@ Future<void> main() async {
8181
// You can also use a `ReCaptchaEnterpriseProvider` provider instance as an
8282
// argument for `webProvider`
8383
webProvider: ReCaptchaV3Provider('recaptcha-v3-site-key'),
84-
// Default provider for Android is the Play Integrity provider. You can use the "AndroidProvider" enum to choose
84+
// Default provider for Android is the Play Integrity provider. You can use the "providerAndroid" parameter to choose
8585
// your preferred provider. Choose from:
86-
// 1. Debug provider
87-
// 2. Safety Net provider
88-
// 3. Play Integrity provider
89-
androidProvider: AndroidProvider.debug,
90-
// Default provider for iOS/macOS is the Device Check provider. You can use the "AppleProvider" enum to choose
91-
// your preferred provider. Choose from:
92-
// 1. Debug provider
93-
// 2. Device Check provider
94-
// 3. App Attest provider
95-
// 4. App Attest provider with fallback to Device Check provider (App Attest provider is only available on iOS 14.0+, macOS 14.0+)
96-
appleProvider: AppleProvider.appAttest,
86+
// 1. AndroidDebugProvider for debug environments
87+
// 2. AndroidPlayIntegrityProvider
88+
providerAndroid: AndroidDebugProvider(),
89+
// Default provider for iOS/macOS is the Device Check provider. You can use the "providerApple" parameter to choose
90+
// your preferred provider. Choose from:
91+
// 1. AppleDebugProvider for debug environments
92+
// 2. AppleDeviceCheckProvider
93+
// 3. AppleAppAttestProvider
94+
// 4. AppleAppAttestProviderWithDeviceCheckFallback (App Attest provider is only available on iOS 14.0+, macOS 14.0+)
95+
providerApple: AppleAppAttestProvider(),
9796
);
9897
runApp(App());
9998
}

packages/firebase_app_check/firebase_app_check/android/src/main/java/io/flutter/plugins/firebase/appcheck/FlutterFirebaseAppCheckPlugin.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ private Task<Void> activate(Map<String, Object> arguments) {
9898
case debugProvider:
9999
{
100100
FirebaseAppCheck firebaseAppCheck = getAppCheck(arguments);
101+
FlutterFirebaseAppRegistrar.debugToken =
102+
(String) arguments.get("androidDebugToken");
101103
firebaseAppCheck.installAppCheckProviderFactory(
102104
DebugAppCheckProviderFactory.getInstance());
103105
break;

packages/firebase_app_check/firebase_app_check/android/src/main/java/io/flutter/plugins/firebase/appcheck/FlutterFirebaseAppRegistrar.java

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,38 @@
55
package io.flutter.plugins.firebase.appcheck;
66

77
import androidx.annotation.Keep;
8+
import androidx.annotation.Nullable;
9+
import com.google.firebase.appcheck.debug.InternalDebugSecretProvider;
810
import com.google.firebase.components.Component;
911
import com.google.firebase.components.ComponentRegistrar;
1012
import com.google.firebase.platforminfo.LibraryVersionComponent;
11-
import java.util.Collections;
13+
import java.util.Arrays;
1214
import java.util.List;
1315

1416
@Keep
15-
public class FlutterFirebaseAppRegistrar implements ComponentRegistrar {
17+
public class FlutterFirebaseAppRegistrar
18+
implements ComponentRegistrar, InternalDebugSecretProvider {
19+
20+
private static final String DEBUG_SECRET_NAME = "fire-app-check-debug-secret";
21+
public static String debugToken;
22+
1623
@Override
1724
public List<Component<?>> getComponents() {
18-
return Collections.<Component<?>>singletonList(
19-
LibraryVersionComponent.create(BuildConfig.LIBRARY_NAME, BuildConfig.LIBRARY_VERSION));
25+
Component<?> library =
26+
LibraryVersionComponent.create(BuildConfig.LIBRARY_NAME, BuildConfig.LIBRARY_VERSION);
27+
28+
Component<InternalDebugSecretProvider> debugSecretProvider =
29+
Component.builder(InternalDebugSecretProvider.class)
30+
.name(DEBUG_SECRET_NAME)
31+
.factory(container -> this)
32+
.build();
33+
34+
return Arrays.asList(library, debugSecretProvider);
35+
}
36+
37+
@Nullable
38+
@Override
39+
public String getDebugSecret() {
40+
return debugToken;
2041
}
2142
}

packages/firebase_app_check/firebase_app_check/example/lib/main.dart

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
import 'package:cloud_firestore/cloud_firestore.dart';
56
import 'package:firebase_app_check/firebase_app_check.dart';
67
import 'package:firebase_core/firebase_core.dart';
78
import 'package:flutter/foundation.dart';
89
import 'package:flutter/material.dart';
9-
import 'package:cloud_firestore/cloud_firestore.dart';
1010

1111
import 'firebase_options.dart';
1212

@@ -25,7 +25,9 @@ Future<void> main() async {
2525
.activate(
2626
androidProvider: AndroidProvider.debug,
2727
appleProvider: AppleProvider.debug,
28-
webProvider: ReCaptchaV3Provider(kWebRecaptchaSiteKey),
28+
providerWeb: ReCaptchaV3Provider(kWebRecaptchaSiteKey),
29+
providerAndroid: const AndroidDebugProvider(debugToken: 'androidDebug'),
30+
providerApple: const AppleDebugProvider(debugToken: 'appleDebug'),
2931
);
3032

3133
runApp(MyApp());
@@ -115,7 +117,7 @@ class _FirebaseAppCheck extends State<FirebaseAppCheckExample> {
115117
);
116118
}
117119
await appCheck.activate(
118-
webProvider: ReCaptchaV3Provider(kWebRecaptchaSiteKey),
120+
providerWeb: ReCaptchaV3Provider(kWebRecaptchaSiteKey),
119121
);
120122
setMessage('activated!!');
121123
},

packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProvider.m

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,18 @@ - (id)initWithApp:app {
1414
return self;
1515
}
1616

17-
- (void)configure:(FIRApp *)app providerName:(NSString *)providerName {
17+
- (void)configure:(FIRApp *)app
18+
providerName:(NSString *)providerName
19+
debugToken:(NSString *)debugToken {
1820
if ([providerName isEqualToString:@"debug"]) {
21+
if (debugToken != nil) {
22+
// We have a debug token, so just need to stuff it in the environment and it will hook up
23+
char *key = "FIRAAppCheckDebugToken", *value = (char *)[debugToken UTF8String];
24+
int overwrite = 1;
25+
setenv(key, value, overwrite);
26+
}
1927
FIRAppCheckDebugProvider *provider = [[FIRAppCheckDebugProvider alloc] initWithApp:app];
20-
NSLog(@"Firebase App Check Debug Token: %@", [provider localDebugToken]);
28+
if (debugToken == nil) NSLog(@"Firebase App Check Debug Token: %@", [provider localDebugToken]);
2129
self.delegateProvider = provider;
2230
}
2331

packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProviderFactory.m

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,15 @@ @implementation FLTAppCheckProviderFactory
2525
self.providers[app.name] = [FLTAppCheckProvider new];
2626
FLTAppCheckProvider *provider = self.providers[app.name];
2727
// We set "deviceCheck" as this is currently what is default. Backward compatible.
28-
[provider configure:app providerName:@"deviceCheck"];
28+
[provider configure:app providerName:@"deviceCheck" debugToken:nil];
2929
}
3030

3131
return self.providers[app.name];
3232
}
3333

34-
- (void)configure:(FIRApp *)app providerName:(NSString *)providerName {
34+
- (void)configure:(FIRApp *)app
35+
providerName:(NSString *)providerName
36+
debugToken:(NSString *)debugToken {
3537
if (self.providers == nil) {
3638
self.providers = [NSMutableDictionary new];
3739
}
@@ -41,7 +43,7 @@ - (void)configure:(FIRApp *)app providerName:(NSString *)providerName {
4143
}
4244

4345
FLTAppCheckProvider *provider = self.providers[app.name];
44-
[provider configure:app providerName:providerName];
46+
[provider configure:app providerName:providerName debugToken:debugToken];
4547
}
4648

4749
@end

packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTFirebaseAppCheckPlugin.m

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,10 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)flutter
123123
- (void)activate:(id)arguments withMethodCallResult:(FLTFirebaseMethodCallResult *)result {
124124
NSString *appNameDart = arguments[@"appName"];
125125
NSString *providerName = arguments[@"appleProvider"];
126+
NSString *debugToken = arguments[@"appleDebugToken"];
126127

127128
FIRApp *app = [FLTFirebasePlugin firebaseAppNamed:appNameDart];
128-
[self->providerFactory configure:app providerName:providerName];
129+
[self->providerFactory configure:app providerName:providerName debugToken:debugToken];
129130
result.success(nil);
130131
}
131132

packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/include/FLTAppCheckProvider.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010

1111
@property id<FIRAppCheckProvider> delegateProvider;
1212

13-
- (void)configure:(FIRApp *)app providerName:(NSString *)providerName;
13+
- (void)configure:(FIRApp *)app
14+
providerName:(NSString *)providerName
15+
debugToken:(NSString *)debugToken;
1416

1517
- (id)initWithApp:(FIRApp *)app;
1618

packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/include/FLTAppCheckProviderFactory.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
@property NSMutableDictionary *_Nullable providers;
99

10-
- (void)configure:(FIRApp *_Nonnull)app providerName:(NSString *_Nonnull)providerName;
10+
- (void)configure:(FIRApp *_Nonnull)app
11+
providerName:(NSString *_Nonnull)providerName
12+
debugToken:(NSString *_Nullable)debugToken;
1113

1214
@end

0 commit comments

Comments
 (0)