Skip to content

Metadata: Environment and Device Information #315

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 17 commits into
base: fraud-signals-metadata
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Sources/SmileID/Classes/Metadata/MetadataKey.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ enum MetadataKey: String {
case cameraName = "camera_name"
case clientIP = "client_ip"
case deviceModel = "device_model"
case deviceOrientation = "device_orientation"
case deviceOS = "device_os"
case documentBackCaptureRetries = "document_back_capture_retries"
case documentBackCaptureDuration = "document_back_capture_duration_ms"
Expand All @@ -14,11 +15,16 @@ enum MetadataKey: String {
case documentFrontCaptureDuration = "document_front_capture_duration_ms"
case documentFrontImageOrigin = "document_front_image_origin"
case fingerprint
case locale = "locale"
case memoryInfo = "memory_info"
case networkConnection = "network_connection"
case proxyDetected = "proxy"
case screenResolution = "screen_resolution"
case selfieCaptureDuration = "selfie_capture_duration_ms"
case selfieImageOrigin = "selfie_image_origin"
case sdk
case sdkVersion = "sdk_version"
case systemArchitecture = "system_architecture"
case timezone = "timezone"
case vpnDetected = "vpn"
}
10 changes: 10 additions & 0 deletions Sources/SmileID/Classes/Metadata/MetadataManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ public class MetadataManager {
key: .deviceModel, value: UIDevice.current.modelName)
addMetadata(
key: .deviceOS, value: UIDevice.current.systemVersion)
addMetadata(
key: .deviceOrientation, value: UIDevice.current.orientationString)
addMetadata(
key: .timezone, value: TimeZone.current.identifier)
addMetadata(
key: .locale, value: Locale.current.identifier)
addMetadata(
key: .screenResolution, value: UIScreen.main.formattedResolution)
addMetadata(key: .memoryInfo, value: ProcessInfo.processInfo.availableMemoryInMB)
addMetadata(key: .systemArchitecture, value: ProcessInfo.processInfo.systemArchitecture)
}

private func registerDefaultProviders() {
Expand Down
27 changes: 27 additions & 0 deletions Sources/SmileID/Classes/Metadata/ProcessInfoExtension.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import Foundation

extension ProcessInfo {
/// Returns the available physical memory in MB
var availableMemoryInMB: String {
// Get physical memory in bytes
let physicalMemory = self.physicalMemory

// Convert to MB (1 MB = 1,048,576 bytes)
let memoryInMB = physicalMemory / 1_048_576

return "\(memoryInMB)"
}

/// Returns the system architecture (e.g., "ARM64", "x86_64")
var systemArchitecture: String {
#if arch(arm64)
return "ARM64"
#elseif arch(x86_64)
return "x86_64"
#elseif arch(i386)
return "i386"
#else
return "Unknown"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we keep this all lower cased?

Suggested change
return "ARM64"
#elseif arch(x86_64)
return "x86_64"
#elseif arch(i386)
return "i386"
#else
return "Unknown"
return "arm64"
#elseif arch(x86_64)
return "x86_64"
#elseif arch(i386)
return "i386"
#else
return "unknown"

#endif
}
}
28 changes: 28 additions & 0 deletions Sources/SmileID/Classes/Metadata/UIDeviceExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,34 @@ extension UIDevice {
?? identifier
}

var orientationString: String {
switch UIDevice.current.orientation {
case .portrait, .portraitUpsideDown:
return "Portrait"
case .landscapeLeft, .landscapeRight:
return "Landscape"
case .faceUp:
return "FaceUp"
case .faceDown:
return "FaceDown"
case .unknown:
// Default to UI orientation if device orientation is unknown
let interfaceOrientation = UIApplication.shared.windows.first?.windowScene?.interfaceOrientation
switch interfaceOrientation {
case .portrait, .portraitUpsideDown:
return "Portrait"
case .landscapeLeft, .landscapeRight:
return "Landscape"
case .unknown, .none:
return "Unknown"
@unknown default:
return "Unknown"
}
@unknown default:
return "Unknown"
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: The code is using the deprecated UIApplication.shared.windows property which was deprecated in iOS 15. Use UIApplication.shared.connectedScenes instead to get the interface orientation. [possible issue, importance: 8]

Suggested change
var orientationString: String {
switch UIDevice.current.orientation {
case .portrait, .portraitUpsideDown:
return "Portrait"
case .landscapeLeft, .landscapeRight:
return "Landscape"
case .faceUp:
return "FaceUp"
case .faceDown:
return "FaceDown"
case .unknown:
// Default to UI orientation if device orientation is unknown
let interfaceOrientation = UIApplication.shared.windows.first?.windowScene?.interfaceOrientation
switch interfaceOrientation {
case .portrait, .portraitUpsideDown:
return "Portrait"
case .landscapeLeft, .landscapeRight:
return "Landscape"
case .unknown, .none:
return "Unknown"
@unknown default:
return "Unknown"
}
@unknown default:
return "Unknown"
}
}
var orientationString: String {
switch UIDevice.current.orientation {
case .portrait, .portraitUpsideDown:
return "Portrait"
case .landscapeLeft, .landscapeRight:
return "Landscape"
case .faceUp:
return "FaceUp"
case .faceDown:
return "FaceDown"
case .unknown:
// Default to UI orientation if device orientation is unknown
if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene {
switch windowScene.interfaceOrientation {
case .portrait, .portraitUpsideDown:
return "Portrait"
case .landscapeLeft, .landscapeRight:
return "Landscape"
case .unknown:
return "Unknown"
@unknown default:
return "Unknown"
}
}
return "Unknown"
@unknown default:
return "Unknown"
}
}


struct DeviceModel: Decodable {
let identifier: String
let model: String
Expand Down
11 changes: 11 additions & 0 deletions Sources/SmileID/Classes/Metadata/UIScreenExtension.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import UIKit

extension UIScreen {
/// Returns the screen resolution in pixels as a formatted string
var formattedResolution: String {
let scale = self.scale
let width = Int(self.bounds.width * scale)
let height = Int(self.bounds.height * scale)
return "\(width) x \(height)"
}
}
Loading