Skip to content

Commit 32a74ab

Browse files
Various updates to handle pinning updates more cleanly
1 parent 8aa25ec commit 32a74ab

File tree

3 files changed

+233
-165
lines changed

3 files changed

+233
-165
lines changed

android/src/main/java/com/criticalblue/approov_service_flutter_httpclient/ApproovHttpClientPlugin.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ public void approovCallback(Approov.TokenFetchResult tokenFetchResult) {
186186
resultMap.put("IsForceApplyPins", tokenFetchResult.isForceApplyPins());
187187
resultMap.put("MeasurementConfig", tokenFetchResult.getMeasurementConfig());
188188
resultMap.put("LoggableToken", tokenFetchResult.getLoggableToken());
189+
resultMap.put("ConfigEpoch", configEpoch);
189190
countDownLatch.countDown();
190191
if (handler != null)
191192
handler.post(() -> fgChannel.invokeMethod("response", resultMap));
@@ -227,6 +228,11 @@ Map<String, Object> getResult() {
227228
// Provides any prior initial comment supplied, or empty string if none was provided
228229
private String initializedComment;
229230

231+
// Counter for the configuration epoch that is incremented whenever the configuration is fetched. This keeps
232+
// track of dynamic configuration changes and the state is held in the platform layer as we want this to work
233+
// across multiple different isolates which have independent Dart level state.
234+
private int configEpoch = 0;
235+
230236
// Handler for the main thread to allow call backs since they must be in the context of that thread
231237
private Handler handler;
232238

@@ -295,10 +301,13 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
295301
}
296302
} else if (call.method.equals("fetchConfig")) {
297303
try {
304+
configEpoch++;
298305
result.success(Approov.fetchConfig());
299306
} catch(Exception e) {
300307
result.error("Approov.fetchConfig", e.getLocalizedMessage(), null);
301308
}
309+
} else if (call.method.equals("getConfigEpoch")) {
310+
result.success(configEpoch);
302311
} else if (call.method.equals("getDeviceID")) {
303312
try {
304313
result.success(Approov.getDeviceID());

ios/Classes/ApproovHttpClientPlugin.m

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -213,8 +213,9 @@ @interface InternalCallBackHandler: NSObject
213213
*
214214
* @param transactionID is the transaction ID to use for the fetch
215215
* @param channel is the FlutterMethodChannel to use any callback to Flutter or nil if not required
216+
* @param configEpoch is the configuration epoch that the fetch was made within
216217
*/
217-
- (nullable instancetype)initWithTransactionID:(NSString *)transactionID channel:(FlutterMethodChannel *)channel;
218+
- (nullable instancetype)initWithTransactionID:(NSString *)transactionID channel:(FlutterMethodChannel *)channel configEpoch:(int)configEpoch;
218219

219220
/**
220221
* Provides string mappings for the token fetch status with strings that are compatible with the common dart layer. This
@@ -245,6 +246,9 @@ - (NSDictionary *)getResult;
245246
// FlutterMethodChannel to use for any callback to Flutter or nil if no callback is needed
246247
@property FlutterMethodChannel *channel;
247248

249+
// configuration epoch that the fetch was made within
250+
@property int configEpoch;
251+
248252
// Dispatch group to indicate when the fetch is complete
249253
@property dispatch_group_t group;
250254

@@ -258,12 +262,13 @@ - (NSDictionary *)getResult;
258262
@implementation InternalCallBackHandler
259263

260264
// see interface for documentation
261-
- (nullable instancetype)initWithTransactionID:(NSString *)transactionID channel:(FlutterMethodChannel *)channel
265+
- (nullable instancetype)initWithTransactionID:(NSString *)transactionID channel:(FlutterMethodChannel *)channel configEpoch:(int)configEpoch
262266
{
263267
self = [super init];
264268
if (self) {
265269
_transactionID = transactionID;
266270
_channel = channel;
271+
_configEpoch = configEpoch;
267272
_group = dispatch_group_create();
268273
_results = [NSMutableDictionary dictionary];
269274
dispatch_group_enter(_group);
@@ -330,6 +335,7 @@ - (void)postWithTokenFetchResult:(ApproovTokenFetchResult *_Nonnull)tokenFetchRe
330335
_results[@"MeasurementConfig"] = tokenFetchResult.measurementConfig;
331336
if (tokenFetchResult.loggableToken != nil)
332337
_results[@"LoggableToken"] = tokenFetchResult.loggableToken;
338+
_results[@"ConfigEpoch"] = [NSNumber numberWithInt:_configEpoch];
333339

334340
// leave the dispatch group to indicate that the results are available
335341
dispatch_group_leave(_group);
@@ -367,6 +373,11 @@ @interface ApproovHttpClientPlugin()
367373
// Provides any prior initial comment supplied, or empty string if none was provided
368374
@property NSString *initializedComment;
369375

376+
// Counter for the configuration epoch that is incremented whenever the configuration is fetched. This keeps
377+
// track of dynamic configuration changes and the state is held in the platform layer as we want this to work
378+
// across multiple different isolates which have independent Dart level state.
379+
@property int configEpoch;
380+
370381
// Active set of callback handlers to the Approov SDK - accessess to this must be protected as it could be
371382
// accessed from multiple threads
372383
@property NSMutableDictionary<NSString*, InternalCallBackHandler*> *activeCallBackHandlers;
@@ -398,6 +409,7 @@ + (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
398409
[registrar addMethodCallDelegate:instance channel:fgChannel];
399410
instance.bgChannel = bgChannel;
400411
[registrar addMethodCallDelegate:instance channel:bgChannel];
412+
instance.configEpoch = 0;
401413
instance.activeCallBackHandlers = [NSMutableDictionary dictionary];
402414
instance.activeCertFetches = [NSMutableDictionary dictionary];
403415
}
@@ -445,7 +457,10 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result
445457
result(nil);
446458
}
447459
} else if ([@"fetchConfig" isEqualToString:call.method]) {
460+
_configEpoch++;
448461
result([Approov fetchConfig]);
462+
} else if ([@"getConfigEpoch" isEqualToString:call.method]) {
463+
result([NSNumber numberWithInt:_configEpoch]);
449464
} else if ([@"getDeviceID" isEqualToString:call.method]) {
450465
result([Approov getDeviceID]);
451466
} else if ([@"getPins" isEqualToString:call.method]) {
@@ -504,7 +519,7 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result
504519
NSString *transactionID = call.arguments[@"transactionID"];
505520
BOOL performCallBack = [call.arguments[@"performCallBack"] isEqualToString:@"YES"];
506521
InternalCallBackHandler *callBackHandler = [[InternalCallBackHandler alloc] initWithTransactionID:transactionID
507-
channel:(performCallBack ? _fgChannel : nil)];
522+
channel:(performCallBack ? _fgChannel : nil) configEpoch:_configEpoch];
508523
[Approov fetchApproovToken:^(ApproovTokenFetchResult *tokenFetchResult) {
509524
[callBackHandler postWithTokenFetchResult:tokenFetchResult];
510525
} :call.arguments[@"url"]];
@@ -521,7 +536,7 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result
521536
newDef = call.arguments[@"newDef"];
522537
BOOL performCallBack = [call.arguments[@"performCallBack"] isEqualToString:@"YES"];
523538
InternalCallBackHandler *callBackHandler = [[InternalCallBackHandler alloc] initWithTransactionID:transactionID
524-
channel:(performCallBack ? _fgChannel : nil)];
539+
channel:(performCallBack ? _fgChannel : nil) configEpoch:_configEpoch];
525540
[Approov fetchSecureString:^(ApproovTokenFetchResult *tokenFetchResult) {
526541
[callBackHandler postWithTokenFetchResult:tokenFetchResult];
527542
} :call.arguments[@"key"] :newDef];
@@ -535,7 +550,7 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result
535550
NSString *transactionID = call.arguments[@"transactionID"];
536551
BOOL performCallBack = [call.arguments[@"performCallBack"] isEqualToString:@"YES"];
537552
InternalCallBackHandler *callBackHandler = [[InternalCallBackHandler alloc] initWithTransactionID:transactionID
538-
channel:(performCallBack ? _fgChannel : nil)];
553+
channel:(performCallBack ? _fgChannel : nil) configEpoch:_configEpoch];
539554
[Approov fetchCustomJWT:^(ApproovTokenFetchResult *tokenFetchResult) {
540555
[callBackHandler postWithTokenFetchResult:tokenFetchResult];
541556
} :call.arguments[@"payload"]];

0 commit comments

Comments
 (0)