Skip to main content

Overview

Radar’s location verification feature enables you to verify a user’s location with high confidence using device integrity checks and cryptographic attestation. Perfect for geofencing compliance, location-based promotions, fraud prevention, and regulatory requirements.

How It Works

Location verification combines:
  1. Device Integrity: Uses Apple’s DeviceCheck framework to verify the device is genuine
  2. Location Accuracy: Validates GPS accuracy and checks for spoofing
  3. Cryptographic Token: Returns a signed JWT that can be verified server-side
  4. Fraud Detection: Checks for VPNs, proxies, emulators, and location spoofing
  5. Jurisdiction Validation: Optionally validates the user is in expected country/state
Prerequisites: SSL pinning must be configured before using verified tracking. This prevents man-in-the-middle attacks and ensures secure communication.

Setting Up SSL Pinning

Configure SSL pinning before calling any verified tracking methods:
import RadarSDK

// In your AppDelegate or app initialization
let initializeOptions = RadarInitializeOptions()
initializeOptions.enableCertificatePinning = true

Radar.initialize(
    publishableKey: "prj_live_pk_...",
    options: initializeOptions
)
SSL pinning is required for location verification. Calls to trackVerified() will fail without it.

Track Verified Location

Track a user’s location with device integrity verification:
Radar.trackVerified { (status, token) in
    if status == .success {
        if let token = token {
            print("Verified location token: \(token.token ?? "")")
            print("Passed verification: \(token.passed)")
            
            if token.passed {
                // User passed all checks
                print("User verified at location")
            } else {
                // User failed one or more checks
                if let reasons = token.failureReasons {
                    print("Failed verification: \(reasons.joined(separator: ", "))")
                }
            }
            
            // Send token to your server for verification
            sendTokenToServer(token.token)
        }
    } else {
        // Handle error
        print("Verification failed: \(status)")
    }
}

Track Verified with Options

Specify accuracy, beacon ranging, and additional context:
Radar.trackVerified(
    beacons: false,
    desiredAccuracy: .high,
    reason: "checkout",
    transactionId: "txn-123"
) { (status, token) in
    if status == .success {
        // handle verification token
    }
}

Track Verified Parameters

ParameterTypeDescription
beaconsBOOLWhether to range nearby beacons for additional verification.
desiredAccuracyRadarTrackingOptionsDesiredAccuracyDesired GPS accuracy (high, medium, low).
reasonString?Optional reason for verification (e.g., “checkout”, “sign_in”).
transactionIdString?Optional transaction or session ID for tracking.

Continuous Verified Tracking

Start continuous background tracking with verification:
// Start verified tracking with 30-second intervals
Radar.startTrackingVerified(interval: 30, beacons: false)

// Check if verified tracking is active
let isTracking = Radar.isTrackingVerified()
print("Verified tracking active: \(isTracking)")

Stop Verified Tracking

Radar.stopTrackingVerified()
Verified tracking runs in addition to regular tracking. It generates verified location tokens at specified intervals.

Getting Verified Location Token

Retrieve a cached verified location token if still valid:
Radar.getVerifiedLocationToken { (status, token) in
    if status == .success {
        if let token = token, token.expiresIn > 0 {
            print("Valid token expires in: \(token.expiresIn) seconds")
            // Use cached token
        } else {
            print("Token expired or unavailable, requesting fresh token")
        }
    }
}

Clear Cached Token

Radar.clearVerifiedLocationToken()

Verified Location Token

The RadarVerifiedLocationToken object contains:
let token: RadarVerifiedLocationToken

// JWT token - verify server-side with your secret key
let jwt = token.token

// Verification result
let passed = token.passed // true if all checks passed

// User and events
let user = token.user
let events = token.events

// Failure reasons (if any)
if let reasons = token.failureReasons {
    for reason in reasons {
        print("Failed check: \(reason)")
    }
}

// Token metadata
let checkId = token._id // Radar check ID
let expiresAt = token.expiresAt // Expiration date
let expiresIn = token.expiresIn // Seconds until expiration

// Full dictionary value
let fullDict = token.fullDict

Jurisdiction Validation

Set expected jurisdiction (country and state) to verify user location:
// Set expected jurisdiction
Radar.setExpectedJurisdiction(countryCode: "US", stateCode: "NY")

// Track verified
Radar.trackVerified { (status, token) in
    if let token = token {
        if token.passed {
            print("User verified in expected jurisdiction")
        } else if let reasons = token.failureReasons {
            // May include "jurisdiction_mismatch"
            print("Failed: \(reasons)")
        }
    }
}
Use jurisdiction validation for geofencing compliance, region-restricted content, or regulatory requirements.

Listening for Verified Tokens

Implement RadarVerifiedDelegate to receive verified location tokens:
class MyVerifiedDelegate: NSObject, RadarVerifiedDelegate {
    func didUpdateToken(_ token: RadarVerifiedLocationToken) {
        print("Received verified token: \(token.token ?? "")")
        print("Passed: \(token.passed)")
        
        if token.passed {
            // User location verified
            sendTokenToServer(token.token)
        } else {
            // Verification failed
            handleVerificationFailure(token.failureReasons)
        }
    }
    
    func didFail(status: RadarStatus) {
        print("Verification failed: \(status)")
    }
}

// Set the verified delegate
Radar.setVerifiedDelegate(MyVerifiedDelegate())

Server-Side Verification

Verify the JWT token server-side using your Radar secret key:
curl https://api.radar.io/v1/verify \
  -H "Authorization: your_secret_key" \
  -d token="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
The token payload includes:
{
  "user": { /* User object */ },
  "events": [ /* Array of events */ ],
  "passed": true,
  "failureReasons": [],
  "location": { /* Location coordinates */ },
  "fraud": { /* Fraud check results */ }
}
Always verify tokens server-side. Never trust client-side verification alone for security-critical decisions.

Failure Reasons

Common failure reasons include:
ReasonDescription
jurisdiction_mismatchUser is not in the expected country or state
location_spoofingLocation spoofing detected
device_integrity_failedDevice failed integrity checks
inaccurate_locationGPS accuracy is insufficient
vpn_detectedVPN or proxy detected
emulator_detectedApp running on emulator/simulator
low_confidenceLocation confidence is below threshold
if let reasons = token.failureReasons {
    for reason in reasons {
        switch reason {
        case "jurisdiction_mismatch":
            print("User outside expected region")
        case "location_spoofing":
            print("Location spoofing detected")
        case "vpn_detected":
            print("VPN/proxy detected")
        case "device_integrity_failed":
            print("Device integrity check failed")
        default:
            print("Verification failed: \(reason)")
        }
    }
}

Fraud Detection Events

When fraud is detected, Radar generates a fraud event:
func didReceiveEvents(_ events: [RadarEvent], user: RadarUser?) {
    for event in events {
        if event.type == .userFailedFraud {
            if let fraud = event.fraud {
                print("Fraud detected")
                print("Passed: \(fraud.passed)")
                
                // Check specific fraud flags
                if fraud.proxy {
                    print("Proxy detected")
                }
                if fraud.mocked {
                    print("Location mocking detected")
                }
                if fraud.jumped {
                    print("Location jump detected")
                }
                if fraud.compromised {
                    print("Device compromised")
                }
            }
        }
    }
}

Use Cases

Sports Betting

Verify users are within legal jurisdictions before allowing betting transactions.

Age-Restricted Content

Confirm user location for geo-restricted content and compliance with regional regulations.

Fraud Prevention

Detect location spoofing, VPNs, and other fraudulent behavior for financial transactions.

Promotional Eligibility

Verify customers are at physical store locations for in-store promotions and offers.

Attendance Verification

Confirm employees or students are physically present at required locations.

Insurance Claims

Verify location of insurance claims to prevent fraud and ensure accuracy.

Best Practices

1

Enable SSL Pinning

Always configure SSL pinning before using verified tracking. This is required and prevents security vulnerabilities.
2

Verify Tokens Server-Side

Never trust client-side verification alone. Always verify JWT tokens on your server using your secret key.
3

Handle Failures Gracefully

Check passed status and failureReasons. Provide clear messaging to users when verification fails.
4

Set Appropriate Jurisdiction

If using jurisdiction validation, ensure country and state codes are set before tracking.
5

Monitor Token Expiration

Verified tokens expire after a short time. Request fresh tokens when needed rather than caching indefinitely.
6

Balance Security and UX

Consider when to require verification. Not every action needs location verification—use it for high-value or compliance-critical operations.

Testing

Location verification requires physical devices. It will not work in simulators or when running on jailbroken devices.

Test Checklist

  • SSL pinning configured
  • Test on physical iOS device (not simulator)
  • Test with real GPS location (not mocked)
  • Verify tokens server-side
  • Test with VPN enabled (should fail)
  • Test jurisdiction validation
  • Test token expiration handling
  • Test failure scenarios
For more details on fraud detection, visit the Radar documentation.

Build docs developers (and LLMs) love