안녕하세요. iOS 개발자 도미닉입니다.
오늘은 페이워치코리아에서 생체 인증을 처음으로 도입해 본 경험을 기록으로 남겨보고자 합니다.
페이워치코리아에 처음 입사해서 iOS 쪽 일을 찾던 와중에 생체 인증이 필요하다는 것을 알게 되었습니다.
저희 앱에 인출하기 버튼을 누르면 패스워드를 입력하는데요.
이 때 비밀번호 입력을 생체 인증으로 대신하면 어떨까? 하는 사항이였습니다.
생체 인증은 편하게 금융 앱 등에서 사용했었습니다.
하지만 구현을 해보려고 하니 알고 있는 내용들이 많이 없었습니다.
위처럼 궁금한 점이 많았습니다.
먼저 간단히 생체 인증 예제 코드를 작성해봤습니다.
//
// ViewController.swift
// ExFaceTouchId
//
//
import UIKit
import LocalAuthentication
class ViewController: UIViewController {
@IBOutlet weak var loginButton: UIButton!
enum AuthenticationState {
case loggedin, loggedout
}
// ✅ 현재 로그인 상태에 따른 UI 변화
var state = AuthenticationState.loggedout {
didSet {
if state == .loggedin {
loginButton.setTitle("Logout", for: .normal)
} else {
loginButton.setTitle("Login", for: .normal)
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func didTapButton(_ sender: Any) {
if state == .loggedin {
state = .loggedout
} else {
// ✅ LAContext 로 Secure Enclave 와 앱과의 상호작용을 중개.
let context = LAContext()
// ✅ alert view 에서 cancel button 메시지.
context.localizedCancelTitle = "Enter Username/Password"
var error: NSError?
// ✅ 지정한 policy 로 biometrics 인증이 가능한지 테스트.
if context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error) {
let reason = "Log in to your account"
// ✅ 지정한 policy 로 biometrics 인증 시작.
context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: reason ) { success, error in
if success {
// ✅ state 업데이트는 UI 변화를 일으켜서 main thread 에서 처리해야한다.
DispatchQueue.main.async { [unowned self] in
self.state = .loggedin
print("state : \(self.state)")
}
} else {
print(error?.localizedDescription ?? "Failed to authenticate")
// Fall back to a asking for username and password.
// ...
}
}
}
}
}
}
이 코드에서 생체 인증을 시도해보고 성공, 실패에 따른 분기 처리를 확인할 수 있었습니다.
아래처럼 의문을 해결해가면서 기획된 내용들을 대부분 구현할 수 있었습니다.
참고에 첫번째 링크에 있는 에러 메시지들을 통해 LAError.biometryNotEnrolled 에러일 경우 기기에 등록된 생체 인식 ID가 없다는 것을 알 수 있었습니다.
이 에러가 발생할 경우에는 생체 인증이 진행되지 않고 휴대폰의 "설정" 앱에서 생체 인증을 우선 등록하라는 간단한 오류창을 띄웠습니다.
기획에는 앱에 생체 인증을 등록해야 앱 내에서 생체 인증 기능을 사용할 수 있었습니다.
하지만 제가 개발을 하고 예제를 만들어보니 앱을 위한 등록을 하지 않아도 바로 기기에 등록한 생체 인증 정보를 사용할 수 있었습니다.
이 부분은 빼야하나 고민을 하고 의논해보니 다른 핸드폰에서 생체 인증을 하면 재등록을 하도록 해야하기 때문에 앱 내에 생체 인증 등록이 필요했습니다.
생체 데이터는 아니지만 아래 코드로 생체 정보 ID 값을 가져올 수 있습니다.
let context = LAContext()
context.evaluatedPolicyDomainState
이 생체 정보 ID 값을 UserDefaults 로 휴대폰 내부에 저장할 수 있습니다.
또한 DB 에 저장하여 생체 정보가 바뀐 것을 확인할 수 있습니다.
여러 핸드폰에서 각자의 생체 인증 ID로 생체 인증을 진행하면 안 되기 때문에 이 값을 DB 에 저장하도록 API 를 요청하였습니다.
이렇게 DB 에 저장하는 것을 앱에 생체 인증 등록하는 것으로 처리하였습니다.
별도로 인증 시도에 실패했을 때 어떤 코드를 실행하도록 컨트롤 할 수는 없는 것으로 파악했습니다.
예제 코드에서는 생체 인증에 여러 번 실패 시 아이폰의 비밀번호로 생체 인증을 대신할 수 있었습니다.
아이폰을 취득해서 아이폰의 비밀번호만 알고 있는 사람이 저희 서비스에 비밀번호를 모르고도 진행을 할 수 있었습니다.
이러면 안되기 때문에 LAContext 의 정책을 deviceOwnerAuthentication 가 아닌 deviceOwnerAuthenticationWithBiometrics 로 변경하여 기기의 비밀번호를 알더라도 생체 인증을 하지 않으면 진행할 수 없도록 막았습니다.
만약 사용자의 휴대폰을 누군가 주워서 생체 인증에 자신의 지문이나 FaceID 를 추가하게 되서 우리 서비스의 인증을 진행하게 되면 안될 것입니다.
생체 인증 정보가 변경된 것을 캐치해서 생체 인증을 못하게 막고 재등록을 해야만 사용할 수 있도록 구성을 하였습니다.
생체 인증 정보가 바뀐 것은 생체 인증을 진행하기 전에 위에 등록처럼 context.evaluatedPolicyDomainState 값을 활용합니다.
이 값은 생체에 대한 정보가 담긴 데이터는 아니며 생체의 고유한 ID 값으로 이해했으며 생체 정보가 바뀐다면 이 값이 바뀌게 되었습니다.
이 값을 DB 에 저장하고 조회하여 현재 값과 다르다면 생체 인증이 진행되지 않게 막았습니다.
위에 질문과 조사한 내용들로 저희가 원하는 대로 생체 인증을 구성할 수 있었습니다.
진행한 내용들을 통해서 생체 인증을 정리해보고자 합니다.
생체 인증을 사용하고자 한다면 우선 LocalAuthentication 을 import 해야합니다.
import LocalAuthentication
그 뒤에 LAContext 라는 클래스를 생성하고 사용하며 생체 인증을 개발할 수 있습니다.
let context = LAContext()
기존에 저장된 생체 ID 와 다른 것을 체크하기 위해서 아래처럼 context.evaluatedPolicyDomainState 값을 사용할 수 있었습니다.
let biometricsData = context.evaluatedPolicyDomainState
생체 인증 alert view 에서 cancel button 메시지를 아래처럼 작성할 수 있습니다.
context.localizedCancelTitle = "취소"
그러고는 보통 아래처럼 지정한 policy(위에서 적어놓았던 deviceOwnerAuthentication 와 deviceOwnerAuthenticationWithBiometrics 중 선택)에서 인증이 가능한지 확인합니다.
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
if 문 안으로 이동되어서 인증이 가능하다면 지정한 policy로 생체 인증을 진행합니다.
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason ) { success, error in
if success {
// 생체 인증에 성공했을 때의 동작
} else {
// 실패했을 때의 동작
}
}
이렇게 해서 생체 인증 기능을 저희 앱에 추가하여 어제 배포 완료하였습니다.
저희 회사에서는 여러 공고를 통해 개발자 분들을 모집하고 있습니다.
https://www.wanted.co.kr/company/11912
위 링크로 많은 지원 부탁드립니다.
질문이 있거나 잘못된 점 있으면 편하게 댓글 달아주세요.
이상으로 긴 글 읽어주셔서 감사합니다.
https://kkh0977.tistory.com/1608
https://dev.classmethod.jp/articles/ios-biometrics-authentication-kr/
https://dev.classmethod.jp/articles/ios-biometry-authentication-domain-change-kr/
저도 해당 글 참고해서 생체인증 사용해서 개발할수있겠네요 ㅎㅎ
유익한 글 작성해주셔서 감사합니다. 다음 글도 기대할게요 도미닉 개발자님~