@react-native-firebase/app-check 26.4.0 → 27.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/RNFBAppCheck.podspec +8 -2
  3. package/android/build.gradle +3 -0
  4. package/android/src/main/java/io/invertase/firebase/appcheck/RNFBAppCheckListenerRegistry.kt +72 -0
  5. package/dist/module/index.js +1 -2
  6. package/dist/module/index.js.map +1 -1
  7. package/dist/module/version.js +1 -1
  8. package/dist/typescript/lib/index.d.ts +1 -1
  9. package/dist/typescript/lib/index.d.ts.map +1 -1
  10. package/dist/typescript/lib/version.d.ts +1 -1
  11. package/ios/RNFBAppCheck/RNFBAppCheckHelper.h +61 -0
  12. package/ios/RNFBAppCheck/RNFBAppCheckHelper.m +213 -0
  13. package/ios/RNFBAppCheck/RNFBAppCheckModule.mm +22 -155
  14. package/ios/RNFBAppCheck/RNFBAppCheckRejectCodeMapper.swift +50 -0
  15. package/ios/RNFBAppCheck.xcodeproj/project.pbxproj +14 -0
  16. package/ios/RNFBAppCheckUnitTests/HostStubs/Firebase/FIRAppCheckHostStub.m +109 -0
  17. package/ios/RNFBAppCheckUnitTests/HostStubs/Firebase/Firebase.h +47 -0
  18. package/ios/RNFBAppCheckUnitTests/HostStubs/RNFBApp/RCTConvert+FIRApp.h +13 -0
  19. package/ios/RNFBAppCheckUnitTests/HostStubs/RNFBApp/RCTConvert+FIRAppHostStub.m +27 -0
  20. package/ios/RNFBAppCheckUnitTests/HostStubs/RNFBApp/RNFBSharedUtils.h +18 -0
  21. package/ios/RNFBAppCheckUnitTests/HostStubs/RNFBApp/RNFBSharedUtilsHostStub.m +18 -0
  22. package/ios/RNFBAppCheckUnitTests/HostStubs/RNFBAppCheck/RNFBAppCheckProviderHostStub.m +48 -0
  23. package/ios/RNFBAppCheckUnitTests/HostStubs/React/RCTBridgeModule.h +10 -0
  24. package/ios/RNFBAppCheckUnitTests/RNFBAppCheckHelperHostStubTests.m +197 -0
  25. package/ios/RNFBAppCheckUnitTests/RNFBAppCheckRejectCodeMapperTests.swift +85 -0
  26. package/ios/RNFBAppCheckUnitTests/RNFBAppCheckUnitTests.xcodeproj/project.pbxproj +277 -0
  27. package/ios/RNFBAppCheckUnitTests/RNFBAppCheckUnitTests.xcodeproj/xcshareddata/xcschemes/RNFBAppCheckUnitTests.xcscheme +69 -0
  28. package/lib/index.ts +1 -1
  29. package/lib/version.ts +1 -1
  30. package/package.json +4 -4
  31. package/plugin/build/ios/appDelegate.js +12 -13
  32. package/plugin/src/ios/appDelegate.ts +13 -14
  33. package/android/src/main/java/io/invertase/firebase/appcheck/RNFBAppCheckListenerRegistry.java +0 -76
@@ -15,29 +15,18 @@
15
15
  *
16
16
  */
17
17
 
18
- #if __has_include(<Firebase/Firebase.h>)
19
- #import <Firebase/Firebase.h>
20
- #elif __has_include(<FirebaseAppCheck/FirebaseAppCheck.h>)
21
- #import <FirebaseAppCheck/FirebaseAppCheck.h>
22
- #import <FirebaseCore/FirebaseCore.h>
23
- #else
24
- @import FirebaseCore;
25
- @import FirebaseAppCheck;
26
- #endif
27
-
18
+ // This module intentionally has no Firebase imports -- see RNFBAppCheckHelper.h /
19
+ // RNFBAppCheckModule.h for why. Every Firebase App Check SDK call is routed through
20
+ // the plain Objective-C RNFBAppCheckHelper class instead, which can safely
21
+ // `@import FirebaseAppCheck` (and import RNFBAppCheck-Swift.h for the reject-code
22
+ // mapper) because it compiles as ObjC, not ObjC++.
28
23
  #import <React/RCTInvalidating.h>
29
- #import <React/RCTUtils.h>
30
24
 
31
- #import "RNFBApp/RCTConvert+FIRApp.h"
32
- #import "RNFBApp/RNFBSharedUtils.h"
25
+ #import "RNFBAppCheckHelper.h"
33
26
  #import "RNFBAppCheckModule.h"
34
- #import "RNFBAppCheckProviderFactory.h"
35
27
  #import "RNFBAppCheckTurboModules.h"
36
28
 
37
29
  @interface RNFBAppCheckModule () <NativeRNFBTurboAppCheckSpec, RCTInvalidating>
38
-
39
- @property RNFBAppCheckProviderFactory *_Nullable providerFactory;
40
-
41
30
  @end
42
31
 
43
32
  @implementation RNFBAppCheckModule
@@ -58,8 +47,7 @@ RCT_EXPORT_MODULE(NativeRNFBTurboAppCheck)
58
47
  __strong static RNFBAppCheckModule *sharedInstance;
59
48
  dispatch_once(&once, ^{
60
49
  sharedInstance = [[RNFBAppCheckModule alloc] init];
61
- sharedInstance.providerFactory = [[RNFBAppCheckProviderFactory alloc] init];
62
- [FIRAppCheck setAppCheckProviderFactory:sharedInstance.providerFactory];
50
+ [RNFBAppCheckHelper ensureProviderFactoryInstalled];
63
51
  });
64
52
  return sharedInstance;
65
53
  }
@@ -72,16 +60,11 @@ RCT_EXPORT_MODULE(NativeRNFBTurboAppCheck)
72
60
  isTokenAutoRefreshEnabled:(BOOL)isTokenAutoRefreshEnabled
73
61
  resolve:(RCTPromiseResolveBlock)resolve
74
62
  reject:(RCTPromiseRejectBlock)reject {
75
- FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
76
- DLog(@"deprecated API, provider will be deviceCheck / token refresh %d for app %@",
77
- isTokenAutoRefreshEnabled, firebaseApp.name);
78
- [[RNFBAppCheckModule sharedInstance].providerFactory configure:firebaseApp
79
- providerName:@"deviceCheck"
80
- debugToken:nil];
81
-
82
- FIRAppCheck *appCheck = [FIRAppCheck appCheckWithApp:firebaseApp];
83
- appCheck.isTokenAutoRefreshEnabled = isTokenAutoRefreshEnabled;
84
- resolve([NSNull null]);
63
+ [RNFBAppCheckHelper activate:appName
64
+ siteKeyProvider:siteKeyProvider
65
+ isTokenAutoRefreshEnabled:isTokenAutoRefreshEnabled
66
+ resolve:resolve
67
+ reject:reject];
85
68
  }
86
69
 
87
70
  - (void)configureProvider:(NSString *)appName
@@ -89,152 +72,36 @@ RCT_EXPORT_MODULE(NativeRNFBTurboAppCheck)
89
72
  debugToken:(NSString *)debugToken
90
73
  resolve:(RCTPromiseResolveBlock)resolve
91
74
  reject:(RCTPromiseRejectBlock)reject {
92
- FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
93
- DLog(@"appName/providerName/debugToken: %@/%@/%@", firebaseApp.name, providerName,
94
- (debugToken == nil ? @"null" : @"(not shown)"));
95
- @try {
96
- [[RNFBAppCheckModule sharedInstance].providerFactory configure:firebaseApp
97
- providerName:providerName
98
- debugToken:debugToken];
99
- resolve([NSNull null]);
100
- } @catch (NSException *exception) {
101
- [RNFBSharedUtils rejectPromiseWithUserInfo:reject
102
- userInfo:(NSMutableDictionary *)@{
103
- @"code" : @"unknown",
104
- @"message" : exception.reason ?: @"internal-error",
105
- }];
106
- }
75
+ [RNFBAppCheckHelper configureProvider:appName
76
+ providerName:providerName
77
+ debugToken:debugToken
78
+ resolve:resolve
79
+ reject:reject];
107
80
  }
108
81
 
109
82
  - (void)setTokenAutoRefreshEnabled:(NSString *)appName
110
83
  isTokenAutoRefreshEnabled:(BOOL)isTokenAutoRefreshEnabled {
111
- FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
112
- DLog(@"app/isTokenAutoRefreshEnabled: %@/%d", firebaseApp.name, isTokenAutoRefreshEnabled);
113
- FIRAppCheck *appCheck = [FIRAppCheck appCheckWithApp:firebaseApp];
114
- appCheck.isTokenAutoRefreshEnabled = isTokenAutoRefreshEnabled;
84
+ [RNFBAppCheckHelper setTokenAutoRefreshEnabled:appName
85
+ isTokenAutoRefreshEnabled:isTokenAutoRefreshEnabled];
115
86
  }
116
87
 
117
88
  - (void)isTokenAutoRefreshEnabled:(NSString *)appName
118
89
  resolve:(RCTPromiseResolveBlock)resolve
119
90
  reject:(RCTPromiseRejectBlock)reject {
120
- FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
121
- FIRAppCheck *appCheck = [FIRAppCheck appCheckWithApp:firebaseApp];
122
- BOOL isTokenAutoRefreshEnabled = appCheck.isTokenAutoRefreshEnabled;
123
- DLog(@"app/isTokenAutoRefreshEnabled: %@/%d", firebaseApp.name, isTokenAutoRefreshEnabled);
124
- resolve([NSNumber numberWithBool:isTokenAutoRefreshEnabled]);
125
- }
126
-
127
- // AppCheck-AD-8: map pending fail-closed to provider-not-ready (not token-error).
128
- // Walk NSUnderlyingErrorKey because FIRAppCheck wraps non-SDK errors via
129
- // publicDomainErrorWithError: and drops top-level userInfo[@"code"].
130
- // Locked message: kRNFBAppCheckProviderNotReadyMessage (RNFBAppCheckProvider.h).
131
- static NSString *RNFBAppCheckRejectCodeForError(NSError *error) {
132
- NSError *current = error;
133
- while (current != nil) {
134
- id code = current.userInfo[@"code"];
135
- if ([code isKindOfClass:[NSString class]] && [code isEqualToString:@"provider-not-ready"]) {
136
- return @"provider-not-ready";
137
- }
138
- current = current.userInfo[NSUnderlyingErrorKey];
139
- if (![current isKindOfClass:[NSError class]]) {
140
- break;
141
- }
142
- }
143
- return @"token-error";
144
- }
145
-
146
- // AppCheck-AD-8 durable path: reject before FIRAppCheck token APIs when the
147
- // factory-held facade still has a nil delegateProvider (pending / not configured).
148
- static BOOL RNFBAppCheckRejectIfProviderNotReady(FIRApp *firebaseApp,
149
- RCTPromiseRejectBlock reject) {
150
- RNFBAppCheckProviderFactory *factory = [RNFBAppCheckModule sharedInstance].providerFactory;
151
- RNFBAppCheckProvider *provider = [factory providerForApp:firebaseApp];
152
- if (provider != nil && provider.delegateProvider != nil) {
153
- return NO;
154
- }
155
- DLog(@"RNFBAppCheck - provider not ready for app %@ (delegateProvider nil)", firebaseApp.name);
156
- [RNFBSharedUtils rejectPromiseWithUserInfo:reject
157
- userInfo:(NSMutableDictionary *)@{
158
- @"code" : @"provider-not-ready",
159
- @"message" : kRNFBAppCheckProviderNotReadyMessage,
160
- }];
161
- return YES;
91
+ [RNFBAppCheckHelper isTokenAutoRefreshEnabled:appName resolve:resolve reject:reject];
162
92
  }
163
93
 
164
94
  - (void)getToken:(NSString *)appName
165
95
  forceRefresh:(BOOL)forceRefresh
166
96
  resolve:(RCTPromiseResolveBlock)resolve
167
97
  reject:(RCTPromiseRejectBlock)reject {
168
- FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
169
- DLog(@"appName %@", firebaseApp.name);
170
- if (RNFBAppCheckRejectIfProviderNotReady(firebaseApp, reject)) {
171
- return;
172
- }
173
- FIRAppCheck *appCheck = [FIRAppCheck appCheckWithApp:firebaseApp];
174
- [appCheck
175
- tokenForcingRefresh:forceRefresh
176
- completion:^(FIRAppCheckToken *_Nullable token, NSError *_Nullable error) {
177
- if (error != nil) {
178
- DLog(@"RNFBAppCheck - getToken - Unable to retrieve App Check token: %@", error);
179
- NSString *code = RNFBAppCheckRejectCodeForError(error);
180
- [RNFBSharedUtils rejectPromiseWithUserInfo:reject
181
- userInfo:(NSMutableDictionary *)@{
182
- @"code" : code,
183
- @"message" : [error localizedDescription],
184
- }];
185
- return;
186
- }
187
- if (token == nil) {
188
- DLog(@"RNFBAppCheck - getToken - Unable to retrieve App Check token.");
189
- [RNFBSharedUtils rejectPromiseWithUserInfo:reject
190
- userInfo:(NSMutableDictionary *)@{
191
- @"code" : @"token-null",
192
- @"message" : @"no token fetched",
193
- }];
194
- return;
195
- }
196
-
197
- NSMutableDictionary *tokenResultDictionary = [NSMutableDictionary new];
198
- tokenResultDictionary[@"token"] = token.token;
199
- resolve(tokenResultDictionary);
200
- }];
98
+ [RNFBAppCheckHelper getToken:appName forceRefresh:forceRefresh resolve:resolve reject:reject];
201
99
  }
202
100
 
203
101
  - (void)getLimitedUseToken:(NSString *)appName
204
102
  resolve:(RCTPromiseResolveBlock)resolve
205
103
  reject:(RCTPromiseRejectBlock)reject {
206
- FIRApp *firebaseApp = [RCTConvert firAppFromString:appName];
207
- DLog(@"appName %@", firebaseApp.name);
208
- if (RNFBAppCheckRejectIfProviderNotReady(firebaseApp, reject)) {
209
- return;
210
- }
211
- FIRAppCheck *appCheck = [FIRAppCheck appCheckWithApp:firebaseApp];
212
- [appCheck limitedUseTokenWithCompletion:^(FIRAppCheckToken *_Nullable token,
213
- NSError *_Nullable error) {
214
- if (error != nil) {
215
- DLog(@"RNFBAppCheck - getLimitedUseToken - Unable to retrieve App Check token: %@", error);
216
- NSString *code = RNFBAppCheckRejectCodeForError(error);
217
- [RNFBSharedUtils rejectPromiseWithUserInfo:reject
218
- userInfo:(NSMutableDictionary *)@{
219
- @"code" : code,
220
- @"message" : [error localizedDescription],
221
- }];
222
- return;
223
- }
224
- if (token == nil) {
225
- DLog(@"RNFBAppCheck - getLimitedUseToken - Unable to retrieve App Check token.");
226
- [RNFBSharedUtils rejectPromiseWithUserInfo:reject
227
- userInfo:(NSMutableDictionary *)@{
228
- @"code" : @"token-null",
229
- @"message" : @"no token fetched",
230
- }];
231
- return;
232
- }
233
-
234
- NSMutableDictionary *tokenResultDictionary = [NSMutableDictionary new];
235
- tokenResultDictionary[@"token"] = token.token;
236
- resolve(tokenResultDictionary);
237
- }];
104
+ [RNFBAppCheckHelper getLimitedUseToken:appName resolve:resolve reject:reject];
238
105
  }
239
106
 
240
107
  - (void)addAppCheckListener:(NSString *)appName {
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Copyright (c) 2016-present Invertase Limited & Contributors
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this library except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import Foundation
18
+
19
+ /**
20
+ * Maps token-fetch `NSError` chains to JS reject codes previously assembled
21
+ * inline in `RNFBAppCheckModule.mm` (`RNFBAppCheckRejectCodeForError`).
22
+ *
23
+ * AppCheck-AD-8 contracts:
24
+ * - Walk `userInfo[@"code"]` and `NSUnderlyingErrorKey` (FIRAppCheck wraps
25
+ * non-SDK errors and may drop the top-level code)
26
+ * - Return `provider-not-ready` if any level has that string code
27
+ * - Else return `token-error`
28
+ *
29
+ * Foundation-only so unit tests do not link Firebase App Check.
30
+ */
31
+ @objc(RNFBAppCheckRejectCodeMapper)
32
+ public final class RNFBAppCheckRejectCodeMapper: NSObject {
33
+ /// Pre-port `RNFBAppCheckRejectCodeForError`.
34
+ @objc(rejectCodeForError:)
35
+ public static func rejectCode(for error: NSError?) -> NSString {
36
+ var current: NSError? = error
37
+ while let err = current {
38
+ if let code = err.userInfo["code"] as? String, code == "provider-not-ready" {
39
+ return "provider-not-ready" as NSString
40
+ }
41
+ let underlying = err.userInfo[NSUnderlyingErrorKey]
42
+ if let next = underlying as? NSError {
43
+ current = next
44
+ } else {
45
+ break
46
+ }
47
+ }
48
+ return "token-error" as NSString
49
+ }
50
+ }
@@ -8,6 +8,8 @@
8
8
 
9
9
  /* Begin PBXBuildFile section */
10
10
  2744B98621F45429004F8E3F /* RNFBAppCheckModule.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2744B98521F45429004F8E3F /* RNFBAppCheckModule.mm */; };
11
+ RNFBAC000000000000000001 /* RNFBAppCheckRejectCodeMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = RNFBAC000000000000000002 /* RNFBAppCheckRejectCodeMapper.swift */; };
12
+ RNFBAC000000000000000003 /* RNFBAppCheckHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = RNFBAC000000000000000005 /* RNFBAppCheckHelper.m */; };
11
13
  /* End PBXBuildFile section */
12
14
 
13
15
  /* Begin PBXCopyFilesBuildPhase section */
@@ -26,6 +28,9 @@
26
28
  2744B98221F45429004F8E3F /* libRNFBAppCheck.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNFBAppCheck.a; sourceTree = BUILT_PRODUCTS_DIR; };
27
29
  2744B98421F45429004F8E3F /* RNFBAppCheckModule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RNFBAppCheckModule.h; path = RNFBAppCheck/RNFBAppCheckModule.h; sourceTree = SOURCE_ROOT; };
28
30
  2744B98521F45429004F8E3F /* RNFBAppCheckModule.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = RNFBAppCheckModule.mm; path = RNFBAppCheck/RNFBAppCheckModule.mm; sourceTree = SOURCE_ROOT; };
31
+ RNFBAC000000000000000002 /* RNFBAppCheckRejectCodeMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = RNFBAppCheckRejectCodeMapper.swift; path = RNFBAppCheck/RNFBAppCheckRejectCodeMapper.swift; sourceTree = SOURCE_ROOT; };
32
+ RNFBAC000000000000000004 /* RNFBAppCheckHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RNFBAppCheckHelper.h; path = RNFBAppCheck/RNFBAppCheckHelper.h; sourceTree = SOURCE_ROOT; };
33
+ RNFBAC000000000000000005 /* RNFBAppCheckHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = RNFBAppCheckHelper.m; path = RNFBAppCheck/RNFBAppCheckHelper.m; sourceTree = SOURCE_ROOT; };
29
34
  /* End PBXFileReference section */
30
35
 
31
36
  /* Begin PBXFrameworksBuildPhase section */
@@ -54,6 +59,9 @@
54
59
  2744B98C21F45C64004F8E3F /* common */,
55
60
  2744B98421F45429004F8E3F /* RNFBAppCheckModule.h */,
56
61
  2744B98521F45429004F8E3F /* RNFBAppCheckModule.mm */,
62
+ RNFBAC000000000000000004 /* RNFBAppCheckHelper.h */,
63
+ RNFBAC000000000000000005 /* RNFBAppCheckHelper.m */,
64
+ RNFBAC000000000000000002 /* RNFBAppCheckRejectCodeMapper.swift */,
57
65
  );
58
66
  path = RNFBAppCheck;
59
67
  sourceTree = "<group>";
@@ -125,6 +133,8 @@
125
133
  buildActionMask = 2147483647;
126
134
  files = (
127
135
  2744B98621F45429004F8E3F /* RNFBAppCheckModule.mm in Sources */,
136
+ RNFBAC000000000000000003 /* RNFBAppCheckHelper.m in Sources */,
137
+ RNFBAC000000000000000001 /* RNFBAppCheckRejectCodeMapper.swift in Sources */,
128
138
  );
129
139
  runOnlyForDeploymentPostprocessing = 0;
130
140
  };
@@ -150,6 +160,7 @@
150
160
  CODE_SIGN_STYLE = Automatic;
151
161
  COPY_PHASE_STRIP = NO;
152
162
  DEBUG_INFORMATION_FORMAT = dwarf;
163
+ DEFINES_MODULE = YES;
153
164
  GCC_C_LANGUAGE_STANDARD = gnu11;
154
165
  GCC_DYNAMIC_NO_PIC = NO;
155
166
  GCC_OPTIMIZATION_LEVEL = 0;
@@ -166,6 +177,7 @@
166
177
  PRODUCT_NAME = "$(TARGET_NAME)";
167
178
  SDKROOT = iphoneos;
168
179
  SKIP_INSTALL = YES;
180
+ SWIFT_VERSION = 5.10;
169
181
  TARGETED_DEVICE_FAMILY = "1,2";
170
182
  };
171
183
  name = Debug;
@@ -189,6 +201,7 @@
189
201
  CODE_SIGN_STYLE = Automatic;
190
202
  COPY_PHASE_STRIP = NO;
191
203
  DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
204
+ DEFINES_MODULE = YES;
192
205
  ENABLE_NS_ASSERTIONS = NO;
193
206
  GCC_C_LANGUAGE_STANDARD = gnu11;
194
207
  GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
@@ -200,6 +213,7 @@
200
213
  PRODUCT_NAME = "$(TARGET_NAME)";
201
214
  SDKROOT = iphoneos;
202
215
  SKIP_INSTALL = YES;
216
+ SWIFT_VERSION = 5.10;
203
217
  TARGETED_DEVICE_FAMILY = "1,2";
204
218
  VALIDATE_PRODUCT = YES;
205
219
  };
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Host-only stub for macOS XCTest. Not shipped in the production pod.
3
+ */
4
+ #import <Firebase/Firebase.h>
5
+
6
+ @implementation FIRApp
7
+
8
+ - (instancetype)initWithName:(NSString *)name {
9
+ self = [super init];
10
+ if (self) {
11
+ _name = [name copy];
12
+ }
13
+ return self;
14
+ }
15
+
16
+ @end
17
+
18
+ @implementation FIRAppCheckToken {
19
+ NSString *_token;
20
+ }
21
+
22
+ - (instancetype)initWithToken:(NSString *)token {
23
+ self = [super init];
24
+ if (self) {
25
+ _token = [token copy];
26
+ }
27
+ return self;
28
+ }
29
+
30
+ - (NSString *)token {
31
+ return _token;
32
+ }
33
+
34
+ @end
35
+
36
+ @implementation FIRAppCheck
37
+
38
+ static id<FIRAppCheckProviderFactory> sFactory;
39
+ static void (^sTokenForcingRefreshHandler)(BOOL, FIRAppCheckTokenCompletionBlock);
40
+ static void (^sLimitedUseTokenHandler)(FIRAppCheckTokenCompletionBlock);
41
+ static NSMutableDictionary<NSString *, FIRAppCheck *> *sInstances;
42
+
43
+ + (void)initialize {
44
+ if (self == [FIRAppCheck class]) {
45
+ sInstances = [NSMutableDictionary new];
46
+ }
47
+ }
48
+
49
+ + (void)setAppCheckProviderFactory:(id<FIRAppCheckProviderFactory>)factory {
50
+ sFactory = factory;
51
+ }
52
+
53
+ + (void (^)(BOOL, FIRAppCheckTokenCompletionBlock))tokenForcingRefreshHandler {
54
+ return sTokenForcingRefreshHandler;
55
+ }
56
+
57
+ + (void)setTokenForcingRefreshHandler:
58
+ (void (^)(BOOL, FIRAppCheckTokenCompletionBlock))tokenForcingRefreshHandler {
59
+ sTokenForcingRefreshHandler = [tokenForcingRefreshHandler copy];
60
+ }
61
+
62
+ + (void (^)(FIRAppCheckTokenCompletionBlock))limitedUseTokenHandler {
63
+ return sLimitedUseTokenHandler;
64
+ }
65
+
66
+ + (void)setLimitedUseTokenHandler:
67
+ (void (^)(FIRAppCheckTokenCompletionBlock))limitedUseTokenHandler {
68
+ sLimitedUseTokenHandler = [limitedUseTokenHandler copy];
69
+ }
70
+
71
+ + (void)resetTestState {
72
+ sTokenForcingRefreshHandler = nil;
73
+ sLimitedUseTokenHandler = nil;
74
+ [sInstances removeAllObjects];
75
+ }
76
+
77
+ + (instancetype)appCheckWithApp:(FIRApp *)app {
78
+ NSString *key = app.name ?: @"__nil__";
79
+ FIRAppCheck *existing = sInstances[key];
80
+ if (existing != nil) {
81
+ return existing;
82
+ }
83
+ FIRAppCheck *created = [[FIRAppCheck alloc] init];
84
+ sInstances[key] = created;
85
+ return created;
86
+ }
87
+
88
+ - (void)tokenForcingRefresh:(BOOL)forceRefresh
89
+ completion:(FIRAppCheckTokenCompletionBlock)completion {
90
+ if (sTokenForcingRefreshHandler != nil) {
91
+ sTokenForcingRefreshHandler(forceRefresh, completion);
92
+ return;
93
+ }
94
+ if (completion != nil) {
95
+ completion(nil, nil);
96
+ }
97
+ }
98
+
99
+ - (void)limitedUseTokenWithCompletion:(FIRAppCheckTokenCompletionBlock)completion {
100
+ if (sLimitedUseTokenHandler != nil) {
101
+ sLimitedUseTokenHandler(completion);
102
+ return;
103
+ }
104
+ if (completion != nil) {
105
+ completion(nil, nil);
106
+ }
107
+ }
108
+
109
+ @end
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Host-only stub for macOS XCTest. Not shipped in the production pod.
3
+ * Enough of Firebase Core / App Check for compiling RNFBAppCheckHelper.m
4
+ * and driving token completion branches without linking the SDK.
5
+ */
6
+ #import <Foundation/Foundation.h>
7
+
8
+ @interface FIRApp : NSObject
9
+ @property(nonatomic, copy) NSString *name;
10
+ - (instancetype)initWithName:(NSString *)name;
11
+ @end
12
+
13
+ @interface FIRAppCheckToken : NSObject
14
+ @property(nonatomic, readonly, copy) NSString *token;
15
+ - (instancetype)initWithToken:(NSString *)token;
16
+ @end
17
+
18
+ @protocol FIRAppCheckProvider <NSObject>
19
+ @end
20
+
21
+ @protocol FIRAppCheckProviderFactory <NSObject>
22
+ - (nullable id<FIRAppCheckProvider>)createProviderWithApp:(FIRApp *)app;
23
+ @end
24
+
25
+ typedef void (^FIRAppCheckTokenCompletionBlock)(FIRAppCheckToken *_Nullable token,
26
+ NSError *_Nullable error);
27
+
28
+ @interface FIRAppCheck : NSObject
29
+
30
+ @property(nonatomic, assign) BOOL isTokenAutoRefreshEnabled;
31
+
32
+ + (void)setAppCheckProviderFactory:(nullable id<FIRAppCheckProviderFactory>)factory;
33
+ + (instancetype)appCheckWithApp:(FIRApp *)app;
34
+
35
+ - (void)tokenForcingRefresh:(BOOL)forceRefresh
36
+ completion:(FIRAppCheckTokenCompletionBlock)completion;
37
+ - (void)limitedUseTokenWithCompletion:(FIRAppCheckTokenCompletionBlock)completion;
38
+
39
+ /** Test seam: when set, invoked instead of a network/token fetch. */
40
+ @property(class, nonatomic, copy, nullable) void (^tokenForcingRefreshHandler)
41
+ (BOOL forceRefresh, FIRAppCheckTokenCompletionBlock completion);
42
+ @property(class, nonatomic, copy, nullable) void (^limitedUseTokenHandler)
43
+ (FIRAppCheckTokenCompletionBlock completion);
44
+
45
+ + (void)resetTestState;
46
+
47
+ @end
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Host-only stub for macOS XCTest. Not shipped in the production pod.
3
+ */
4
+ #import <Foundation/Foundation.h>
5
+
6
+ @class FIRApp;
7
+
8
+ @interface RCTConvert : NSObject
9
+ + (FIRApp *)firAppFromString:(NSString *)appName;
10
+ /** Test seam: map appName → FIRApp. Cleared via resetTestState. */
11
+ + (void)setFirAppFromStringHandler:(FIRApp * (^)(NSString *appName))handler;
12
+ + (void)resetTestState;
13
+ @end
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Host-only stub for macOS XCTest. Not shipped in the production pod.
3
+ */
4
+ #import "RNFBApp/RCTConvert+FIRApp.h"
5
+
6
+ #import <Firebase/Firebase.h>
7
+
8
+ @implementation RCTConvert
9
+
10
+ static FIRApp * (^sFirAppFromStringHandler)(NSString *appName);
11
+
12
+ + (FIRApp *)firAppFromString:(NSString *)appName {
13
+ if (sFirAppFromStringHandler != nil) {
14
+ return sFirAppFromStringHandler(appName);
15
+ }
16
+ return [[FIRApp alloc] initWithName:appName ?: @"[DEFAULT]"];
17
+ }
18
+
19
+ + (void)setFirAppFromStringHandler:(FIRApp * (^)(NSString *appName))handler {
20
+ sFirAppFromStringHandler = [handler copy];
21
+ }
22
+
23
+ + (void)resetTestState {
24
+ sFirAppFromStringHandler = nil;
25
+ }
26
+
27
+ @end
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Host-only stub for macOS XCTest. Not shipped in the production pod.
3
+ */
4
+ #import <Foundation/Foundation.h>
5
+ #import <React/RCTBridgeModule.h>
6
+
7
+ #ifdef DEBUG
8
+ #define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
9
+ #else
10
+ #define DLog(...)
11
+ #endif
12
+
13
+ @interface RNFBSharedUtils : NSObject
14
+
15
+ + (void)rejectPromiseWithUserInfo:(RCTPromiseRejectBlock)reject
16
+ userInfo:(NSMutableDictionary *)userInfo;
17
+
18
+ @end
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Host-only stub for macOS XCTest. Not shipped in the production pod.
3
+ */
4
+ #import "RNFBApp/RNFBSharedUtils.h"
5
+
6
+ @implementation RNFBSharedUtils
7
+
8
+ + (void)rejectPromiseWithUserInfo:(RCTPromiseRejectBlock)reject
9
+ userInfo:(NSMutableDictionary *)userInfo {
10
+ if (reject == nil) {
11
+ return;
12
+ }
13
+ NSString *code = userInfo[@"code"] ?: @"unknown";
14
+ NSString *message = userInfo[@"message"] ?: @"";
15
+ reject(code, message, nil);
16
+ }
17
+
18
+ @end
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Host-only stub for macOS XCTest. Not shipped in the production pod.
3
+ * Replaces production RNFBAppCheckProvider.m (DeviceCheck / App Attest / debug SDK).
4
+ */
5
+ #import "RNFBAppCheckProvider.h"
6
+
7
+ NSString *const kRNFBAppCheckProviderNotReadyMessage =
8
+ @"App Check provider is not ready. Call initializeAppCheck before requesting tokens.";
9
+
10
+ @interface RNFBAppCheckHostStubDelegateProvider : NSObject <FIRAppCheckProvider>
11
+ @end
12
+
13
+ @implementation RNFBAppCheckHostStubDelegateProvider
14
+ @end
15
+
16
+ @implementation RNFBAppCheckProvider
17
+
18
+ - (id)initWithApp:(FIRApp *)app {
19
+ self = [super init];
20
+ if (self) {
21
+ self.app = app;
22
+ }
23
+ return self;
24
+ }
25
+
26
+ - (void)configure:(FIRApp *)app
27
+ providerName:(NSString *)providerName
28
+ debugToken:(NSString *)debugToken {
29
+ (void)providerName;
30
+ (void)debugToken;
31
+ self.app = app;
32
+ // Mark ready so Helper RejectIfProviderNotReady allows token APIs.
33
+ self.delegateProvider = [[RNFBAppCheckHostStubDelegateProvider alloc] init];
34
+ }
35
+
36
+ - (void)getTokenWithCompletion:(nonnull void (^)(FIRAppCheckToken *_Nullable,
37
+ NSError *_Nullable))handler {
38
+ if (handler != nil) {
39
+ handler(nil, [NSError errorWithDomain:@"RNFBAppCheckHostStub"
40
+ code:0
41
+ userInfo:@{
42
+ @"code" : @"provider-not-ready",
43
+ NSLocalizedDescriptionKey : kRNFBAppCheckProviderNotReadyMessage,
44
+ }]);
45
+ }
46
+ }
47
+
48
+ @end
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Host-only stub for macOS XCTest. Not shipped in the production pod.
3
+ */
4
+ #import <Foundation/Foundation.h>
5
+
6
+ typedef void (^RCTPromiseResolveBlock)(id result);
7
+ typedef void (^RCTPromiseRejectBlock)(NSString *code, NSString *message, NSError *error);
8
+
9
+ @protocol RCTBridgeModule <NSObject>
10
+ @end