Authentication Hub Core iOS-SDK - 2.3.2

Authentication Hub Core SDK - 2.3.2 includes Authentication Hub Request Module, Password Encryption Module, Network Module, and Utility APIs.

Updates in Authentication Hub Core iOS 2.3.2 release

VIP Authentication Hub
includes the following new features and improvements in iOS SDK 2.3.2 release:
If you previously used the
initAuth
SDK API to set the request object for logging network request data, you now must set the Authentication Hub request object by invoking the setAuthHubRequestObject() SDK API on the AHCore instance.

Authentication Hub Network Request Module

Authentication Hub Network Request Module is a part of the AuthHubCore framework. The Authentication Hub Client SDK APIs are designed to handle the network request and response for all the Authentication Hub APIs, such as, "/authentication", "/BrandingSettings" and have complete control over them. Apart from handling essential API request payload/headers/query params, if you intend to customize the network layer to use it for tasks like adding custom headers or supporting SSL pinning, you need to implement three interfaces in your application to handle the network request customization. These interfaces are provided by Authentication Hub and are explained in the following sections:
  • AuthHubEndPoint
    : This interface provides the set of APIs that mobile applications can implement to customize the network request. Using these API implementation, the mobile application can override the headers, add custom headers, or add new parameters to the request payload as required.
    This interface defines the following APIs -
    func setRequestPayloadParameters(_ params: [String: Any]!) func setRequestHeaders(_ headers: [String: Any]!) func build() throws -> URLRequest
    The following table explains the APIs of this interface:
    API Name
    Description
    setRequestPayloadParameters()
    Accepts the map of key-value pairs which is sent in the JSON request body of the network request.
    setRequestHeaders()
    Accepts the map of key-value pairs which is sent as a request header of the network request.
    build()
    Builds an actual network request object which is sent to the Authentication Hub server.
  • AuthHubRequestLogger
    : This interface provides the APIs required for logging the network level data and logs the time that is required for the network calls. The AuthHubRequestLogger provides the ability to log network request level information, such as request headers, request body, request response body, and response time.
    The AuthHubRequestLogger interface must be implemented if you want to add custom logging to the network request object.
    This interface defines the following APIs -
    func enableLog(enable: Bool) func setLoggingType(type: RequestLoggingType) func logRequestData(responseTime: Int64, endPoint: AuthHubEndpoint, respDict: [String : AnyObject]?)
    The following table explains the APIs of this interface:
    API Name
    Description
    enableLog()
    Enables logging for a network request. By default it is
    disabled
    .
    setLoggingType()
    Sets the logging type of the request logger. The RequestLoggingType is an
    enum
    that can have these values:
    resp_time
    ,
    data
    , and
    none
    .
    • resp_time - This type of logger logs only the response time
    • data - This type of logger logs the request data, such as, headers, request body, response body and response time
    • none - This type of logger does not log any data
    logRequestData()
    This API is used for logging the request data as per the RequestLoggingType.
    • AHRequestLogger
      :This class is the default implementation of the AuthHubRequestLogger interface. By default, this class logs all request data to the console.
      You must create an instance of this class and must initialize it with the name of the log file, if you want the logger to write logs to the file.
  • AHAPIRequest
    : This interface provides the APIs required to handle network level functionality, such as, sending requests, logging network request. This interface defines the following APIs -
    func sendRequest(endpoint: AuthHubEndpoint) async throws -> AHRequestResult func setRequestLogger(requestLogger: AuthHubRequestLogger)
    The following table explains the APIs of this interface:
    API Name
    Description
    sendRequest()
    This API accepts the AuthHubEndpoint instance object.
    setRequestLogger()
    This API sets the AuthHubRequestLogger object for the network request object.
    • AuthHubBasicRequest
      : This class is the default implementation of the
      AHAPIRequest
      interface.
The following example shows a sample implementation of the network request interface that is defined previously.
import Foundation import AuthHubCore class SampleAuthHubRequest : AuthHubBasicRequest { func addRequestHeaders(endpoint: AuthHubEndpoint) -> [String:Any] { let urlPath = endpoint.path var newHeaders = endpoint.headers switch(urlPath) { case .brandingSettings: newHeaders["HEDMORAL_BRANDING_SETTINGS"] = "HEDMORAL_BRANDING_VALUE"; break; case .authHubPublicKey: newHeaders["HEDMORAL_PUBLIC_KEY"] = "HEDMORAL_PUBLIC_KEY_VALUE"; break; case .serverNonceGenerator: newHeaders["HEDMORAL_SERVER_NONCE"] = "HEDMORAL_SERVER_NONCE_VALUE"; break; case .authEndpoint: newHeaders["HEDMORAL_INIT_AUTH"] = "HEDMORAL_INIT_AUTH_VALUE"; break; case .registerChallengeGenerator: newHeaders["HEDMORAL_REG_CHAL_GEN"] = "HEDMORAL_REG_CHAL_GEN_VALUE"; break; case .registerChallengeVerifier: newHeaders["HEDMORAL_REG_CHAL_VERIFY"] = "HEDMORAL_REG_CHAL_VERIFY_VALUE"; break; case .authChallengeGenerator: newHeaders["HEDMORAL_AUTH_CHAL_GEN"] = "HEDMORAL_AUTH_CHAL_GEN_VALUE"; break; case .authChallengeVerifier: newHeaders["HEDMORAL_AUTH_CHAL_VERIFY"] = "HEDMORAL_AUTH_CHAL_VERIFY_VALUE"; break; case .txnSignChallengeGenerator: newHeaders["HEDMORAL_TXN_CHAL_GEN"] = "HEDMORAL_TXN_CHAL_GEN_VALUE"; break; case .txnSignChallengeVerifier: newHeaders["HEDMORAL_TXN_CHAL_VERIFY"] = "HEDMORAL_AUTH_CHAL_VERIFY_VALUE"; break; @unknown default: newHeaders["HEDMORAL_DEFAULT_HEADER"] = "HEDMORAL_DEFAULT_HEADER_VALUE"; break; } return newHeaders; } override func sendRequest(endpoint: AuthHubEndpoint) async throws -> AHRequestResult { let newHeaders = addRequestHeaders(endpoint: endpoint) endpoint.setRequestHeaders(newHeaders) return try await super.sendRequest(endpoint: endpoint) } }
The following example shows how to use the sample request that was created in the previous example to initialize the Authentication Hub FIDO SDK instance:
let ahfidosdk = AHFIDOSDK.getInstance() /*Create instance of SampleAuthHubRequest*/ let hedmoralRequestObject = SampleAuthHubRequest() /*Create instance of AHRequestLogger and enable it*/ let ahReqLogger = AuthHubCore.AHRequestLogger(fileName: nil) ahReqLogger.enableLog(enable: true) /*Set request logger for created request object*/ hedmoralRequestObject.setRequestLogger(requestLogger: ahReqLogger) /*Create instance of AHRequestLogger and enable it*/ ahfidosdk.initFIDO(serverHost: "example.broadcom.com", tenant: "default", authhubRequest: hedmoralRequestObject)

Authentication Hub Core Framework APIs

This section includes the Authentication Hub Core Framework APIs:

Create an instance of the AuthHubCore.framework AHCore class

  • To create an instance of the
    AuthHubCore.framework AHCore
    class, invoke the
    getInstance()
    API. The API returns a singleton instance of the AHCore class.
    public static func getInstance() -> AHCore
  • To get the version of the
    AuthHubCore.framework,
    invoke the
    getVersion() API.
    The currently supported version of the
    AuthHubCore.framework
    is 2.3.2.
    public static func getVersion() -> String

Setting Up the Network Request Object

To set the network request object, call the AuthHubCore API,
setAuthHubRequestObject()
public func setAuthHubRequestObject(authhubRequest: AuthHubBasicRequest)
The API parameters have been described in the following table:
Name
Type
Description
authhubRequest
AuthHubBasicRequest
This is an optional parameter and can be set to nil value.
As a developer, if you intend to customise the network request which is being sent to Authentication Hub (like adding custom header or additional request body param), then implement AHAPIRequest interface. The AuthHubBasicRequest class is the default implementation of the AHAPIRequest interface. When the initAuth() is invoked with authhubRequest as nil object, then SDK makes use of default implementation of AHAPIRequest interface that is; AuthHubBasicRequest.

Initiate Authentication

  • Use the
    initAuth
    function to initiate the authentication flow by invoking the POST
    https://<sspHost>/<tenantName>/auth/v1/authenticate
    API. Use this function at all existing places where you are invoking the
    /authenticate
    API.
    API Signature
    public func initAuth(serverHost: String, tenant: String, requestHeaders:[String:Any], authRequestParams: [String:Any], fieldsTobeEncryptedList:[String]?, completionBlock: @escaping (( _ response: AHCoreResult) -> Void)) throws
    The API parameters are described in the following table:
    Name
    Type
    Description
    serverHost
    string
    This is the Authentication Hub server host.
    tenant
    string
    This is the tenant name.
    requestHeaders
    dictionary
    The requestHeaders is the collection of Authentication Hub FIDO Server specific headers that are required for REST API calls.
    The following parameters should be passed with proper values:
    • Authorization
    authRequestParams
    dictionary
    This is a collection of parameters that are required for '/authenticate' REST API calls. The following sample parameters can be passed as a dictionary object:
    { "subject": "{{userLoginid}}", "channel": "mobile", "ipAddress": "10.10.123.124", "action":"authenticate", "rememberMe" : true, "device": { "signature": { "iaAuthData": "_v02MyUgNGgYOi88OTk0emB7ZXV9GDQ2PDshOiY9bnUcOyEwOXUYNDZ1GgZ1DXVkZQpkYApjfHUUJSU5MAIwNx48IXpgZmJ7ZmN1fR4dARgZeXU5PD4wdRIwNj46fHUWPSc6ODB6bWB7ZXthZG1me21mdQY0MzQnPHpgZmJ7ZmMpGDQ2HDshMDlzMyUmNmhmZSlkY21lKWRlYGUpZGNtZSlsYWxzMyUmImg8OyEwJzs0OXglMTN4IzwwIjAnKTg9PzM3ODEyNjM/NzclNDA6PzozOj06MDMyPDA9PzQ8KTw7ITAnOzQ5eDs0Njl4JTkgMjw7czMlJTxoczMlIS9oYHtgczMlOTtoMDt4EhcpKSlzMyU2JWhlZGRkZWRkZGRkZGRkZGRkZGRkZGRkZWRkZGRkZGRkZGRkZGVkZGRkZWRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGVkZXMzJSM2aHMzJSMmaGdzMyUhJmhzMyUhMmg=" } } }
    fieldsTobeEncryptedList
    string
    array
    • This is optional parameter and can be set to nil value.
    • The list of string array contains the list of the fields which needs encryption. This list of fields can be obtained from getFieldsToBeEncryptedInAuthFlow() API. The list of fields that are sent to initAuth() decides whether server nonce is required to encrypt field in the transit.
    completionBlock
    closure block
    Represents the closure block that the SDK passes to the calling API. The closure block returns the AHCoreResult object as a response. AHCoreResult is a struct object containing data (dictionary object), code (API response), and message (string) as members.
    The completionBlock closure returns a AHCoreResult struct object as defined here:
    public struct AHCoreResult { public init(code: Int, message: String, data: [String:Any]) { self.code = code self.message = message self.data = data } public var code : Int public var message : String public var data : [String:Any] }
  • Example: API call with Server Host and Tenant
    do { //set network request object in AuthCore ahCore.setAuthHubRequestObject(authhubRequest:hedmoralRequestObject) //get access token from server var jsonResponse = getAccessTokenFromAHServer() var accessToken = "Bearer \(jsonResponse["access_token"] as! String)" var reqHeaders = [String:Any]() reqHeaders["Authorization"] = accessToken /*get list of the fields from BrandingSettings API*/ let brandingSettingsHeaders:[String:String] = [AHConstants.HttpHeader.KeyAz:accessToken] try ahCore.getFieldsToBeEncryptedInAuthFlow(serverHost: serverHost, tenant: tenant, requestHeaders:brandingSettingsHeaders) { result in if(result.code == AHResult.Code.SUCCESS) { //On success, fetch the list of the fields which needs encryption let fieldsToBeEncrypted = result.data[AHConstants.GenericKeys.FieldsToBeEncrypted] as? [String] ?? [] //pass on the list to initAuth() try ahCore.initAuth(serverHost: serverHost, tenant: tenant, requestHeaders: reqHeaders, authRequestParams: paramBodyRequest, fieldsTobeEncryptedList:fieldsToBeEncrypted) { response in if response.data["errorCode"] != nil { let errorCode = response.data["errorCode"] as! String let code = Int(errorCode)! var errorMsg = response.data["errorMessage"] as? String ?? "" if(!errorMsg.isEmpty) { print("Error: message - \(errorMsg) and code: \(errorCode)") } } else { if let flowState = response.data["flowState"] as? String { print(flowState) } guard let nextAction = response.data["nextaction"] else { Logger().logMessage(message: "Next Action not set!!") return } //handle nevigation to next page based on response from AH server navigateToNextPageBasedOnNextAction() } } } }
    This function is used for initiating the authentication flow by invoking the POST
    https://<proxyUrl>/auth/v1/authenticate
    API. This API also supports the
    proxy URL
    configuration for the Authentication Hub instance where the tenant name is not required as part of the URL. This function should be used at all the existing places where you are invoking the
    /authenticate
    API.
    API Signature
    public func initAuth(serverUrl: String, requestHeaders:[String:Any], authRequestParams: [String:Any], fieldsTobeEncryptedList:[String]?, completionBlock: @escaping (( _ response: AHCoreResult) -> Void)) throws
    The API parameters have been described here:
    Name
    Type
    Description
    serverURL
    string
    The endpoint url that can be a proxy url for an Authentication Hub instance.
    requestHeaders
    dictionary
    The requestHeaders is the collection of Authentication Hub FIDO Server specific headers that are required for REST API calls.
    The following parameters should be passed with proper values:
    • Authorization
    authRequestParams
    dictionary
    This is a collection of parameters that are required for '/authenticate' REST API calls. The following sample parameters can be passed as a dictionary object:
    { "subject": "{{userLoginid}}", "channel": "mobile", "ipAddress": "10.10.123.124", "action":"authenticate", "rememberMe" : true, "device": { "signature": { "iaAuthData": "_v02MyUgNGgYOi88OTk0emB7ZXV9GDQ2PDshOiY9bnUcOyEwOXUYNDZ1GgZ1DXVkZQpkYApjfHUUJSU5MAIwNx48IXpgZmJ7ZmN1fR4dARgZeXU5PD4wdRIwNj46fHUWPSc6ODB6bWB7ZXthZG1me21mdQY0MzQnPHpgZmJ7ZmMpGDQ2HDshMDlzMyUmNmhmZSlkY21lKWRlYGUpZGNtZSlsYWxzMyUmImg8OyEwJzs0OXglMTN4IzwwIjAnKTg9PzM3ODEyNjM/NzclNDA6PzozOj06MDMyPDA9PzQ8KTw7ITAnOzQ5eDs0Njl4JTkgMjw7czMlJTxoczMlIS9oYHtgczMlOTtoMDt4EhcpKSlzMyU2JWhlZGRkZWRkZGRkZGRkZGRkZGRkZGRkZWRkZGRkZGRkZGRkZGVkZGRkZWRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGVkZXMzJSM2aHMzJSMmaGdzMyUhJmhzMyUhMmg=" } } }
    fieldsTobeEncryptedList
    string
    array
    • This is an optional parameter and can be set to nil.
    • The list of string array contains the list of the fields which needs encryption. This list of fields can be obtained from getFieldsToBeEncryptedInAuthFlow() API.  The list of fields sent to initAuth() decides whether server nonce is required to encrypt the fields in the transit.
    completionBlock
    closure block
    Represents the closure block that the SDK passes to the calling API. The closure block returns the AHCoreResult object as a response. AHCoreResult is a struct object containing data (dictionary object), code (API response), and message (string) as members.
    The completionBlock closure returns a AHCoreResult struct object as defined here:
    public struct AHCoreResult { public init(code: Int, message: String, data: [String:Any]) { self.code = code self.message = message self.data = data } public var code : Int public var message : String public var data : [String:Any] }
  • Example: API call with Proxy URL
    do { //set network request object in AuthCore ahCore.setAuthHubRequestObject(authhubRequest:hedmoralRequestObject) //get access token from server var jsonResponse = getAccessTokenFromAHServer() var accessToken = "Bearer \(jsonResponse["access_token"] as! String)" var reqHeaders = [String:Any]() reqHeaders["Authorization"] = accessToken /*get list of the fields from BrandingSettings API*/ let brandingSettingsHeaders:[String:String] = [AHConstants.HttpHeader.KeyAz:accessToken] try ahCore.getFieldsToBeEncryptedInAuthFlow(serverUrl: proxyUrl, requestHeaders:brandingSettingsHeaders) { result in if(result.code == AHResult.Code.SUCCESS) { //On success, fetch the list of the fields which needs encryption let fieldsToBeEncrypted = result.data[AHConstants.GenericKeys.FieldsToBeEncrypted] as? [String] ?? [] //pass on the list to initAuth() try ahCore.initAuth(serverUrl: proxyUrl, requestHeaders: reqHeaders, authRequestParams: paramBodyRequest, fieldsTobeEncryptedList:fieldsToBeEncrypted) { response in if response.data["errorCode"] != nil { let errorCode = response.data["errorCode"] as! String let code = Int(errorCode)! var errorMsg = response.data["errorMessage"] as? String ?? "" if(!errorMsg.isEmpty) { print("Error: message - \(errorMsg) and code: \(errorCode)") } } else { if let flowState = response.data["flowState"] as? String { print(flowState) } guard let nextAction = response.data["nextaction"] else { Logger().logMessage(message: "Next Action not set!!") return } //handle nevigation to next page based on response from AH server navigateToNextPageBasedOnNextAction() } } } }

Data Encryption

Authentication Hub supports "Password" (In-Transit and At-Rest) encryption and "Device Signature" (In-Transit) encryption.
Prerequisite
To use the iOS client SDK for
"Password"
and
"Device Signature"
encryption, the following prerequisites must be met.
  1. Change the value of the tenant setting,
    fieldsToBeEncryptedInAuthFlow
    to
    "Password", and/or "Device Signature".
    The default value is
    none,
    which indicates that "Password" and "Device Signature" encryption is disabled by default.
    [ { "name": "fieldsToBeEncryptedInAuthFlow", "value": "password, devicesignature" } ]
  2. Integrate the
    AuthHubCore.framework
    SDK with the iOS application. The SDK includes the APIs that can be called from the iOS application context to achieve "Password" and "Device Signature" encryption.
    The
    AuthHubCore.framework
    SDK file can be found in the VIP Authentication Hub - Customer Validation site along with other SDKs.

Get the list of fields to be encrypted in the authentication flow

  1. To get a list of the fields that are enabled for encryption, invoke
    getFieldsToBeEncryptedInAuthFlow()
    function before calling initAuth().
    public func getFieldsToBeEncryptedInAuthFlow(serverHost: String, tenant: String, requestHeaders:[String:Any], completionBlock: @escaping ( _ response: AHCoreResult) -> Void) throws
    The API parameters have been described here:
    Name
    Type
    Description
    serverHost
    string
    This is the Authentication Hub server host.
    tenant
    string
    This is the tenant name.
    requestHeaders
    dictionary
    • The requestHeaders is the collection of Authentication Hub FIDO Server specific headers that are required for for "/auth/v1/BrandingSettings" Authentication Hub REST API calls.
    • In this case, you must pass authorization request header value as reqHeaders["Authorization"] = accessToken as mandatory request header parameter.
    • Other optional custom headers can be passed as per customer requirement.
    completionBlock
    closure block
    • Represents the closure block that the SDK passes to the calling API. The closure block returns the AHCoreResult object as a response. AHCoreResult is a struct object containing data (dictionary object), code (API response), and message (string) as members.
    • The data is a dictionary object, message is a string, and the code is the API response code.
    • The result.data[AHConstants.GenericKeys.FieldsToBeEncrypted] contains list of fields(string array) [String] which can be passed on to the initAuth() API
The completionBlock closure returns an AHCoreResult object, containing a dictionary collection named "data." The result.data dictionary, comprises a key identified as AHConstants.GenericKeys.FieldsToBeEncrypted (specified in the fieldName argument of the API) and a list of fields in string array format. [String], denoting the fields requiring encryption. Currently, it may include "password," "devicesignature," or both.
do { //set network request object in AuthCore ahCore.setAuthHubRequestObject(authhubRequest:hedmoralRequestObject) //get access token from server var jsonResponse = getAccessTokenFromAHServer() var accessToken = "Bearer \(jsonResponse["access_token"] as! String)" var reqHeaders = [String:Any]() reqHeaders["Authorization"] = accessToken /*get list of the fields from BrandingSettings API*/ let brandingSettingsHeaders:[String:String] = [AHConstants.HttpHeader.KeyAz:accessToken] try ahCore.getFieldsToBeEncryptedInAuthFlow(serverHost: serverHost, tenant: tenant, requestHeaders:brandingSettingsHeaders) { result in if(result.code == AHResult.Code.SUCCESS) { //On success, fetch the list of the fields which needs encryption let fieldsToBeEncrypted = result.data[AHConstants.GenericKeys.FieldsToBeEncrypted] as? [String] ?? [] //pass on the list to initAuth() try ahCore.initAuth(serverHost: serverHost, tenant: tenant, requestHeaders: reqHeaders, authRequestParams: paramBodyRequest, fieldsTobeEncryptedList:fieldsToBeEncrypted) { response in if response.data["errorCode"] != nil { let errorCode = response.data["errorCode"] as! String let code = Int(errorCode)! var errorMsg = response.data["errorMessage"] as? String ?? "" if(!errorMsg.isEmpty) { print("Error: message - \(errorMsg) and code: \(errorCode)") } } else { if let flowState = response.data["flowState"] as? String { print(flowState) } guard let nextAction = response.data["nextaction"] else { Logger().logMessage(message: "Next Action not set!!") return } //handle nevigation to next page based on response from AH server navigateToNextPageBasedOnNextAction() } } } }

Support for proxy URL configuration to get the list of fields that are required for encryption

The following API supports the proxy Url configuration for Authentication Hub instance where tenant name is not required as part of the URL.
public func getFieldsToBeEncryptedInAuthFlow(serverUrl: String, requestHeaders:[String:Any], completionBlock: @escaping ( _ response: AHCoreResult) -> Void) throws
The API parameters have been described here:
Name
Type
Description
serverURL
string
The endpoint url that can be a proxy url for an Authentication Hub instance.
requestHeaders
dictionary
  • requestHeaders is the collection of AuthHub FIDO Server specific parameters required for "/auth/v1/BrandingSettings" AH REST call.
  • In this case, developer must pass authorization request header value as reqHeaders["Authorization"] = accessToken as mandatory request header parameter.
  • Other optional custom headers can be passed as per customer requirement.
completionBlock
closure block
  • Represents the closure block that the SDK passes to the calling API. The closure block returns the AHCoreResult object as a response.
  • AHCoreResult is a struct object containing data (dictionary object), code (API response), and message (string) as members.
  • The data is a dictionary object, message is a string, and the code is the API response code.
The completionBlock closure returns an AHCoreResult object, containing a dictionary collection named "data." The result.data dictionary, comprises a key identified as AHConstants.GenericKeys.FieldsToBeEncrypted (specified in the fieldName argument of the API) and a list of fields in string array format. [String], denoting the fields requiring encryption. Currently, it may include "password," "devicesignature," or both, as shown in the following example.
do { //set network request object in AuthCore ahCore.setAuthHubRequestObject(authhubRequest:hedmoralRequestObject) //get access token from server var jsonResponse = getAccessTokenFromAHServer() var accessToken = "Bearer \(jsonResponse["access_token"] as! String)" var reqHeaders = [String:Any]() reqHeaders["Authorization"] = accessToken /*get list of the fields from BrandingSettings API*/ let brandingSettingsHeaders:[String:String] = [AHConstants.HttpHeader.KeyAz:accessToken] try ahCore.getFieldsToBeEncryptedInAuthFlow(serverUrl: proxyUrl, requestHeaders:brandingSettingsHeaders) { result in if(result.code == AHResult.Code.SUCCESS) { //On success, fetch the list of the fields which needs encryption let fieldsToBeEncrypted = result.data[AHConstants.GenericKeys.FieldsToBeEncrypted] as? [String] ?? [] //pass on the list to initAuth() try ahCore.initAuth(serverUrl: proxyUrl, requestHeaders: reqHeaders, authRequestParams: paramBodyRequest, fieldsTobeEncryptedList:fieldsToBeEncrypted) { response in if response.data["errorCode"] != nil { let errorCode = response.data["errorCode"] as! String let code = Int(errorCode)! var errorMsg = response.data["errorMessage"] as? String ?? "" if(!errorMsg.isEmpty) { print("Error: message - \(errorMsg) and code: \(errorCode)") } } else { if let flowState = response.data["flowState"] as? String { print(flowState) } guard let nextAction = response.data["nextaction"] else { Logger().logMessage(message: "Next Action not set!!") return } //handle nevigation to next page based on response from AH server navigateToNextPageBasedOnNextAction() } } } }

Encryption Confirmation

Encryption confirmation for "Password" and "Device Signature" is described in this section.
  • "Password" Encryption Confirmation
    Call the
    isEncryptionRequiredForField
    function to check if the password field is configured for "Password" encryption.
    API Signature
    public func isEncryptionRequiredForField(serverHost: String, tenant: String, requestHeaders:[String:Any], fieldName:String, completionBlock: @escaping (( _ response: AHCoreResult) -> Void)) throws -> Bool
    Sample Code for "Password" Encryption
    //get access token from server var jsonResponse = getAccessTokenFromAHServer() var accessToken = "Bearer \(jsonResponse["access_token"] as! String)" var reqHeaders = [String:Any]() reqHeaders["Authorization"] = accessToken let ahCore = AHCore.getInstance()do { //get user password try ahCore.isEncryptionRequiredForField(serverHost: serverHost, tenant: tenant, requestHeaders:reqHeaders, fieldName: "password", completionBlock: { result in if result.data["errorCode"] != nil { let errorCode = result.data["errorCode"] as! String let code = Int(errorCode)! var errorMsg = result.data["errorMessage"] as? String ?? "" if(!errorMsg.isEmpty) { print("Error: message - \(errorMsg) and code: \(errorCode)") } handleError(errorCode, errorMsg) } do { let code = result.code let isPswdEncRequired = result.data[AHConstants.GenericKeys.PasswordField] as? Bool ?? false if(code == AHResult.Code.SUCCESS && isPswdEncRequired) { let encryptedPassword = try ahCore.encryptdData(plainText: password) if(!encryptedPassword.isEmpty) { password = encryptedPassword } } //send password authentication request to the Authentication Hub server performPasswordAuthentication(password) } catch { print(error) return } }) } catch { let message = error.localizedDescription print("Error: message - \(message)") }
  • "Device Signature" Encryption Confirmation
    Call the
    isEncryptionRequiredForField
    function to check if the device signature field is configured for encryption.
    API Signature
    public func isEncryptionRequiredForField(serverHost: String, tenant: String, requestHeaders:[String:Any], fieldName:String, completionBlock: @escaping (( _ response: AHCoreResult) -> Void)) throws -> Bool
    Sample Code for "Device Signature" Encryption
    //get access token from server var jsonResponse = getAccessTokenFromAHServer() var accessToken = "Bearer \(jsonResponse["access_token"] as! String)" var reqHeaders = [String:Any]() reqHeaders["Authorization"] = accessToken let ahCore = AHCore.getInstance()do { //get device signature from VIPIA framework try ahCore.isEncryptionRequiredForField(serverHost: serverHost, tenant: tenant, requestHeaders:reqHeaders, fieldName: "devicesignature", completionBlock: { result in if result.data["errorCode"] != nil { let errorCode = result.data["errorCode"] as! String let code = Int(errorCode)! var errorMsg = result.data["errorMessage"] as? String ?? "" if(!errorMsg.isEmpty) { print("Error: message - \(errorMsg) and code: \(errorCode)") } handleError(errorCode, errorMsg) } do { let code = result.code let isEncRequired = result.data["devicesignature"] as? Bool ?? false if(code == AHResult.Code.SUCCESS && isEncRequired) { let encryptedSignature = try ahCore.encryptdData(plainText: deviceSignature) if(!encryptedSignature.isEmpty) { deviceSignature = encryptedSignature } } //send encrypted device signature as "x-device-tag" header to the Authentication Hub server setEcryptedDeviceTagHeader(deviceSignature) } catch { print(error) return } }) } catch { let message = error.localizedDescription print("Error: message - \(message)") }

Support for
proxy URL
configuration

The Encryption API also supports the
proxy URL
configuration for the AuthHub instance where the tenant name is not required as part of the URL.
The following is an example for "Password" encryption. You can use the same API signature for "Device Signature".
API Signature
public func isEncryptionRequiredForField(serverUrl: String, requestHeaders:[String:Any] fieldName:String, completionBlock: @escaping (( _ response: AHCoreResult) -> Void)) throws -> Bool
Sample Code
: This example shows a "Password" encryption sample using a proxyURL. Similar code can be used for "Device Signature".
//get access token from server var jsonResponse = getAccessTokenFromAHServer() var accessToken = "Bearer \(jsonResponse["access_token"] as! String)" var reqHeaders = [String:Any]() reqHeaders["Authorization"] = accessToken let ahCore = AHCore.getInstance() do { //get user password try ahCore.isEncryptionRequiredForField(serverUrl: proxyUrl, requestHeaders:reqHeaders, fieldName: "password", completionBlock: { result in if result.data["errorCode"] != nil { let errorCode = result.data["errorCode"] as! String let code = Int(errorCode)! var errorMsg = result.data["errorMessage"] as? String ?? "" if(!errorMsg.isEmpty) { print("Error: message - \(errorMsg) and code: \(errorCode)") } handleError(errorCode, errorMsg) } do { let code = result.code let isPswdEncRequired = result.data[AHConstants.GenericKeys.PasswordField] as? Bool ?? false if(code == AHResult.Code.SUCCESS && isPswdEncRequired) { let encryptedPassword = try ahCore.encryptdData(plainText: password) if(!encryptedPassword.isEmpty) { password = encryptedPassword } } //send password authentication request to AH server performPasswordAuthentication(password) } catch { print(error) return } }) } catch { let message = error.localizedDescription print("Error: message - \(message)") }
Parameter Description
  • hostName:
    Specifies the SSP (
    VIP Authentication Hub
    ) server hostname. Data Type -
    string.
  • tenant:
    Specifies the tenant name. Example: default. Data Type -
    string.
  • serverUrl:
    Specifies the endpoint URL that can be a proxy URL for an Authentication Hub instance. Data Type -
    string.
    Ensure that the proxy resolves the Authentication Hub instance URL that points to the intended
    Authentication Hub
    server host and tenant.
  • requestHeaders:
    Represents a collection of
    VIP Authentication Hub
    server-specific headers that are required for the REST API calls. The mandatory parameter to be passed is the Authorization header containing
    "Bearer <auth_token>".
    Data Type -
    dictionary.
  • fieldName:
    Specifies the field name that is marked for password encryption. The value of this parameter must be
    password.
  • completionBlock:
    Represents the closure block that the SDK passes to the calling API. The closure block returns the AHCoreResult object as a response. AHCoreResult is a struct object containing data (dictionary object), code (API response), and message (string) as members. The result.data dictionary contains the key as the field name (password) and boolean data (true, false) as a value. The value
    true
    indicates that the password field must be encrypted.

Encrypt "Password" and "Device Signature"

  • Encrypt Password
    To encrypt the plain password with the tenant-level public key
    without
    server nonce, call the
    encryptDataWithPublicKey
    function:
    API Signature
    public func encryptDataWithPublicKey(plainText: String) throws -> String
    To encrypt the plain password with the tenant-level public key
    along with
    server nonce, call the
    encryptData
    function:
    API Signature
    public func encryptData(plainText: String) throws -> String
    Parameter Description
    • plainText:
      Specifies the password string that must be encrypted in the authentication flow.
    API Response
    The API encrypts the plain text and returns the encrypted value as a base64 encoded string. The encrypted password can be sent to the
    VIP Authentication Hub
    where password encryption is enabled for authentication. For server-side information, see Password Encryption.
  • Encrypt "Device Signature"
    To encrypt the plain "Device Signature" with symmetric key, call the
    encryptDataWithSymmetricKey
    function:
    API Signature
    public func encryptDataWithSymmetricKey(plainText: String) throws -> String
    Parameter Description
    • plainText:
      Specifies the "Device Signature", "X-Device-Tag" string that must be encrypted in the authentication flow.
    API Response
    The API encrypts the plain text and returns the encrypted value in a base64 encoded string. The encrypted device signature and x-device-tag can be sent to the
    VIP Authentication Hub
    as an encrypted data. For server-side information, see "Device Signature" Encryption.