Overview
Describes the steps for integrating the HYPR FIDO Client Adapter into an iOS Application to facilitate decentralized registration, authentication, and deregistration.
HyprFidoClientAdapter
class can be used separately from the HyprUserAgent for FIDO Client registration, authentication and deregistration operations.
Requirements:
- HyprFidoClientAdapter is a part of the HyprCore SDK and can be used separately from HyprUserAgent
- HYPR SDK supports the iOS 11+, iPhone 5S and all latest models.
- Minimum deployment target - iOS 10.0
- Valid architectures: arm64
- Minimum Xcode version of 9.2
- Objective-C or Swift
Project Setup instructions
- Copy all frameworks from the HyprFidoClientAdapterSampleApp folder to your project folder.


- Add all frameworks files to your Xcode project with Add Files To ...


- On the general tab of your project file add all frameworks to the Embedded Binaries section


- Set
bitcode enabled = NO


- Set
Valid Architectures = arm64


HYPR SDK frameworks are ready for usage in your Xcode project.
Running instructions
Before running the HYPR SDK version with HYPR ADP included on the device - the developer should perform 2 simple steps:
- Go to Edit Scheme... menu
- Uncheck the Debug executable checkmark for the appropriate target.
The simulator works without this workaround
HYPR SDK Setup
Initialize and set the parentViewController. parentViewController
will be used for presenting authenticators on it.
Also you need to register the authenticators to be used in your app before the initialization.
By default, interstitial view is enabled and if 'interstitialViewDelegate' is not set, a default interstitial view will be provided. If interstitial view is not desired, disable it by calling 'enableInterstitialView:' function.
//register authenticators
[HYPRUAFClient registerAuthenticatorModule:[HYPRFaceAsm class]];
[HYPRUAFClient registerAuthenticatorModule:[HYPRFingerprintAsm class]];
//add another ones if needed
//set custom timeout in miliseconds. 30000 is default value
[HYPRFaceAsm setTimeout:10000];
//initialize
HYPRFidoClientAdapter* adapter = [HYPRFidoClientAdapter new];
//set parent view controller
[adapter setParentViewController:self];
// disable interstitial view
[adapter enableInterstitialView:NO];
//register authenticators
HYPRUAFClient.registerAuthenticatorModule(HYPRFaceIDAsm.self)
HYPRUAFClient.registerAuthenticatorModule(HYPRFingerprintAsm.self)
//add another ones if needed
//initialize
let fidoAdapter = HYPRFidoClientAdapter()
//set parent view controller
fidoAdapter.setParentViewController(self)
// disable interstitial view
fidoAdapter.enableInterstitialView(false)
FIDO Operations
Registration
[adapter registerRequest:fidoPayload
completion:^(NSString * _Nullable resultString, NSError * _Nullable error) {
//create a call to server with successPayload or handle the error
}];
//after receiving server response notify the adapter was it successful or not
NSError* error = nil;
BOOL isSuccessful = [adapter registerDidComplete:YES error:&error];
fidoAdapter.registerRequest(requestString!) { (resultString, error) in
self.textView.text = resultString != nil ?
resultString : "\(String(describing: error))"
//create a call to server with successPayload or handle the error
}
//after receiving server response notify the adapter was it successful or not
let isSuccess = fidoAdapter.registerDidComplete(true)
Authentication
Note
Use the same username, as in the fidoPayload for register request
[adapter authenticateRequest:fidoPayload username:username
completion:^(NSString * _Nullable resultString, NSError * _Nullable error) {
//create a call to server with successPayload or handle the error
}];
//after receiving server response notify the adapter was it successful or not
NSError* error = nil;
BOOL isSuccessful = [adapter authenticateDidComplete:YES error:&error];
fidoAdapter.authenticateRequest(requestString!, username: username!) { (resultString, error) in
self.textView.text = resultString != nil ?
resultString : "\(String(describing: error))"
//create a call to server with successPayload or handle the error
}
//after receiving server response notify the adapter was it successful or not
let isSuccess = fidoAdapter.authenticateDidComplete(true)
Deregistration
Note
Use the same username, as in the fidoPayload for register request
[adapter deregisterRequest:fidoPayload username:username
completion:^(NSString * _Nullable resultString, NSError * _Nullable error) {
//nothing to send to server here
}];
fidoAdapter.deregisterRequest(requestString!, username: username!) { (resultString, error) in
self.textView.text = resultString != nil ?
resultString : "\(String(describing: error))"
//nothing to send to server here
}
Enabling HYPRADP framework
Go to HYPR ADP integration page:
https://dash.readme.io/project/hyprdev/v3.0.0/docs/hypr-adp-integration
Error Handling
Errors may occur during registration, authentication, deregistration.
HYPR SDK returns the NSError
in case of an error. You can check the error code and it's localized description as in standard NSError
. Also in the HyprError.h
interface you can find the method in NSError category which also could be checked for error code and localized description.
-(NSError*)rootError;
Please see Error Handling for more info on the possible errors.
Offline mode
The HYPRFidoClientAdapter
can perform any FIDO operations such as: registration, authentication and deregistration in offline mode.
The point of failure - facets check. If the payload includes the facets check and the facets url is not reachable of any reason in that moment and no cached facets values exist - the operation will fail.
All other cases, including:
- no facets url specified in payload
- facets are cached because of previous successful facets url check
will work correct.
Policy handling
If SDK matches more than one set of the authenticators on registration or authentication request - the Hypr Fido Client Adapter presents the ViewController with UITableView, which include 1 set per cell. Set may include one or many authenticators. The SDK will proceed the registration or authentication process with the chosen set after it.
This feature could be turned off by passing NO to -(void)setAAIDPickerViewEnabled:(BOOL)enabled
method of HyprFidoClientAdapter. Also if picker view is enabled you can enable/disable it separately for authentication with -(void)setAAIDPickerViewEnabledForAuthentication:(BOOL)enabled
method.
// Enables/disables the AAID Picker for the Fido Client Adapter
-(void)setAAIDPickerViewEnabled:(BOOL)enabled;
// Enables/disables the AAID picker for authentication only if it is enabled with previous method
-(void)setAAIDPickerViewEnabledForAuthentication:(BOOL)enabled;
Implementing HYPRInterstitialDelegateProtocol
HYPRFidoClientAdapter provides the ability to specify the custom interstitialViewDelegate:
@property (nonatomic, weak) _Nullable id<HYPRInterstitialDelegateProtocol> interstitialViewDelegate;
Currently only UIAlertController is supported and the user can specify text string only. Here is the implementation example:
-(HYPRInterstitialViewModel* _Nullable)interstitialViewModelForUserInfo:(NSDictionary *)userInfo {
HYPRInterstitialViewModel *customModel = [[HYPRInterstitialViewModel alloc] init];
customModel.viewMode = HYPRInterstitialViewModeAlert;
NSString *previousDescription = userInfo[kHYPRInterstitialDelegateProtocolPreviousDescription];
NSString *nextDescription = userInfo[kHYPRInterstitialDelegateProtocolNextDescription];
NSNumber *currentStep = userInfo[kHYPRInterstitialDelegateProtocolAuthenticatorIndex];
NSNumber *totalSteps = userInfo[kHYPRInterstitialDelegateProtocolTotalAuthenticators];
NSString *title = [NSString stringWithFormat:@"Step %@ of %@ Complete",
currentStep, totalSteps];
NSString *operationString;
if ([userInfo[kHYPRInterstitialDelegateProtocolOperation] isEqualToString:kHYPRInterstitialDelegateProtocolOperationRegistration]) {
operationString = @"registration";
} else if ([userInfo[kHYPRInterstitialDelegateProtocolOperation] isEqualToString:kHYPRInterstitialDelegateProtocolOperationAuthentication]) {
operationString = @"authentication";
} else {
operationString = @"operation"; // fallback, but should not be used
}
NSString *message = [NSString stringWithFormat:@"Completed %@ for %@. Next is %@.",
operationString, previousDescription, nextDescription];
customModel.message = message;
customModel.title = title;
return customModel;
}
If not implemented - the default implementation will be used.
Authentication failing due to Private Key Signing
Authentication can fail if the user has deleted their passcode and created a new one. In order to detect this, call the following method.
let authSigningWillSucceed = HYPRFidoClientAdapter().authenticationSignatureWillSucceedDuringAuth(forUser: "User4e442oqsbi99g31u98rprrvbc3", withFacetId: HYPRUAFClient.facetId())
Note: If you are updating from any version below 6.4.1, then you will need to update your existing users with this following method:
HYPRFidoClientAdapter.createPrivateKeysToCheckIfPasscodeSet(forUser: "User4e442oqsbi99g31u98rprrvbc3", withFacetId: HYPRUAFClient.facetId())
If the passcode was changed prior to upgrading 6.4.1, HYPRFidoClientAdapter().authenticationSignatureWillSucceedDuringAuth will not be able to detect that the passcode has changed.
Updated 4 months ago