Device Profile Module
A flexible, extensible, and privacy-conscious framework for collecting device information in iOS applications.
The Device Profile module provides a structured framework for collecting device information in iOS applications. It uses a modular collector system that makes it easy to gather, extend, and customize the device data you need with modern Swift async/await patterns.
Features
- Modular Architecture: Plug-and-play collector system for maximum flexibility
- Async/Await Support: Modern Swift concurrency for smooth UI performance
- AIC Journey Integration: Built-in support for PingOne AIC Device Profile workflows
- Codable Output: JSON-ready data structures for easy network transmission
- Extensible Framework: Create custom collectors for any device signals you need
- Privacy-Aware: Handles iOS permissions gracefully with automatic permission requests
- Location Services: Built-in location collection with privacy-first permission handling
- SwiftUI Ready: ObservableObject support for seamless SwiftUI integration
Overview
This module helps you collect various device attributes through dedicated collectors:
- Hardware information: Camera capabilities, display properties, CPU cores, memory specifications
- Platform details: iOS version, device model, system name, locale, timezone, security status
- Network information: Connection status, interface type, expense and constraint characteristics
- Telephony information: Carrier name, network country code with multi-SIM support
- Browser information: User agent string from WebKit engine
- Bluetooth capabilities: BLE support detection
- Location data: GPS coordinates with automatic permission handling
- Custom collectors: Extend with your own logic for any device data
Getting Started
Permissions
The module respects iOS’s permission model. Some collectors may require specific permissions:
<!-- Required in Info.plist for LocationCollector -->
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs location access to enhance security and provide personalized experiences.</string>
<!-- Optional: For always-on location access -->
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>This app needs location access to enhance security and provide personalized experiences.</string>
<!-- Note: LocationCollector handles permission requests automatically -->
Basic Usage
- Add the module dependency to your project:
dependencies: [
.package(url: "https://github.com/ForgeRock/ping-ios-sdk", from: "x.y.z")
]
- Create collectors and collect device information:
import DeviceProfile
func collectDeviceProfile() async {
// Initialize collectors with default set
let collectors = DefaultDeviceCollector.defaultDeviceCollectors()
do {
// Collect device information
let deviceProfile = try await collectors.collect()
// Use the collected profile (Dictionary)
print("Device Profile: \(deviceProfile)")
} catch {
print("Collection failed: \(error)")
}
}
SwiftUI Integration
import SwiftUI
import DeviceProfile
struct ContentView: View {
@State private var deviceProfile: [String: Any] = [:]
@State private var isCollecting = false
var body: some View {
VStack {
if isCollecting {
ProgressView("Collecting device information...")
} else {
Button("Collect Device Profile") {
Task {
await collectProfile()
}
}
}
}
}
private func collectProfile() async {
isCollecting = true
defer { isCollecting = false }
let collectors = DefaultDeviceCollector.defaultDeviceCollectors()
do {
deviceProfile = try await collectors.collect()
} catch {
print("Collection error: \(error)")
}
}
}
Example Output
{
"platform": {
"platform": "iOS",
"version": "17.0.1",
"device": "iPhone",
"deviceName": "John's iPhone",
"model": "iPhone15,2",
"brand": "Apple",
"locale": "en",
"timeZone": "America/New_York",
"jailBreakScore": 0.0
},
"hardware": {
"manufacturer": "Apple",
"memory": 6144,
"cpu": 6,
"display": {
"width": 393,
"height": 852,
"orientation": 1
},
"camera": {
"numberOfCameras": 3
}
},
"network": {
"connected": true
},
"telephony": {
"networkCountryIso": "US",
"carrierName": "Verizon"
},
"browser": {
"userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15..."
},
"bluetooth": {
"supported": true
}
}
Built-in Collectors
The module provides several built-in collectors out of the box:
PlatformCollector
Gathers platform and device identification information:
{
"platform": {
"platform": "iOS",
"version": "17.0.1",
"device": "iPhone",
"deviceName": "John's iPhone",
"model": "iPhone15,2",
"brand": "Apple",
"locale": "en",
"timeZone": "America/New_York",
"jailBreakScore": 0.0
}
}
HardwareCollector
Collects comprehensive hardware specifications:
{
"hardware": {
"manufacturer": "Apple",
"memory": 6144,
"cpu": 6,
"display": {
"width": 393,
"height": 852,
"orientation": 1
},
"camera": {
"numberOfCameras": 3
}
}
}
NetworkCollector
Determines current network connectivity status:
{
"network": {
"connected": true
}
}
TelephonyCollector
Collects carrier and network information with multi-SIM support:
{
"telephony": {
"networkCountryIso": "US",
"carrierName": "Verizon"
}
}
BrowserCollector
Collects WebKit user agent information:
{
"browser": {
"userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15..."
}
}
BluetoothCollector
Detects Bluetooth Low Energy capability:
{
"bluetooth": {
"supported": true
}
}
LocationCollector
Collects GPS coordinates with automatic permission handling:
{
"location": {
"latitude": 37.7749,
"longitude": -122.4194
}
}
Location Privacy Features:
- Automatically requests permissions when needed
- Handles both “when in use” and “always” authorization types
- Gracefully handles permission denials
- Includes intelligent caching (5-second validity)
Customization
Using Built-in Collectors
The module comes with several built-in collectors that you can use:
import DeviceProfile
// Use all default collectors
let collectors = DefaultDeviceCollector.defaultDeviceCollectors()
// Or manually select specific collectors
let customCollectors: [any DeviceCollector] = [
PlatformCollector(),
HardwareCollector(),
NetworkCollector(),
TelephonyCollector(),
BrowserCollector(),
BluetoothCollector()
// LocationCollector() // Add separately if needed
]
Creating Custom Collectors
You can create your own collectors to gather specific device information:
struct BatteryCollector: DeviceCollector {
typealias DataType = BatteryInfo
let key = "battery"
func collect() async throws -> BatteryInfo? {
return BatteryInfo(
level: UIDevice.current.batteryLevel,
state: UIDevice.current.batteryState.rawValue
)
}
}
struct BatteryInfo: Codable {
let level: Float
let state: Int
}
AIC Journey Integration
The DeviceProfileCallback class provides a specialized way to collect device information
specifically for integration with AIC Journeys. It creates device profiles in the format expected by
AIC Journeys and integrates seamlessly with the Ping Journey framework.
Setup
PingJourney module will automatically register DeviceProfileCallback if PingDeviceProfile module is imported
Basic Usage with DeviceProfileCallback
When the server requests device profiling during a journey, the callback will automatically be created and configured:
// This happens automatically within a Ping Journey flow
// The callback receives server configuration for metadata and location collection
// Collect with default collectors
let result = await callback.collect()
Customizing AIC Journey Device Profile Collection
You can customize which collectors are used during the callback collection:
let result = await deviceProfileCallback.collect { config in
// Configure custom collectors for enhanced AIC risk assessment
config.collectors {
return [
PlatformCollector(),
HardwareCollector(),
NetworkCollector(),
BrowserCollector(),
BluetoothCollector(),
SecurityCollector() // Custom collector
]
}
}
// Handle the result
result
.onSuccess { profile in
// Device profile automatically submitted to AIC service
print("Profile collected successfully")
}
.onFailure { error in
print("Collection failed: \(error)")
}
AIC Profile Structure
When using DeviceProfileCallback, the output is structured specifically for AIC consumption:
{
"identifier": "unique-device-id",
"metadata": {
"platform": {
"platform": "iOS",
"version": "17.0.1",
"device": "iPhone"
},
"hardware": {
"manufacturer": "Apple",
"memory": 6144,
"cpu": 6
},
"network": {
"connected": true
}
},
"location": {
"latitude": 37.7749,
"longitude": -122.4194
}
}
Server Configuration
The server can configure what data to collect:
- metadata: Controls whether device metadata should be collected
- location: Controls whether location data should be collected
- message: Optional message with instructions or context
// These properties are automatically set based on server configuration
print("Metadata collection: \(callback.metadata)")
print("Location collection: \(callback.location)")
print("Server message: \(callback.message)")
© Copyright 2025-2026 Ping Identity Corporation. All Rights Reserved
View on GitHub