[iOS8 Beta] TouchID (Local Authentication)

TouchID는 iPhone5S에 처음 적용된, 지문을 통한 사용자 인증 방식이다. 개발자의 접근이 막혀있던 TouchID 를 애플이 iOS8에서 오픈했다. (WWDC2014)

LocalAuthentication Framework

TouchID를 사용하려면 LocalAuthentication Framework을 import 해야 한다. Swift에선 Objective-C 처럼 Xcode Build Phases에서 Framework 추가할 필요도 없다. 그냥 적으면 된다.


import LocalAuthentication

iOS Simulator 에선 컴파일 되지 않는다. 본인은 이것땜에 시간을 조금 소비했다. (Swift가 생소해서 설정이든 뭐든 다른 문제가 있구나 생각했었다.)

Xcode6 beta3 부터 iOS Simulator 타겟으로 빌드는 된다. 그러나 LAContext 객체 생성부에서 Runtime Error가 발생한다.

NSDebugDescription=The connection to service named com.apple.CoreAuthentication.daemon was invalidated.

LAContext class

API 사용은 심플하다. LAContext Class 메소드 두 개만 사용하면 되다.  ( iOS8 Pre-Release Reference에 친절하게도 Objective-C  코드가 적혀있다.)

  1. canEvaluatePolicy(_:error:) – TouchID 가능 여부 판별
  2. evaluatePolicy(_:localizedReason:reply:) – TouchID 인증 결과 리턴

func authenticateUser(){

    let myContext = LAContext()
    var authError : NSError?
    let localizedReasonText = "본인 인증 하세요."

    if myContext.canEvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, error:&authError) {
        myContext.evaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics,
                                 localizedReason:localizedReasonText,
                                 reply:{(success: Bool, error : NSError! )in

            if (success) {
                // 인증 성공
                self.didUserAuthenticated()

            } else {
                // 인증 실패
                self.didUserAuthenticationFaild(error)

            }
        })

    }else{
       // TouchID 사용 불가
       self.didUserAuthenticationFaild(authError!)
    }
}

func didUserAuthenticated(){

    println("user authenticated")
}

func didUserAuthenticationFaild(error:NSError){

    switch error.code{

        case LAError.AuthenticationFailed.toRaw(): // limit exceed or Biometric lockout
            println("failed")

        case LAError.UserCancel.toRaw():
            println("canceled by user")

        case LAError.UserFallback.toRaw():
            println("user wants to enter password")

        case LAError.SystemCancel.toRaw():
            println("canceled by system")

        case LAError.PasscodeNotSet.toRaw() , LAError.TouchIDNotAvailable.toRaw(), LAError.TouchIDNotEnrolled.toRaw():
            fallthrough
        default:
            println("TouchID is not available")

    }
}

LAError 

에러상황은 LAError로 구분한다. LAError 정의는 아래와 같다.


enum LAError : Int {
   case AuthenticationFailed
   case UserCancel
   case UserFallback
   case SystemCancel
   case PasscodeNotSet
   case TouchIDNotAvailable
   case TouchIDNotEnrolled
}

evaluatePolicy(_:localizedReason:reply:) 를 호출하면 TouchID 인식요청 알림창이 나타난다.

< TouchID 알림창 >

사용자가  ‘암호입력’ 버튼을 탭하면 리턴되는 것이 UserFallback 이다. 이 때 암호는 디바이스 잠금 암호가 아니다. 앱 내부에서 처리하면 된다. 아래같이 커스텀 뷰컨트롤러를 띄우는 것도 하나의 방법이겠다.

    ...    
   .case UserFallback:
        self.performSegueWithIdentifier(passwordSegue, sender: nil)
    ....   

AuthenticationFailed 는 지문 인식 실패를  의미한다.

알림창에서 인식 3회 실패하거나 연속 5회 실패로 TouchID 가 잠길때 리턴된다. (TouchID 잠김은 아이폰 잠김화면에서 TouchID 반복 실패시 암호를 직접 입력해야 하는 상황으로 생각하면 된다.)

앱내에서 TouchID 잠기면 디바이스 전체에 영향을 미친다.  즉 디바이스가 잠길 경우  TouchID 대신 암호를 입력해야한다.

 

살펴본것처럼 API 사용은 어렵지 않다.

디바이스 잠금번호를 알면 지문 등록이 가능하니, 앱 내에서 사용하는 비밀번호를 TouchID 로 대체하는 것이 안전하다고만 할 수 없다.

애플이 TouchID 사용하는 경우엔 디바이스 비밀번호를 4자리 숫자로 설정하지 못하도록 제한할 수도 있지 않을까? (그렇게 했으면 좋겠다.)

참고로 iOS8에서는 KeyChain에 저장된 데이터에 사용자가 접근할 때 사용자에게 TouchID 인증을 요청할 수 있다. 개발자의 TouchID API 호출없이 Attribute에 키값을 추가하면 OS가 처리해주는 방식이다.

 

* Reference

  • Local Authentication Framework Reference (iOS8 Pre-Release Library)
Advertisements
%d bloggers like this: