diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f91e3f..e149422 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +5.8.0 Release notes (2023-04-20) +============================================================= + +### Enhancements +* Added FaceID helper in the LoginRadius SDK for authentication through facial recognition. + For detailed information on FaceID, please refer to the following document: + https://developer.apple.com/documentation/localauthentication/logging_a_user_into_your_app_with_face_id_or_touch_id + + 5.7.0 Release notes (2022-12-27) ============================================================= diff --git a/Example/ObjCDemo/ObjCDemo/ViewController.m b/Example/ObjCDemo/ObjCDemo/ViewController.m index d7bbfee..2055a8f 100755 --- a/Example/ObjCDemo/ObjCDemo/ViewController.m +++ b/Example/ObjCDemo/ObjCDemo/ViewController.m @@ -11,6 +11,7 @@ #import "DetailViewController.h" #import "XLFormViewControllerExtension.h" #import "AppDelegate.h" +#import @interface ViewController () @property ( nonatomic, nullable) BOOL *isEmailAvailable; @@ -210,11 +211,11 @@ - (void) setupForm //Social Login Section if(![[[LoginRadiusSDK sharedInstance] session] isLoggedIn]) { - section = [XLFormSectionDescriptor formSectionWithTitle:@"Touch ID"]; + section = [XLFormSectionDescriptor formSectionWithTitle:@"Touch / Face ID"]; [form addFormSection:section]; - row = [XLFormRowDescriptor formRowDescriptorWithTag:@"TouchID" rowType:XLFormRowDescriptorTypeButton title:@"Touch ID"]; - row.action.formSelector = @selector(showTouchIDLogin); + row = [XLFormRowDescriptor formRowDescriptorWithTag:@"Touch / Face ID" rowType:XLFormRowDescriptorTypeButton title:@"Touch / Face ID"]; + row.action.formSelector = @selector(biometryType); [section addFormRow:row]; } @@ -573,14 +574,64 @@ - (void) showTouchIDLogin { [[LRTouchIDAuth sharedInstance] localAuthenticationWithFallbackTitle:@"" completion:^(BOOL success, NSError *error) { if (success) { + [self showAlert:@"Success" message:@"Successfully Authenticated"]; NSLog(@"successfully authenticated with touch id"); [self showProfileController]; } else { + [self showAlert:@"Error" message:error.description]; NSLog(@"Error: %@", [error description]); } }]; } +- (void) showFaceIDLogin +{ + [[LRFaceIDAuth sharedInstance]localAuthenticationWithFallbackTitle:@"" completion:^(BOOL success, NSError *error) { + if (success){ + [self showAlert:@"Success" message:@"Successfully Authenticated"]; + NSLog(@"Successfully authenticated with Face ID"); + [self showProfileController]; + }else{ + [self showAlert:@"Error" message:error.description]; + NSLog(@"Error: %@", [error description]); + } + }]; +} + +- (void) biometryType +{ + LAContext *laContext = [[LAContext alloc] init]; + + NSError *error; + + if ([laContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]) { + + if (error != NULL) { + NSLog(error.description); + } else { + + if (@available(iOS 11.0.1, *)) { + if (laContext.biometryType == LABiometryTypeFaceID) { + //localizedReason = "Unlock using Face ID" + [self showFaceIDLogin]; + NSLog(@"FaceId support"); + + } else if (laContext.biometryType == LABiometryTypeTouchID) { + //localizedReason = "Unlock using Touch ID" + [self showTouchIDLogin]; + NSLog(@"TouchId support"); + + } else { + //localizedReason = "Unlock using Application Passcode" + NSLog(@"No Biometric support"); + } + + } + } + } +} + + - (void) errorMessage:(NSDictionary *)data error: (NSError *) error{ diff --git a/Example/SwiftDemo/SwiftDemo/ViewController.swift b/Example/SwiftDemo/SwiftDemo/ViewController.swift index bb135ff..a451501 100755 --- a/Example/SwiftDemo/SwiftDemo/ViewController.swift +++ b/Example/SwiftDemo/SwiftDemo/ViewController.swift @@ -10,6 +10,7 @@ import LoginRadiusSDK import Eureka import SwiftyJSON import AuthenticationServices +import LocalAuthentication /* Google Native SignIn import GoogleSignIn @@ -363,16 +364,16 @@ class ViewController: FormViewController if !LoginRadiusSDK.sharedInstance().session.isLoggedIn { - form +++ Section("Touch ID") + form +++ Section("Touch / Face ID") { - $0.tag = "Touch ID" + $0.tag = "Touch / Face ID" } - <<< ButtonRow ("Touch ID") + <<< ButtonRow ("Touch / Face ID") { $0.title = $0.tag }.onCellSelection{ row,arg in - self.showTouchIDLogin() + self.biometryType() } } @@ -852,6 +853,57 @@ class ViewController: FormViewController }) } + func showFaceIDLogin() + { + LRFaceIDAuth.sharedInstance().localAuthentication(withFallbackTitle: " ", completion: { + (success, error) in + if let err = error{ + self.showAlert(title: "ERROR", message: err.localizedDescription) + }else{ + self.showAlert(title: "SUCCESS", message:"Valid User") + print("Face ID authentication successfull") + self.showProfileController() + } + }) + } + + + func biometryType() + { + + let context = LAContext() + + var error: NSError? + + if context.canEvaluatePolicy( + LAPolicy.deviceOwnerAuthenticationWithBiometrics, + error: &error) { + if (error != nil) { + print(error?.description) + } else { + + if #available(iOS 11.0.1, *) { + if (context.biometryType == .faceID) { + //localizedReason = "Unlock using Face ID" + self.showFaceIDLogin() + + print("Face ID supports") + + } else if (context.biometryType == .touchID) { + //localizedReason = "Unlock using Touch ID" + self.showTouchIDLogin() + print("TouchId support") + + } else { + //localizedReason = "Unlock using Application Passcode" + print("No Biometric support") + } + + } + } + } + + } func errorAlert(data:[AnyHashable:Any]?, error:Error ) { diff --git a/LoginRadiusSDK.podspec b/LoginRadiusSDK.podspec index 8670285..73011f7 100755 --- a/LoginRadiusSDK.podspec +++ b/LoginRadiusSDK.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = 'LoginRadiusSDK' -s.version = '5.7.0' +s.version = '5.8.0' s.summary = 'Official LoginRadius SDK for iOS to integrate User Registration Service or Social Login in your app.' s.description = <<-DESC diff --git a/README.md b/README.md index a1bd50b..6fa3710 100755 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ target 'TargetName' do #Comment the next line if you don't want to use dynamic frameworks use_frameworks! -pod 'LoginRadiusSDK', '~> 5.7.0' +pod 'LoginRadiusSDK', '~> 5.8.0' end ``` diff --git a/Sources/FaceID/LRFaceIDAuth.h b/Sources/FaceID/LRFaceIDAuth.h new file mode 100644 index 0000000..f290056 --- /dev/null +++ b/Sources/FaceID/LRFaceIDAuth.h @@ -0,0 +1,30 @@ +// +// LRFaceIDAuth.h +// Pods +// +// Created by Megha Agarwal on 15/12/22. +// + +#import +#import "LoginRadiusSDK.h" + + + +@interface LRFaceIDAuth : NSObject + +#pragma mark - Init + +/** + * Initializer + * @return singleton instance + */ ++ (instancetype)sharedInstance; + + + +- (void)localAuthenticationWithFallbackTitle:(NSString *)localizedFallbackTitle + completion:(LRServiceCompletionHandler)handler; + +@end + + diff --git a/Sources/FaceID/LRFaceIDAuth.m b/Sources/FaceID/LRFaceIDAuth.m new file mode 100644 index 0000000..f24829a --- /dev/null +++ b/Sources/FaceID/LRFaceIDAuth.m @@ -0,0 +1,58 @@ +// +// LRFaceIDAuth.m +// Pods +// +// Created by Megha Agarwal on 15/12/22. +// + +#import "LRFaceIDAuth.h" +#import +#import "LRErrors.h" +#import "LoginRadiusError.h" +#import "LoginRadiusSDK.h" + +@implementation LRFaceIDAuth + ++ (instancetype)sharedInstance { + static dispatch_once_t onceToken; + static LRFaceIDAuth *instance; + + dispatch_once(&onceToken, ^{ + instance = [[LRFaceIDAuth alloc] init]; + }); + + return instance; +} + + +- (void)localAuthenticationWithFallbackTitle:(NSString *)localizedFallbackTitle + completion:(LRServiceCompletionHandler)handler{ + + LAContext *context = [[LAContext alloc] init]; + NSError *error = nil; + + if ([context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]) { + // Authenticate User + context.localizedFallbackTitle = localizedFallbackTitle; + + [context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics + localizedReason:@"Use FaceID to Authenticate" + reply:^(BOOL success, NSError *error) { + + if (error) { + handler(NO, error); + } + if (success) { + handler(YES, nil); + } else { + handler(NO, [LRErrors faceIDNotDeviceOwner]); + } + }]; + + } else { + NSError *error = [LRErrors faceIDNotAvailable]; + handler(NO, error); + } +} + +@end diff --git a/Sources/Helper/LRErrorCode.h b/Sources/Helper/LRErrorCode.h index a635040..b0db947 100755 --- a/Sources/Helper/LRErrorCode.h +++ b/Sources/Helper/LRErrorCode.h @@ -104,6 +104,13 @@ typedef NS_ENUM(NSInteger, LRErrorCode) { * TouchID error */ LRErrorCodeTouchIDNotAvailable, + /** + * User is not verified + */ + /** + * FaceID error + */ + LRErrorCodeFaceIDNotAvailable, /** * User is not verified */ diff --git a/Sources/Helper/LRErrors.h b/Sources/Helper/LRErrors.h index c1e7e3b..115b6f7 100755 --- a/Sources/Helper/LRErrors.h +++ b/Sources/Helper/LRErrors.h @@ -45,6 +45,8 @@ + (NSError*)touchIDNotAvailable; + (NSError*)touchIDNotDeviceOwner; - +#pragma mark - Face ID ++ (NSError*)faceIDNotAvailable; ++ (NSError*)faceIDNotDeviceOwner; @end diff --git a/Sources/Helper/LRErrors.m b/Sources/Helper/LRErrors.m index 3e4b479..688fc3d 100755 --- a/Sources/Helper/LRErrors.m +++ b/Sources/Helper/LRErrors.m @@ -150,4 +150,15 @@ + (NSError*)touchIDNotDeviceOwner { failureReason:@"TouchID Authentiction failed since the user is not the device's owner"]; } ++ (NSError*)faceIDNotAvailable { + return [NSError errorWithCode:LRErrorCodeFaceIDNotAvailable + description:@"Face ID authentication failed" + failureReason:@"The User's device cannot be authenticated using FaceID"]; +} + ++ (NSError*)faceIDNotDeviceOwner { + return [NSError errorWithCode:LRErrorCodeFaceIDNotAvailable + description:@"Face ID authentication failed" + failureReason:@"FaceID Authentiction failed since the user is not the device's owner"]; +} @end diff --git a/Sources/LoginRadius.h b/Sources/LoginRadius.h index a77ce9c..b2de5a7 100755 --- a/Sources/LoginRadius.h +++ b/Sources/LoginRadius.h @@ -12,6 +12,7 @@ FOUNDATION_EXPORT const unsigned char LoginRadiusSDKVersionString[]; #import #import #import +#import #import #import #import diff --git a/Sources/LoginRadiusSDK.m b/Sources/LoginRadiusSDK.m index a119572..0fb0f81 100755 --- a/Sources/LoginRadiusSDK.m +++ b/Sources/LoginRadiusSDK.m @@ -7,6 +7,7 @@ #import "LoginRadiusSDK.h" #import "LoginRadiusSocialLoginManager.h" #import "LRTouchIDAuth.h" +#import "LRFaceIDAuth.h" #import "LRSession.h" #import "LoginRadiusEncryptor.h" @@ -26,6 +27,7 @@ @interface LoginRadiusSDK () @property (strong, nonatomic) LoginRadiusSocialLoginManager *socialLoginManager; @property (strong, nonatomic) LRTouchIDAuth *touchIDManager; +@property (strong, nonatomic) LRFaceIDAuth *faceIDManager; @end @implementation LoginRadiusSDK @@ -79,6 +81,7 @@ - (instancetype)init { _session = [[LRSession alloc] init]; _socialLoginManager = [[LoginRadiusSocialLoginManager alloc] init]; _touchIDManager = [[LRTouchIDAuth alloc] init]; + _faceIDManager = [[LRFaceIDAuth alloc] init]; _customHeaders = customHeaders; _setEncryption = setEncryption; }