diff --git a/Cidaas.podspec b/Cidaas.podspec index 71faee0..d12195d 100644 --- a/Cidaas.podspec +++ b/Cidaas.podspec @@ -8,7 +8,7 @@ Pod::Spec.new do |s| s.name = 'Cidaas' - s.version = '1.1.0' + s.version = '1.1.0.1' s.summary = 'Native SDK for iOS providing login, registration and verification functionalities' s.homepage = 'https://github.com/Cidaas/cidaas-sdk-ios-v2' s.license = { :type => 'MIT', :file => 'LICENSE' } diff --git a/Cidaas/Classes/Core/Controllers/Repository/Login/LoginController.swift b/Cidaas/Classes/Core/Controllers/Repository/Login/LoginController.swift index 7b71e68..d9e3674 100644 --- a/Cidaas/Classes/Core/Controllers/Repository/Login/LoginController.swift +++ b/Cidaas/Classes/Core/Controllers/Repository/Login/LoginController.swift @@ -13,7 +13,7 @@ public class LoginController { // shared instance public static var shared : LoginController = LoginController() - public var delegate: UIViewController = UIViewController() + public var delegate: UIViewController! public var storage: TransactionStore = TransactionStore.shared // constructor @@ -36,8 +36,6 @@ public class LoginController { return } - self.delegate = delegate - // construct url let loginURL = constructURL(properties: properties) let redirectURL = URL(string: properties["RedirectURL"] ?? "")! @@ -51,12 +49,44 @@ public class LoginController { self.storage.store(session) } else { - + self.delegate = delegate // call open safari method openSafari(loginURL : loginURL) } + } + + // login With social + public func loginWithSocial(provider: String, requestId: String, delegate: UIViewController, properties: Dictionary, callback: @escaping(Result) -> Void) { + // null check + if properties["DomainURL"] == "" || properties["DomainURL"] == nil || properties["ClientId"] == "" || properties["ClientId"] == nil || properties["RedirectURL"] == "" || properties["RedirectURL"] == nil { + let error = WebAuthError.shared.propertyMissingException() + // log error + let loggerMessage = "Read properties failure : " + "Error Code - " + String(describing: error.errorCode) + ", Error Message - " + error.errorMessage + ", Status Code - " + String(describing: error.statusCode) + logw(loggerMessage, cname: "cidaas-sdk-error-log") + + DispatchQueue.main.async { + callback(Result.failure(error: error)) + } + return + } + // construct url + let loginURL = constructSocialURL(provider: provider, requestId: requestId, properties: properties) + let redirectURL = URL(string: properties["RedirectURL"] ?? "")! + if #available(iOS 11.0, *) { + + // initiate safari session with the constructed url performing single sign on + let session = SafariAuthenticationSession(loginURL: loginURL, redirectURL: redirectURL, callback: callback) + + // save the session + self.storage.store(session) + } + else { + self.delegate = delegate + // call open safari method + openSafari(loginURL : loginURL) + } } // open safari browser. This method opens the Safari browser to display the login page. This method should be called internally and only for lower versions of ios (below 11.0) @@ -64,12 +94,12 @@ public class LoginController { // assign url to safari controller let vc = SFSafariViewController(url: loginURL) - + // present the safari controller self.delegate.present(vc, animated: true, completion: nil) } - private func constructURL(properties: Dictionary) -> URL { + public func constructURL(properties: Dictionary) -> URL { var urlParams = Dictionary() urlParams["redirect_uri"] = properties["RedirectURL"] ?? "" @@ -78,13 +108,31 @@ public class LoginController { urlParams["view_type"] = properties["ViewType"] ?? "login" urlParams["code_challenge"] = properties["Challenge"] urlParams["code_challenge_method"] = properties["Method"] + urlParams["nonce"] = UUID.init().uuidString var urlComponents = URLComponents(string : properties["AuthorizationURL"] ?? "") urlComponents?.queryItems = [] + for (key, value) in urlParams { urlComponents?.queryItems?.append(URLQueryItem(name: key, value: value)) } + for(key, value) in Cidaas.shared.extraParams { + urlComponents?.queryItems?.append(URLQueryItem(name: key, value: value)) + } + + return (urlComponents?.url)! + } + + public func constructSocialURL(provider: String, requestId: String, properties: Dictionary) -> URL { + + let baseURL = (properties["DomainURL"]) ?? "" + + // construct url + let urlString = baseURL + URLHelper.shared.getSocialLoginURL(provider: provider, requestId: requestId) + + let urlComponents = URLComponents(string : urlString) + return (urlComponents?.url)! } diff --git a/Cidaas/Classes/Core/Helpers/General/URLHelper.swift b/Cidaas/Classes/Core/Helpers/General/URLHelper.swift index ff8005f..f230913 100644 --- a/Cidaas/Classes/Core/Helpers/General/URLHelper.swift +++ b/Cidaas/Classes/Core/Helpers/General/URLHelper.swift @@ -118,6 +118,7 @@ public class URLHelper { public var denyRequestURL = "/verification-srv/notification/reject" public var updateFCMTokenURL = "/devices-srv/device/updatefcm" public var pendingNotificationListURL = "/verification-srv/notification/initiated" + public var socialLoginURL = "/login-srv/social/login/" public func getRequestIdURL() -> String { return requestIdURL @@ -171,6 +172,10 @@ public class URLHelper { return consentURL + "?consent_name=" + consent_name + "&version=" + String(version) } + public func getSocialLoginURL(provider: String, requestId: String) -> String { + return socialLoginURL + provider + "/" + requestId + } + public func getConsentDetailsURL(consent_name: String) -> String { return consentDetailsURL + "?name=" + consent_name } diff --git a/Cidaas/Classes/Core/Helpers/Session/AuthSession.swift b/Cidaas/Classes/Core/Helpers/Session/AuthSession.swift index 57835b8..cb1d4d5 100644 --- a/Cidaas/Classes/Core/Helpers/Session/AuthSession.swift +++ b/Cidaas/Classes/Core/Helpers/Session/AuthSession.swift @@ -21,10 +21,12 @@ public class AuthSession: NSObject, OAuthTransactionDelegate { } public func resume(_ url: URL, options: [UIApplicationOpenURLOptionsKey: Any] = [:]) -> Bool { + Cidaas.shared.handleToken(url: url) return true } public func cancel() { // return error + self.callback(Result.failure(error: WebAuthError.shared.userCancelledException())) } } diff --git a/Cidaas/Classes/Core/Helpers/Session/SafariAuthenticationSession.swift b/Cidaas/Classes/Core/Helpers/Session/SafariAuthenticationSession.swift index 54595d3..b9b9a59 100644 --- a/Cidaas/Classes/Core/Helpers/Session/SafariAuthenticationSession.swift +++ b/Cidaas/Classes/Core/Helpers/Session/SafariAuthenticationSession.swift @@ -20,9 +20,9 @@ public class SafariAuthenticationSession : AuthSession { self.authSession = SFAuthenticationSession(url: self.loginURL, callbackURLScheme: self.redirectURL.absoluteString, completionHandler: { (resultURL, resultError) in guard resultError == nil, let callbackURL = resultURL else { if case SFAuthenticationError.canceledLogin = resultError! { - // return error + callback(Result.failure(error: WebAuthError.shared.userCancelledException())) } else { - // return error + callback(Result.failure(error: WebAuthError.shared.userCancelledException())) } return TransactionStore.shared.clear() } diff --git a/Cidaas/Classes/Core/Views/Cidaas.swift b/Cidaas/Classes/Core/Views/Cidaas.swift index 29f5803..c89ec92 100644 --- a/Cidaas/Classes/Core/Views/Cidaas.swift +++ b/Cidaas/Classes/Core/Views/Cidaas.swift @@ -25,7 +25,9 @@ public class Cidaas { var storage: TransactionStore var timer = Timer() var trackingManager: TrackingManager! - public var browserCallback: ((Result) -> ())! + var browserCallback: ((Result) -> ())! + var propertyFileRead: Bool = false + public var extraParams: Dictionary = Dictionary() // static variables public static var intermediate_verifiation_id: String = "" @@ -115,6 +117,7 @@ public class Cidaas { // log success let loggerMessage = "Saved Property status : \(response)" logw(loggerMessage, cname: "cidaas-sdk-success-log") + self.propertyFileRead = true break } } @@ -187,12 +190,92 @@ public class Cidaas { } } +// -------------------------------------------------------------------------------------------------- // + + // login with social + public func loginWithSocial(provider: String, requestId: String, delegate: UIViewController, callback: @escaping (Result) -> Void) { + let savedProp = DBHelper.shared.getPropertyFile() + if (savedProp != nil) { + self.browserCallback = callback + LoginController.shared.loginWithSocial(provider: provider, requestId: requestId, delegate: delegate, properties: savedProp!, callback: callback) + } + else { + // log error + let loggerMessage = "Read properties file failure : " + "Error Code - 10001, Error Message - File not found, Status Code - 404" + logw(loggerMessage, cname: "cidaas-sdk-error-log") + + let error = WebAuthError.shared.fileNotFoundException() + + // return failure callback + DispatchQueue.main.async { + callback(Result.failure(error: error)) + } + return + } + } + +// -------------------------------------------------------------------------------------------------- // + + // get login url + public func getLoginURL(callback: @escaping (Result) -> Void) { + var savedProp = DBHelper.shared.getPropertyFile() + if (savedProp != nil) { + savedProp?["ViewType"] = "login" + callback(Result.success(result: LoginController.shared.constructURL(properties: savedProp!))) + } + else { + // log error + let loggerMessage = "Read properties file failure : " + "Error Code - 10001, Error Message - File not found, Status Code - 404" + logw(loggerMessage, cname: "cidaas-sdk-error-log") + + let error = WebAuthError.shared.fileNotFoundException() + + // return failure callback + DispatchQueue.main.async { + callback(Result.failure(error: error)) + } + return + } + } + +// -------------------------------------------------------------------------------------------------- // + + // get register url + public func getRegistrationURL(callback: @escaping (Result) -> Void) { + var savedProp = DBHelper.shared.getPropertyFile() + if (savedProp != nil) { + savedProp?["ViewType"] = "register" + callback(Result.success(result: LoginController.shared.constructURL(properties: savedProp!))) + } + else { + // log error + let loggerMessage = "Read properties file failure : " + "Error Code - 10001, Error Message - File not found, Status Code - 404" + logw(loggerMessage, cname: "cidaas-sdk-error-log") + + let error = WebAuthError.shared.fileNotFoundException() + + // return failure callback + DispatchQueue.main.async { + callback(Result.failure(error: error)) + } + return + } + } + // -------------------------------------------------------------------------------------------------- // // handle token public func handleToken(url: URL) { - let code = url.valueOf("code") ?? "" - AccessTokenController.shared.getAccessToken(code: code, callback: browserCallback!) + if LoginController.shared.delegate != nil { + LoginController.shared.delegate.dismiss(animated: true, completion: nil) + } + + if browserCallback != nil { + let code = url.valueOf("code") ?? "" + if code != "" { + AccessTokenController.shared.getAccessToken(code: code, callback: browserCallback!) + } + } } // -------------------------------------------------------------------------------------------------- // @@ -2535,7 +2618,7 @@ public class Cidaas { // 2. Call getPendingNotifications method // 3. Maintain logs based on flags - public func getPendingNotifications(sub: String, fcmId: String, callback: @escaping(Result) -> Void) { + public func getPendingNotifications(sub: String, callback: @escaping(Result) -> Void) { let savedProp = DBHelper.shared.getPropertyFile() if (savedProp != nil) { diff --git a/Example/Cidaas/AppDelegate.swift b/Example/Cidaas/AppDelegate.swift index f811bc0..8c8e8d3 100644 --- a/Example/Cidaas/AppDelegate.swift +++ b/Example/Cidaas/AppDelegate.swift @@ -16,7 +16,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. -// Cidaas.shared.ENABLE_LOG = true + Cidaas.shared.ENABLE_LOG = true return true } @@ -31,6 +31,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { return true } + func applicationWillResignActive(_ application: UIApplication) { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. diff --git a/Example/Cidaas/Info.plist b/Example/Cidaas/Info.plist index 96f70dd..abf8aa4 100644 --- a/Example/Cidaas/Info.plist +++ b/Example/Cidaas/Info.plist @@ -23,9 +23,13 @@ CFBundleURLTypes + CFBundleTypeRole + Editor + CFBundleURLName + com.cidaas.sdk.demo CFBundleURLSchemes - fb1889502804712451 + com.cidaas.sdk.demo @@ -52,7 +56,7 @@ Location in foreground UIBackgroundModes - remote-notification + fetch UILaunchStoryboardName LaunchScreen diff --git a/Example/Cidaas/ViewController.swift b/Example/Cidaas/ViewController.swift index b91ae22..f878d42 100644 --- a/Example/Cidaas/ViewController.swift +++ b/Example/Cidaas/ViewController.swift @@ -11,11 +11,14 @@ import Cidaas class ViewController: UIViewController { + var requestId: String = "" // did load override func viewDidLoad() { super.viewDidLoad() - + var dict = Dictionary() + dict["scope"] = "openid email profile offline_access" + Cidaas.shared.extraParams = dict } // did receive memory warning @@ -24,17 +27,46 @@ class ViewController: UIViewController { } @IBAction func loginAction(_ sender: Any) { - Cidaas.shared.loginWithBrowser(delegate: self) { + + Cidaas.shared.getRequestId() { switch $0 { - case .failure(let errorResponse): - print(errorResponse.errorMessage) - break - case .success(let successResponse): - print(successResponse.data.access_token) - break + case .success(let resultURL): + print(resultURL.data.requestId) + self.requestId = resultURL.data.requestId + + Cidaas.shared.loginWithSocial(provider: "facebook", requestId: self.requestId, delegate: self) { + switch $0 { + case .success(let loginSuccessResponse): + print(loginSuccessResponse.data.access_token) + break + case .failure(let loginErrorResponse): + print(loginErrorResponse.errorMessage) + break + } + } + + break + case .failure(let errorResponse): + print(errorResponse.errorMessage) + break } } +// Cidaas.shared.loginWithBrowser(delegate: self) { +// switch $0 { +// case .failure(let errorResponse): +// print(errorResponse.errorMessage) +// break +// case .success(let successResponse): +// let alert = UIAlertController(title: "Access Token", message: "\(successResponse.data.access_token)", preferredStyle: .alert) +// alert.addAction(UIAlertAction(title: "Done", style: .default, handler: nil)) +// self.present(alert, animated: true, completion: nil) +// break +// } +// } + +// guard let url = URL(string: "https://stackoverflow.com") else { return } +// UIApplication.shared.open(url) + } } - diff --git a/Example/Cidaas_Example.entitlements b/Example/Cidaas_Example.entitlements index f5214aa..407852c 100644 --- a/Example/Cidaas_Example.entitlements +++ b/Example/Cidaas_Example.entitlements @@ -4,7 +4,7 @@ com.apple.developer.associated-domains - webcredentials:example.com + applinks:nightlybuild.cidaas.de diff --git a/README.md b/README.md index 2c90a89..1435648 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # cidaas-sdk-ios-v2 -[![Build Status](https://travis-ci.org/Cidaas/cidaas-sdk-ios-v2.svg?branch=development)](https://travis-ci.org/Cidaas/cidaas-sdk-ios-v2) -[![codecov.io](https://codecov.io/gh/Cidaas/cidaas-sdk-ios-v2/branch/development/graphs/badge.svg)](https://codecov.io/gh/Cidaas/cidaas-sdk-ios-v2/branch/development) +[![Build Status](https://travis-ci.org/Cidaas/cidaas-sdk-ios-v2.svg?branch=master)](https://travis-ci.org/Cidaas/cidaas-sdk-ios-v2) +[![codecov.io](https://codecov.io/gh/Cidaas/cidaas-sdk-ios-v2/branch/master/graphs/badge.svg)](https://codecov.io/gh/Cidaas/cidaas-sdk-ios-v2/branch/master) [![Swift support](https://img.shields.io/badge/Swift-3.3%20%7C%204.0%20%7C%204.1-lightgrey.svg?colorA=28a745&colorB=4E4E4E)](#swift-versions-support) [![XCode support](https://img.shields.io/badge/Xcode-9.4-lightgrey.svg?colorA=28a745&colorB=4E4E4E)](#swift-versions-support) [![CocoaPods Compatible](https://img.shields.io/cocoapods/v/Cidaas.svg?style=flat&label=CocoaPods&colorA=28a745&&colorB=4E4E4E)](https://cocoapods.org/pods/Cidaas) @@ -8,25 +8,124 @@ The steps here will guide you through setting up and managing authentication and authorization in your apps using cidaas SDK. -### Requirements +## Table of Contents + + +* [Requirements](#requirements) +* [Installation](#installation) +* [Getting started](#getting-started) +* [Getting Client Id and urls](#getting-client-id-and-urls) +* [Initialisation](#initialisation) +* [Usage](#usage) + + * [Native Browser Login](#native-browser-login) + + * [Classic Login](#classic-login) + * [Social Login](#social-login) + + * [Pure Native UI Integration](#pure-native-ui-integration) + + * [Getting RequestId](#getting-request-id) + * [Getting Tenant Information](#getting-tenant-info) + * [Getting Client Information](#getting-client-info) + * [Registration](#registration) + + * [Getting Registration Fields](#getting-registration-fields) + * [Register user](#register-user) + + * [De-duplication](#de-duplication) + + * [Get Deduplication Details](#get-deduplication-details) + * [Register user](#register-user-1) + * [Login With Deduplication](#login-with-deduplication) + + * [Account Verification](#account-verification) + + * [Initiate Email verification](#initiate-email-verification) + * [Initiate SMS verification](#initiate-sms-verification) + * [Initiate IVR verification](#initiate-ivr-verification) + * [Verify Account](#verify-account) + + + * [Login](#login) + + * [Login with credentials](#login-with-credentials) + + * [Forgot Password](#forgot-password) + + * [Initiate Reset Password](#initiate-reset-password) + * [Handle Reset Password](#handle-reset-password) + * [Reset Password](#reset-password) + + * [Passwordless or Multifactor Authentication ](#passwordless-or-multifactor-authentication) + + * [Email](#email) + + * [Configuration](#configure-email) + + * [Configure Email](#configure-email) + * [Enroll Email](#enroll-email) + + * [Usage](#login-via-email) + + * [Login via Email](#login-via-email) + * [Verify Email](#verify-email) + + + * [SMS](#sms) + + * [Configuration](#configure-sms) + + * [Configure SMS](#configure-sms) + * [Enroll SMS](#enroll-sms) + + * [Usage](#login-via-sms) + + * [Login via SMS](#login-via-sms) + * [Verify SMS](#verify-sms) + + + * [IVR](#ivr) + + * [Configuration](#configure-ivr) + + * [Configure IVR](#configure-ivr) + * [Enroll IVR](#enroll-ivr) + + * [Usage](#login-via-ivr) + + * [Login via IVR](#login-via-ivr) + * [Verify IVR](#verify-ivr) + + + * [Backupcode](#backupcode) + + * [Configuration](#configure-backupcode) + + * [Configure Backupcode](#configure-backupcode) + + * [Usage](#login-via-backupcode) + + + + + +#### Requirements Operating System | Xcode | Swift --- | --- | --- iOS 10.0 or above | 9.0 or above | 3.3 or above -### Steps for integrate native iOS SDKs: #### Installation -##### CocoaPods Installations - Cidaas is available through [CocoaPods](https://cocoapods.org/pods/Cidaas). To install it, simply add the following line to your Podfile: ``` -pod 'Cidaas', '~> 0.0.1' +pod 'Cidaas' ``` #### Getting started -The following steps are to be followed to use this Cidaas-SDK. +The following steps are to be followed to use this cidaas SDK. Create a plist file named as cidaas.plist and fill all the inputs in key value pair. The inputs are below mentioned. @@ -66,12 +165,66 @@ or use the shared instance var cidaas = Cidaas.shared ``` -### Usage +#### Usage -#### Getting Request Id -You have to first get RequestId and use this in your subsequent calls. Server provides a unique Id based on urls configured for your application. Henceforth, in all requests like login, registration, you have to pass requestId, which is utilized to identify your client between two consecutive independant calls. To get the requestId, call +#### Native Browser Login +#### Classic Login +You can login using your native browser and redirects to the App once successfully logged in. To login with your native browser call ****loginWithBrowser()****. + +```swift +cidaas.loginWithBrowser(delegate: self) { + switch $0 { + case .success(let successResponse): + // your success code here + break + case .failure(let error): + // your failure code here + break + } +} +``` + +#### Social Login +You can also perform social login using your native browser and redirects to the App once successfully logged in. To perform social login call ****loginWithSocial()****. + +```swift +cidaas.loginWithSocial(provider: "your_social_provider", requestId: "your_request_id", delegate: self) { + switch $0 { + case .success(let successResponse): + // your success code here + break + case .failure(let error): + // your failure code here + break + } +} +``` +where social provider may be either facebook, google, linkedin or any other providers and requestId can be get from [Getting RequestId](#getting-request-id) + +Use [customScheme](https://developer.apple.com/documentation/uikit/core_app/communicating_with_other_apps_using_custom_urls#2928963) or [universalLinks](https://developer.apple.com/library/content/documentation/General/Conceptual/AppSearch/UniversalLinks.html) to return back the control from browser to App. -****getRequestId()****. +If you use custom scheme, configure your URL types and resume the SDK from AppDelegate's **open url** method + +```swift +func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool { + Cidaas.shared.handleToken(url: url) + return true +} +``` + +If you use universal links, configure your Domain setup and resume the SDK from AppDelegate's **userActivity** method + +```swift +func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool { + let url = userActivity.webpageURL! + Cidaas.shared.handleToken(url: url) + return true +} +``` +#### Pure Native UI Integration + +#### Getting Request Id +You have to first get RequestId and use this in your subsequent calls. Server provides a unique Id based on urls configured for your application. Henceforth, in all requests like login, registration, you have to pass requestId, which is utilized to identify your client between two consecutive independant calls. To get the requestId, call ****getRequestId()****. ```swift cidaas.getRequestId() { @@ -136,7 +289,7 @@ cidaas.getTenantInfo() { } ``` -#### Get Client Info +#### Getting Client Info Once you get tenant information, if you need to find client information you can call following method. It contains client name, logo url specified for the client in the Admin's Apps section and details of what all social providers are configured for the App. To get the client information, call ****getClientInfo()****. @@ -299,9 +452,7 @@ Once registering is done, you can verify your account either by Email, SMS or IV #### Initiate Email verification -This method is to be used when you want to receive a verification code via Email: - -**initiateEmailVerification()**. +This method is to be used when you want to receive a verification code via Email, cal l**initiateEmailVerification()**. ```swift cidaas.initiateEmailVerification(requestId:"45a921cf-ee26-46b0-9bf4-58636dced99f", sub:"7dfb2122-fa5e-4f7a-8494-dadac9b43f9d") { @@ -573,7 +724,7 @@ cidaas.configureEmail(sub: "7dfb2122-fa5e-4f7a-8494-dadac9b43f9d") { } ``` -#### Verify Email by entering code +#### Enroll Email Once you received your verification code via Email, you need to verify that code. For that verification, call **enrollEmail()**. @@ -637,7 +788,7 @@ cidaas.loginWithEmail(passwordlessEntity: passwordlessEntity) { } ``` -#### Verify Email by entering code +#### Verify Email Once you received your verification code via Email, you need to verify the code. For that verification, call **verifyEmail()**. @@ -703,7 +854,7 @@ To receive a verification code via SMS, call **configureSMS()**. } ``` -#### Verify SMS by entering code +#### Enroll SMS Once you received your verification code via SMS, you need to verify the code. For that verification, call **enrollSMS()**. @@ -767,7 +918,7 @@ cidaas.loginWithSMS(passwordlessEntity: passwordlessEntity) { } ``` -#### Verify SMS by entering code +#### Verify SMS Once you received your verification code via SMS, you need to verify the code. For that verification, call **verifySMS()**. @@ -834,7 +985,7 @@ cidaas.configureIVR(sub: "7dfb2122-fa5e-4f7a-8494-dadac9b43f9d") { } ``` -#### Verify IVR by entering code +#### Enroll IVR Once you received your verification code via IVR verification call, you need to verify the code. For that verification, call **enrollIVR()**. @@ -898,7 +1049,7 @@ cidaas.loginWithIVR(passwordlessEntity: passwordlessEntity){ } ``` -#### Verify IVR by entering code +#### Verify IVR Once you received your verification code via IVR, you need to verify the code. For that verification, call **verifyIVR()**. @@ -1617,7 +1768,7 @@ cidaas.registerUser(track_id:"45a921cf-ee26-46b0-9bf4-58636dced99f") { While registering user, if system found similar users already registered,that list is shown to user. User can decide whether to use one of the existing logins, or choose to ignore all shown details. ****loginWithDeduplication()**** method can be called to use one of those existing logins shown by the system. Note that, System will still use the secure authentication and verifications that were setup for earlier user, before login. ```swift -cidaas.loginWithDeduplication(track_id:"45a921cf-ee26-46b0-9bf4-58636dced99f") { +cidaas.loginWithDeduplication(requestId:"45a921cf-ee26-46b0-9bf4-58636dced99f", "sub": "51701ec8-f2d7-4361-a727-f8df476a711a", "password": "123456") { switch $0 { case .success(let loginWithSuccess): // your success code here