FIDO Client Adapter

HYPR SDK for iOS

Describes the steps for integrating the HYPR FIDO Client Adapter (FCA) 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 HYPR SDK for iOS and can be used separately from HyprUserAgent
  • HYPR SDK for iOS supports the iOS 11+, iPhone 5S, and all latest models
  • Minimum deployment target: iOS 10.0
  • Valid architectures: arm64
  • Minimum Xcode version: 9.2
  • Objective-C or Swift

Project Setup Instructions

  1. Copy all frameworks from the HyprFidoClientAdapterSampleApp folder to your project folder.
1528
  1. Add all frameworks files to your Xcode project with Add Files to <ProjectName>....
1038
  1. On the General tab of your project file, add all frameworks to the Embedded Binaries section.
2050
  1. Set Enable Bitcode to No.
2242
  1. Set Valid Architectures to arm64.
2114

HYPR SDK for iOS frameworks are ready to use in your Xcode project.

Running Instructions

Before running the HYPR SDK for iOS version with HYPR ADP included on the device, the developer should perform the following steps:

  1. Go to the Edit Scheme... menu.
  2. 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.
You must 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 the '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 for register requests as used in fidoPayload.

[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 for register requests as used in fidoPayload.

[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
            }

Error Handling

Errors may occur during registration, authentication, and deregistration.

HYPR SDK for iOS returns NSError in the case of an error. You can check the error code and its localized description as with the standard NSError. In the HyprError.h interface you can find the method in the NSError category which also could be checked for an error code and localized description.

-(NSError*)rootError;

Please see Error Reporting for more information on possible errors.

Offline Mode

The HYPRFidoClientAdapter can perform any FIDO operations, such as registration, authentication and deregistration in offline mode.

If the payload includes the facets check and the facets URL is not reachable and no cached facets values exist, the operation will fail.
All other cases will succeed, including:

  • No facets URL is specified in the payload
  • Facets are cached because of previous successful facets URL checks

Policy Handling

If the HYPR SDK for iOS matches more than one set of authenticators upon a registration or authentication request, the HYPR FCA presents the ViewController with UITableView, which includes one set per cell. Each set may include one or many authenticators. The SDK will precede the registration or authentication process, with the chosen set following.

This feature can be turned off by passing NO to the -(void)setAAIDPickerViewEnabled:(BOOL)enabled method of HyprFidoClientAdapter. Also if the picker view is enabled you can enable/disable it separately for authentication with the -(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 a text string only.

-(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;
}

Authentication Failing Due to Private Key Signing

Authentication can fail if the user has deleted their passcode and created a new one. To detect this, call the following method:

let authSigningWillSucceed = HYPRFidoClientAdapter().authenticationSignatureWillSucceedDuringAuth(forUser: "User4e442oqsbi99g31u98rprrvbc3", withFacetId: HYPRUAFClient.facetId())

If you are updating from any version below 6.4.1, then you must update your existing users with this method:

HYPRFidoClientAdapter.createPrivateKeysToCheckIfPasscodeSet(forUser: "User4e442oqsbi99g31u98rprrvbc3", withFacetId: HYPRUAFClient.facetId())

🚧

WARNING

If the passcode was changed prior to upgrading 6.4.1, HYPRFidoClientAdapter().authenticationSignatureWillSucceedDuringAuth will not be able to detect that the passcode has changed.