diff --git a/Example/Example.xcodeproj/project.pbxproj b/Example/Example.xcodeproj/project.pbxproj index 343ba9d80..1a3239cc0 100644 --- a/Example/Example.xcodeproj/project.pbxproj +++ b/Example/Example.xcodeproj/project.pbxproj @@ -340,7 +340,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 9PGY6B643R; + DEVELOPMENT_TEAM = 96GHH65B9D; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", @@ -368,7 +368,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 9PGY6B643R; + DEVELOPMENT_TEAM = 96GHH65B9D; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", diff --git a/RadarSDK.podspec b/RadarSDK.podspec index 78ec84e69..a55a0604f 100644 --- a/RadarSDK.podspec +++ b/RadarSDK.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'RadarSDK' - s.version = '3.8.4' + s.version = '3.8.5' s.summary = 'iOS SDK for Radar, the leading geofencing and location tracking platform' s.homepage = 'https://radar.com' s.author = { 'Radar Labs, Inc.' => 'support@radar.com' } diff --git a/RadarSDK.xcodeproj/project.pbxproj b/RadarSDK.xcodeproj/project.pbxproj index 3a2d4e2c1..38a8255f4 100644 --- a/RadarSDK.xcodeproj/project.pbxproj +++ b/RadarSDK.xcodeproj/project.pbxproj @@ -965,7 +965,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 10.0; - MARKETING_VERSION = 3.8.4; + MARKETING_VERSION = 3.8.5; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -1024,7 +1024,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 10.0; - MARKETING_VERSION = 3.8.4; + MARKETING_VERSION = 3.8.5; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; OTHER_CFLAGS = "-fembed-bitcode"; diff --git a/RadarSDK/Include/Radar.h b/RadarSDK/Include/Radar.h index db9f36f32..7bbb9bfa7 100644 --- a/RadarSDK/Include/Radar.h +++ b/RadarSDK/Include/Radar.h @@ -156,7 +156,7 @@ typedef NS_ENUM(NSInteger, RadarAddressVerificationStatus) { }; -#pragma mark - Callback typedefs +#pragma mark - Callbacks /** Called when a location request succeeds, fails, or times out. @@ -185,6 +185,15 @@ typedef void (^_Nullable RadarBeaconCompletionHandler)(RadarStatus status, NSArr */ typedef void (^_Nullable RadarTrackCompletionHandler)(RadarStatus status, CLLocation *_Nullable location, NSArray *_Nullable events, RadarUser *_Nullable user); +/** + Called when an track request with token callback succeeds, fails, or times out. + + Receives the request status and, if successful, a JSON Web Token (JWT) containing an array of the events generated and the user. Verify the JWT server-side using your secret key. + + @see https://radar.com/documentation/sdk/fraud + */ +typedef void (^_Nullable RadarTrackTokenCompletionHandler)(RadarStatus status, NSString *_Nullable token); + /** Called when a trip update succeeds, fails, or times out. @@ -441,6 +450,17 @@ typedef void (^_Nonnull RadarLogConversionCompletionHandler)(RadarStatus status, */ + (void)trackVerifiedWithCompletionHandler:(RadarTrackCompletionHandler _Nullable)completionHandler NS_SWIFT_NAME(trackVerified(completionHandler:)); +/** + Tracks the user's location with device integrity information for location verification use cases. Returns a JSON Web Token (JWT). Verify the JWT server-side using your secret key. + + @warning Note that you must configure SSL pinning before calling this method. + + @param completionHandler An optional completion handler. + + @see https://radar.com/documentation/fraud + */ ++ (void)trackVerifiedTokenWithCompletionHandler:(RadarTrackTokenCompletionHandler _Nullable)completionHandler NS_SWIFT_NAME(trackVerifiedToken(completionHandler:)); + /** Starts tracking the user's location in the background with configurable tracking options. diff --git a/RadarSDK/Radar.m b/RadarSDK/Radar.m index bcdd9ca02..06c9052fa 100644 --- a/RadarSDK/Radar.m +++ b/RadarSDK/Radar.m @@ -150,7 +150,7 @@ + (void)trackOnceWithDesiredAccuracy:(RadarTrackingOptionsDesiredAccuracy)desire replayed:NO beacons:beacons completionHandler:^(RadarStatus status, NSDictionary *_Nullable res, NSArray *_Nullable events, RadarUser *_Nullable user, - NSArray *_Nullable nearbyGeofences, RadarConfig *_Nullable config) { + NSArray *_Nullable nearbyGeofences, RadarConfig *_Nullable config, NSString *_Nullable token) { if (status == RadarStatusSuccess) { [[RadarLocationManager sharedInstance] replaceSyncedGeofences:nearbyGeofences]; } @@ -219,7 +219,7 @@ + (void)trackOnceWithLocation:(CLLocation *)location completionHandler:(RadarTra replayed:NO beacons:nil completionHandler:^(RadarStatus status, NSDictionary *_Nullable res, NSArray *_Nullable events, RadarUser *_Nullable user, - NSArray *_Nullable nearbyGeofences, RadarConfig *_Nullable config) { + NSArray *_Nullable nearbyGeofences, RadarConfig *_Nullable config, NSString *_Nullable token) { if (completionHandler) { [RadarUtils runOnMainThread:^{ @@ -260,9 +260,10 @@ + (void)trackVerifiedWithCompletionHandler:(RadarTrackCompletionHandler)completi attestationString:attestationString keyId:keyId attestationError:attestationError + encrypted:YES completionHandler:^(RadarStatus status, NSDictionary *_Nullable res, NSArray *_Nullable events, RadarUser *_Nullable user, NSArray *_Nullable nearbyGeofences, - RadarConfig *_Nullable config) { + RadarConfig *_Nullable config, NSString *_Nullable token) { if (completionHandler) { [RadarUtils runOnMainThread:^{ completionHandler(status, location, events, user); @@ -274,6 +275,52 @@ + (void)trackVerifiedWithCompletionHandler:(RadarTrackCompletionHandler)completi }]; } ++ (void)trackVerifiedTokenWithCompletionHandler:(RadarTrackTokenCompletionHandler)completionHandler { + [[RadarAPIClient sharedInstance] + getConfigForUsage:@"verify" verified:YES + completionHandler:^(RadarStatus status, RadarConfig *_Nullable config) { + [[RadarLocationManager sharedInstance] + getLocationWithDesiredAccuracy:RadarTrackingOptionsDesiredAccuracyHigh + completionHandler:^(RadarStatus status, CLLocation *_Nullable location, BOOL stopped) { + if (status != RadarStatusSuccess) { + if (completionHandler) { + [RadarUtils runOnMainThread:^{ + completionHandler(status, nil); + }]; + } + + return; + } + + [[RadarVerificationManager sharedInstance] + getAttestationWithNonce:config.nonce + completionHandler:^(NSString *_Nullable attestationString, NSString *_Nullable keyId, NSString *_Nullable attestationError) { + [[RadarAPIClient sharedInstance] + trackWithLocation:location + stopped:RadarState.stopped + foreground:[RadarUtils foreground] + source:RadarLocationSourceForegroundLocation + replayed:NO + beacons:nil + verified:YES + attestationString:attestationString + keyId:keyId + attestationError:attestationError + encrypted:YES + completionHandler:^(RadarStatus status, NSDictionary *_Nullable res, NSArray *_Nullable events, + RadarUser *_Nullable user, NSArray *_Nullable nearbyGeofences, + RadarConfig *_Nullable config, NSString *_Nullable token) { + if (completionHandler) { + [RadarUtils runOnMainThread:^{ + completionHandler(status, token); + }]; + } + }]; + }]; + }]; + }]; +} + + (void)startTrackingWithOptions:(RadarTrackingOptions *)options { [[RadarLogger sharedInstance] logWithLevel:RadarLogLevelInfo type:RadarLogTypeSDKCall message:@"startTracking()"]; [[RadarLocationManager sharedInstance] startTrackingWithOptions:options]; @@ -345,7 +392,7 @@ + (void)mockTrackingWithOrigin:(CLLocation *)origin replayed:NO beacons:nil completionHandler:^(RadarStatus status, NSDictionary *_Nullable res, NSArray *_Nullable events, RadarUser *_Nullable user, - NSArray *_Nullable nearbyGeofences, RadarConfig *_Nullable config) { + NSArray *_Nullable nearbyGeofences, RadarConfig *_Nullable config, NSString *_Nullable token) { if (completionHandler) { [RadarUtils runOnMainThread:^{ completionHandler(status, location, events, user); diff --git a/RadarSDK/RadarAPIClient.h b/RadarSDK/RadarAPIClient.h index a5ea19c72..e55681c99 100644 --- a/RadarSDK/RadarAPIClient.h +++ b/RadarSDK/RadarAPIClient.h @@ -27,7 +27,8 @@ typedef void (^_Nonnull RadarTrackAPICompletionHandler)(RadarStatus status, NSArray *_Nullable events, RadarUser *_Nullable user, NSArray *_Nullable nearbyGeofences, - RadarConfig *_Nullable config); + RadarConfig *_Nullable config, + NSString *_Nullable token); typedef void (^_Nonnull RadarTripAPICompletionHandler)(RadarStatus status, RadarTrip *_Nullable trip, NSArray *_Nullable events); @@ -86,6 +87,7 @@ typedef void (^_Nonnull RadarSyncLogsAPICompletionHandler)(RadarStatus status); attestationString:(NSString *_Nullable)attestationString keyId:(NSString *_Nullable)keyId attestationError:(NSString *_Nullable)attestationError + encrypted:(BOOL)encrypted completionHandler:(RadarTrackAPICompletionHandler _Nonnull)completionHandler; - (void)verifyEventId:(NSString *_Nonnull)eventId verification:(RadarEventVerification)verification verifiedPlaceId:(NSString *_Nullable)verifiedPlaceId; diff --git a/RadarSDK/RadarAPIClient.m b/RadarSDK/RadarAPIClient.m index e55c6b593..986f2f536 100644 --- a/RadarSDK/RadarAPIClient.m +++ b/RadarSDK/RadarAPIClient.m @@ -130,6 +130,7 @@ - (void)trackWithLocation:(CLLocation *_Nonnull)location attestationString:nil keyId:nil attestationError:nil + encrypted:NO completionHandler:completionHandler]; } @@ -143,10 +144,11 @@ - (void)trackWithLocation:(CLLocation *_Nonnull)location attestationString:(NSString *_Nullable)attestationString keyId:(NSString *_Nullable)keyId attestationError:(NSString *_Nullable)attestationError + encrypted:(BOOL)encrypted completionHandler:(RadarTrackAPICompletionHandler _Nonnull)completionHandler { NSString *publishableKey = [RadarSettings publishableKey]; if (!publishableKey) { - return completionHandler(RadarStatusErrorPublishableKey, nil, nil, nil, nil, nil); + return completionHandler(RadarStatusErrorPublishableKey, nil, nil, nil, nil, nil, nil); } NSMutableDictionary *params = [NSMutableDictionary new]; BOOL anonymous = [RadarSettings anonymousTrackingEnabled]; @@ -257,6 +259,7 @@ - (void)trackWithLocation:(CLLocation *_Nonnull)location params[@"attestationString"] = attestationString; params[@"keyId"] = keyId; params[@"attestationError"] = attestationError; + params[@"encrypted"] = @(encrypted); } params[@"appId"] = [[NSBundle mainBundle] bundleIdentifier]; @@ -314,7 +317,7 @@ - (void)trackWithLocation:(CLLocation *_Nonnull)location [[RadarDelegateHolder sharedInstance] didFailWithStatus:status]; - return completionHandler(status, nil, nil, nil, nil, nil); + return completionHandler(status, nil, nil, nil, nil, nil, nil); } [[RadarReplayBuffer sharedInstance] clearBuffer]; @@ -327,10 +330,21 @@ - (void)trackWithLocation:(CLLocation *_Nonnull)location id eventsObj = res[@"events"]; id userObj = res[@"user"]; id nearbyGeofencesObj = res[@"nearbyGeofences"]; + id tokenObj = res[@"token"]; NSArray *events = [RadarEvent eventsFromObject:eventsObj]; RadarUser *user = [[RadarUser alloc] initWithObject:userObj]; NSArray *nearbyGeofences = [RadarGeofence geofencesFromObject:nearbyGeofencesObj]; + if (encrypted) { + if (!tokenObj) { + return completionHandler(status, nil, nil, nil, nil, nil, nil); + } + + NSString *token = (NSString *)tokenObj; + + return completionHandler(status, nil, nil, nil, nil, nil, token); + } + if (user) { BOOL inGeofences = user.geofences && user.geofences.count; BOOL atPlace = user.place != nil; @@ -394,12 +408,12 @@ - (void)trackWithLocation:(CLLocation *_Nonnull)location [[RadarDelegateHolder sharedInstance] didReceiveEvents:events user:user]; } - return completionHandler(RadarStatusSuccess, res, events, user, nearbyGeofences, config); + return completionHandler(RadarStatusSuccess, res, events, user, nearbyGeofences, config, nil); } [[RadarDelegateHolder sharedInstance] didFailWithStatus:status]; - completionHandler(RadarStatusErrorServer, nil, nil, nil, nil, nil); + completionHandler(RadarStatusErrorServer, nil, nil, nil, nil, nil, nil); }]; } diff --git a/RadarSDK/RadarLocationManager.m b/RadarSDK/RadarLocationManager.m index e60c25219..c58fefa4a 100644 --- a/RadarSDK/RadarLocationManager.m +++ b/RadarSDK/RadarLocationManager.m @@ -845,7 +845,7 @@ - (void)sendLocation:(CLLocation *)location stopped:(BOOL)stopped source:(RadarL replayed:replayed beacons:beacons completionHandler:^(RadarStatus status, NSDictionary *_Nullable res, NSArray *_Nullable events, RadarUser *_Nullable user, - NSArray *_Nullable nearbyGeofences, RadarConfig *_Nullable config) { + NSArray *_Nullable nearbyGeofences, RadarConfig *_Nullable config, NSString *_Nullable token) { self.sending = NO; [self updateTrackingFromMeta:config.meta]; diff --git a/RadarSDK/RadarUtils.m b/RadarSDK/RadarUtils.m index 18e41cd37..e14138b7b 100644 --- a/RadarSDK/RadarUtils.m +++ b/RadarSDK/RadarUtils.m @@ -45,7 +45,7 @@ + (NSNumber *)timeZoneOffset { } + (NSString *)sdkVersion { - return @"3.8.4"; + return @"3.8.5"; } + (NSString *)deviceId {