Additional Functionality
HYPR SDK for iOS
This document describes additional functionality available in the HYPR SDK for iOS.
Reset an App
Fully delete the App profile and all the users registered under the App profile. This will remove all features associated with the Application Profile, including (but not limited to) policies, users, devices, tokens, and associated endpoints.
HYPRUserAgent.resetUserAgent(with: .full) { (error) in
if let error = error {
// Handle the error
}
// Full Reset was complete
}
Locally delete the App profile and all the users registered under the App profile. The device is cleared of all locally stored registrations associated with the App Profile. The App and any other associated data in the CC are unaffected.
HYPRUserAgent.resetUserAgent(with: .local) { (error) in
if let error = error {
// Handle the error
}
// Local Reset was complete
}
Custom HTTPS Headers
Customize the information sent in a network request by adding custom HTTPS headers. Custom headers can be added to registration, authentication, and deregistration requests. To send and receive headers, create an object that conforms to the HYPRCustomHeadersAdapter
protocol and set that object as the CustomHeadersDelegate
via HYPRUserAgent.setCustomHeadersDelegate(<delegate object here>)
.
Sending Custom Headers
Add custom headers to your requests:
customHeaders(forUserInfo userInfo: [String : String] = [:]) -> [AnyHashable : Any]?
Receiving Custom Headers
Process custom headers from the response:
processCustomHeaders(fromUserInfo userInfo: [String : String] = [:])
Integration
- Within the
AppDelegate
method, enable custom headers for theHYPRUserAgent
.
HYPRUserAgent.setCustomHeadersDelegate(self)
- Create the function to set custom headers for networking requests.
func customHeaders(forUserInfo userInfo: [String : String] = [:]) -> [AnyHashable : Any]? {
guard let operation = userInfo[kHYPRCustomHeadersAdapterOperation], let phase = userInfo[kHYPRCustomHeadersAdapterPhase] else {
print("invalid userInfo sent for custom headers")
return nil;
}
switch operation {
case kHYPRCustomHeadersAdapterOperationRegistration:
switch phase {
case kHYPRCustomHeadersAdapterPhaseInit:
return <your custom headers which is a [String:String] dictionary>
case kHYPRCustomHeadersAdapterPhaseComplete:
return <your custom headers which is a [String:String] dictionary>
default:
print("invalid phase sent for custom headers")
}
}
- Create the function to process custom headers for networking responses.
func processCustomHeaders(fromUserInfo userInfo: [String : String] = [:]) {
print("Headers Received: \(userInfo)")
return;
}
Example
Below is a code example where AppDelegate
conforms to the HYPRCustomHeadersAdapter
protocol. The function customHeaders
is used for adding a custom header; processCustomHeaders
is used for processing headers from the response.
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, HYPRCustomHeadersAdapter {
internal func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Other code is here
HYPRUserAgent.setCustomHeadersDelegate(self)
}
func customHeaders(forUserInfo userInfo: [String : String] = [:]) -> [AnyHashable : Any]? {
guard let operation = userInfo[kHYPRCustomHeadersAdapterOperation], let phase = userInfo[kHYPRCustomHeadersAdapterPhase] else {
print("invalid userInfo sent for custom headers")
return nil;
}
switch operation {
case kHYPRCustomHeadersAdapterOperationRegistration:
switch phase {
case kHYPRCustomHeadersAdapterPhaseInit:
return <your custom headers which is a [String:String] dictionary>
case kHYPRCustomHeadersAdapterPhaseComplete:
return <your custom headers which is a [String:String] dictionary>
default:
print("invalid phase sent for custom headers")
}
case kHYPRCustomHeadersAdapterOperationAuthentication:
switch phase {
case kHYPRCustomHeadersAdapterPhaseInit:
return <your custom headers which is a [String:String] dictionary>
case kHYPRCustomHeadersAdapterPhaseComplete:
return <your custom headers which is a [String:String] dictionary>
default:
print("invalid phase sent for custom headers")
}
case kHYPRCustomHeadersAdapterOperationDeregister:
switch phase {
case kHYPRCustomHeadersAdapterPhaseInit:
return <your custom headers which is a [String:String] dictionary>
default:
print("invalid phase sent for custom headers")
}
case kHYPRCustomHeadersAdapterOperationOOBSetup:
switch phase {
case kHYPRCustomHeadersAdapterPhaseInit:
return <your custom headers which is a [String:String] dictionary>
default:
print("invalid phase sent for custom headers")
}
case kHYPRCustomHeadersAdapterOperationOOBRegistration:
switch phase {
case kHYPRCustomHeadersAdapterPhaseInit:
return <your custom headers which is a [String:String] dictionary>
default:
print("invalid phase sent for custom headers")
}
case kHYPRCustomHeadersAdapterOperationOOBAuthorization:
switch phase {
case kHYPRCustomHeadersAdapterPhaseInit:
return <your custom headers which is a [String:String] dictionary>
case kHYPRCustomHeadersAdapterPhaseComplete:
return <your custom headers which is a [String:String] dictionary>
default:
print("invalid phase sent for custom headers")
}
default:
print("invalid operation sent for custom headers")
}
return nil;
}
// For receiving HTTP Headers in HYPR SDK calls
func processCustomHeaders(fromUserInfo userInfo: [String : String] = [:]) {
print("Headers Received: \(userInfo)")
return;
}
}
Enabling SSL Pinning
By default, HYPR SDK for iOS will enforce SSL pinning. Once SSL pinning is enforced, HYPRSSLPinCredential
must be supplied to HYPRUserAgentProfileConfiguration
. HYPRSSLPinCredential
is made up of credential content (expected to be a base64-encoded string of a SHA256 hash of a DER-encoded public key) and algorithm (key algorithm with expected values: RSA_2048
, RSA_4096
, ECDSA_SECP_256_R1
, ECDSA_SECP_384_R1
. See HYPRKeyAlgorithmType
). Otherwise, SSL pinning can be disabled by setting it to false
.
Here is an example using AppDelegate.swift
or AppDelegate.m
:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
HYPRUserAgent.setSSLPinningEnabled(true)
let sslPinCredential = HYPRSSLPinCredential(content: "base64-encoded string of a SHA256 hash of a DER-encoded public key", algorithm: kHYPRKeyAlgorithmRsa2048)
let config = HYPRUserAgentProfileConfiguration(rpAppId: "HYPRDefaultApplication",
rpServerUrl: "Place the RP URL here: i.e. https://9999-pov.hypr.com",
deviceType: "WEB or WORKSTATION"
rpSSLPinCredentials: sslPinCredential,
additionalData: nil,
authenticatorViewConfigurations: nil)
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[HYPRUserAgent setSSLPinningEnabled:YES];
HYPRSSLPinCredential *sslPinCredential = [[HYPRSSLPinCredential alloc] initWithContent:@"base64-encoded string of a SHA256 hash of a DER-encoded public key" algorithm:kHYPRKeyAlgorithmRsa2048];
HYPRUserAgentProfileConfiguration *config = [[HYPRUserAgentProfileConfiguration alloc] initWithRpAppId:@"HYPRDefaultApplication" rpServerUrl:@"Place the RP URL here: i.e. https://9999-pov.hypr.com" rpSSLPinCredentials:sslPinCredential additionalData:nil authenticatorViewConfigurations:nil];
}
Gathering Device and App Information
- The
hyprDeviceIdentifier
method returns the permanently stored universally unique identifier (UUID) used to identify the mobile device
import HyprCore
func deviceId() -> String {
return HYPRUserAgent.hyprDeviceIdentifier()
}
- Use the
ipAddress
method to return the IP address of the device
func ipAddress() -> String? {
var address : String?
// Get list of all interfaces on the local machine:
var ifaddr : UnsafeMutablePointer<ifaddrs>?
guard getifaddrs(&ifaddr) == 0 else { return nil }
guard let firstAddr = ifaddr else { return nil }
// For each interface ...
for ifptr in sequence(first: firstAddr, next: { $0.pointee.ifa_next }) {
let interface = ifptr.pointee
// Check for IPv4 or IPv6 interface:
let addrFamily = interface.ifa_addr.pointee.sa_family
if addrFamily == UInt8(AF_INET) || addrFamily == UInt8(AF_INET6) {
// Check interface name:
let name = String(cString: interface.ifa_name)
if name == "en0" {
// Convert interface address to a human readable string:
var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
getnameinfo(interface.ifa_addr, socklen_t(interface.ifa_addr.pointee.sa_len),
&hostname, socklen_t(hostname.count),
nil, socklen_t(0), NI_NUMERICHOST)
address = String(cString: hostname)
}
}
}
freeifaddrs(ifaddr)
return address
}
- The
mobileOS
method returns the mobile device operating system; e.g., iOS 13.3.1
func mobileOS() -> String {
return "iOS \(UIDevice.current.systemVersion)"
}
- The
appVersion
method returns the version of the application
func appVersion() -> String?{
let bundle = Bundle(for: AppDelegate.self)
return bundle.infoDictionary?["CFBundleShortVersionString"] as? String
}
deviceModel
returns the iPhone Model Identifier; for example, iPhone 8 Plus will return iPhone 10.2
func deviceModel() -> String {
var systemInfo = utsname()
uname(&systemInfo)
let machineMirror = Mirror(reflecting: systemInfo.machine)
return machineMirror.children.reduce("") { identifier, element in
guard let value = element.value as? Int8, value != 0 else { return identifier }
return identifier + String(UnicodeScalar(UInt8(value)))
}
}
appIdentifier
returns the Bundle Identifier for the App
func appIdentifier() -> String? {
return Bundle(for: AppDelegate.self).bundleIdentifier
}
-
Retrieve the device's location (latitude, longitude):
Within
Info.plist
ensure that there is a key value pairing with the following:- key: Privacy – Location When in Use Usage Description
- value:
Here is an example using
AppDelegate
:
import CoreLocation
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var locationManager = CLLocationManager()
var currentLocationString: String? {
get{
if let location = locationManager.location {
return "{\"latitude\":"\(location.coordinate.latitude)",\"longitude\":"\(location.coordinate.longitude))"}"
}
else {
return nil
}
}
}
internal func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
locationManager.delegate = self
let authStatus = CLLocationManager.authorizationStatus()
if authStatus == .notDetermined {
locationManager.requestWhenInUseAuthorization()
}
else if authStatus == .authorizedAlways || authStatus == .authorizedWhenInUse {
locationManager.requestLocation()
}
}
}
extension AppDelegate: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if status == .authorizedAlways || status == .authorizedWhenInUse {
locationManager.requestLocation()
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
}
}
Updated 11 months ago