Radar.trackVerified()
or Radar.startTrackingVerified()
. Radar will perform fraud and jurisdiction checks as described below.
Radar.trackOnce()
to accurately detect a user’s current geofences, current place, or current country and state.
However, users can spoof a device’s location. For example, a gaming app user may spoof their location to access sports betting features only available in specific states. Or, a retail app user may spoof their location to access offers only available inside a store geofence.
To ensure you can trust a user’s location, you can call Radar.trackVerified()
instead. Radar will collect a variety of fraud signals and perform fraud and jurisdiction checks, calculating flags and a signed geolocation token that you can use for fraud detection and geo-compliance in your app.
user.fraud
:
mocked
: Indicates whether a user’s location is being mocked, such as in a simulator or using a location spoofing app (e.g., Fake GPS location).jumped
: Indicates whether the user moved too far too fast (e.g., “jumped” across the country in only a few seconds).compromised
: Indicates whether the user’s device or app has been compromised (e.g., rooted, jailbroken). On Android, uses the Play Integrity API.inaccurate
: Indicates whether the user’s location accuracy is too low to pass verification.sharing
: Indicates whether the user is using screen sharing or remote desktop software (e.g., using TeamViewer).proxy
: Indicates whether the user’s IP address is a known proxy or VPN.verified
: Indicates whether the request was made with Radar.trackVerified()
.user.fraud.passed
flag that indicates whether all fraud checks passed.
Additionally, the lastMockedAt
, lastJumpedAt
, lastCompromisedAt
, lastInaccurateAt
, lastProxyAt
, and lastSharingAt
timestamps indicate the last time that the user failed each fraud check.
Finally, more detailed failure reasons are also exposed.
user.fraud.bypassed = true
and user.fraud.passed = true
, regardless of whether the user passes fraud checks.
user.fraud.blocked = true
and user.fraud.passed = false
, regardless of whether the user passes fraud checks.
user.country.allowed
and user.state.allowed
.
Additionally, you can enable buffer zones and exclusion zones for different states. If buffer zones and exclusion zones are enabled, user.state.inBufferZone
and user.state.inExclusionZone
indicates whether the user is within a buffer zone or exclusion zone.
While you can work with individual flags, Radar also exposes user.state.passed
and user.country.passed
flags that indicate whether all jurisdiction checks passed.
Finally, more detailed failure reasons are also exposed.
sharing
flag on Android, pass fraud = true
to Radar.initialize()
.
compromised
flag on Android, enable the Play Integrity API on the Settings page.
If the user’s device or app does not meet basic integrity checks, user.fraud.compromised = true
.
You must add the Play Integrity API dependency before calling Radar.trackVerified()
.
Add the dependency to the dependencies
section of your app’s build.gradle
file:
Radar.trackVerified()
returns ERROR_FORBIDDEN
, check the logs. The Play Services version on the device may be out of date.
res/xml/network_security_config.xml
file:
compromised
flag on iOS, enable App Attest and configure a list of valid App IDs (e.g., A1B2C3D4E5.com.yourapp.app1,A1B2C3D4E5.com.yourapp.app2
) on the Settings page.
If App Attest indicates that the user’s device or app has been compromised, user.fraud.compromised = true
.
App Attest requires iOS 14 and above. If Radar.trackVerified()
returns ERROR_FORBIDDEN
, check the logs. The iOS version on the device may not support App Attest.
Info.plist
file:
sharing
flag, more advanced mocked
and proxy
detection, and more stable device IDs. Download the Radar Verify Mac app or the Radar Verify Windows app. By default, Radar.trackVerified()
expects the Radar Verify app to be running and returns ERROR_VERIFY_APP
if it is not.
To skip the Radar Verify app and use the no-download solution, pass { skipVerifyApp: true }
to Radar.trackVerified()
, Radar.startTrackingVerified()
, and Radar.getVerifiedLocationToken()
.
Radar.trackVerified()
to manually perform a location check. Radar.trackVerified()
returns a RadarVerifiedLocationToken
with:
passed
: A boolean indicating whether the user passed all fraud and jurisdiction checks (user.fraud.passed && user.country.passed && user.state.passed
).token
: A tamper-proof JSON Web Token (JWT) that you can send to your server to validate the signature, signed with the JSON Web Token (JWT) Secret Key found under Fraud on the Settings page.failureReasons
: If passed == false
, an array of more detailed failure reasons.expiresAt
: The datetime when the token expires, by default in 20 minutes, but earlier when close to the border based on compliance requirements.expiresIn
: The number of seconds until the token expires.user
: The user, with detailed information in user.fraud
, user.country
, and user.state
.events
: The events generated, if any.Radar.startTrackingVerified()
automatically perform location checks on connection changes, on the specified interval
, or more frequently if token.expiresIn < interval
(based on current state, distance to border, and so on).
Instead of calling Radar.trackVerified()
, which always fetches a fresh location token, you can call Radar.getVerifiedLocationToken()
, which returns a cached location token immediately if the last location token is still valid, or fetches a fresh location token if not.
If you set a delegate on iOS with Radar.setVerifiedDelegate()
or a receiver on Android with Radar.setVerifiedReceiver()
, fresh location tokens are also delivered to RadarVerifiedDelegate.didUpdateToken()
and RadarVerifiedReceiver.onTokenUpdated()
, respectively.
For example, to automatically verify the user’s location at least every 20 minutes (1200 seconds), without ranging beacons:
passed == false
, responses include an array of more detailed failure reasons.
country_not_allowed
: The user’s location is in a country that is not allowed based on jurisdiction settings.country_not_expected
: The user’s location is in a country that is not expected based on Radar.setExpectedJurisdiction()
.country_in_buffer_zone
: The user’s location is too close to the border of a country, either based on a jurisdiction-specific threshold or based on the location accuracy reported by the device (i.e., a “radius of uncertainty” that overlaps a country border).country_in_exclusion_zone
: The user’s location is in a country-specific exclusion zone, if enabled.state_not_allowed
: The user’s location is in a state or province that is not allowed according to jurisdiction settingsstate_not_expected
: The user’s location is in a state or province that is not expected according to Radar.setExpectedJurisdiction()
.state_in_buffer_zone
: The user’s location is too close to the border of a state or province, either based on a jurisdiction-specific threshold or based on the location accuracy reported by the device (i.e., a “radius of uncertainty” that overlaps a state or province border).state_in_exclusion_zone
: The user’s location is in a state- or province-specific exclusion zone, if enabled.fraud_blocked_user_id
: The userId
of the user is blocked (all platforms).fraud_blocked_device_id
: The deviceId
of the user is blocked (all platforms).fraud_blocked_ip
: The IP of the user is blocked (all platforms).fraud_blocked_mac_address
: The MAC address of the user is blocked (macOS and Windows only).fraud_blocked_risk_score_auto_block
: The user or device was automatically blocked based on a high risk score (all platforms).fraud_compromised_jailbroken
: The user’s iOS device is jailbroken (iOS only).fraud_compromised_app_attest
: The user’s iOS device failed App Attest checks (iOS only).fraud_compromised_play_integrity_api
: The user’s Android device failed Play Integrity API basic integrity checks (Android only).fraud_mocked_from_mock_provider
: The user’s location is mocked or spoofed according to iOS, Android, macOS, or Windows location services (all platforms).fraud_mocked_known_spoofing_app
: The user’s device is running a known location spoofing app (macOS and Windows only).fraud_mocked_inconsistent_ip_country
: The user’s location is in a country inconsistent with the IP geolocation country (all platforms).fraud_jumped_single_device
: The user’s location moved too far too fast (e.g., “jumped” across the country in a few seconds), possibly indicating impossible travel (all platforms).fraud_jumped_multiple_devices
: The device’s location is inconsistent with another device’s location with the same userId
, possibly indicating account sharing (all platforms).fraud_inaccurate_exceeded_accuracy_threshold
: The user’s location accuracy reported by the device is too low and exceeds a specified threshold (all platforms).fraud_sharing_known_screen_sharing_app
: The user’s device is running a known screen sharing or remote desktop app (macOS and Windows only).fraud_sharing_multiple_displays
: The user’s Android device has multiple displays, indicating possible screen sharing (Android only).fraud_sharing_virtual_input_device
: The user’s Android device has a virtual input device, indicating possible screen sharing (Android only).fraud_proxy_known_proxy_ip
: The user’s IP address is a known proxy or VPN (all platforms).fraud_proxy_network_configuration
: The user’s network configuration indicates the use of a proxy or VPN (macOS and Windows only).mocked
, jumped
, compromised
, sharing
, and proxy
flags: 1 strikeERROR_PERMISSIONS
: Unable to determine your location. Please make sure you’ve granted location permissions and try again.ERROR_LOCATION
: Unable to determine your location. Please make sure location services and wi-fi are enabled and try again.ERROR_NETWORK
: Unable to determine your location. Please make sure you’re connected to the Internet and try again.country.allowed == false
or state.allowed == false
: Unable to verify your location. Please make sure you’re in an allowed area and try again.fraud.proxy == true
: Unable to verify your location. Please disconnect from any VPNs or proxy servers you may be using and try again.