iOS / study / Accessing Keychain Items with Face ID or Touch ID (2)

2018-06-26

Accessing Keychain Items with Face ID or Touch ID : 바이오메트릭정보로 키체인 아이템에 접근(Add, Read, Delete)하기 Origin: Apple Developer Document

Create an Access Control

SecAccessControl

To create a protected keychain item, begin by creating a SecAccessControl instance:

  • 보호된 키체인아이템을 생성하기 위해서 SecAccessControl 인스턴스를 생성함.
let access = SecAccessControlCreateWithFlags(nil, // Use the default allocator.
                                            kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly,
                                            .userPresence,
                                            nil) // Ignore any error.

kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly

The access control instance contains restrictions along two dimensions: accessibility and authentication. For the first, the kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly setting prevents items from being stored if the device has no passcode. Further, any item already stored in the keychain with this level of accessibility becomes unavailable if the user removes the passcode. Also, because this accessibility ends with ThisDeviceOnly, the item isn’t eligible for the iCloud keychain and won’t be included if the user restores a device backup to a new device. This is the most restrictive option, but others are available.

  • access control 인스턴스는 두가지 제한을 포함. 접근과 인증
  • 첫번째로 kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly 설정은 디바이스가 패스코드를 가지고 있지 않은 경우 아이템이 저장되는 것을 막는다.
  • 키체인에 (이 키를 가지고 있는) 이미 저장된 아이템에 대해서, 사용자가 패스코드를 지웠다면 사용할 수 없게됨.
  • 이 접근은 ThisDeviceOnly 이니까, 이 키를 가지고 있는 키체인아이템은 iCloud키체인에서 사용할 수 없으며, 새로운 디바이스에 백업할 때도 복원되지 않음.
  • 이 키가 제일 제한적 옵션임. 다른 옵션들도 있으므로 참고.

userPresence flag

Along the authentication dimension, the above code uses the userPresence flag. This tells keychain services to request biometric authentication, or to fall back on the device passcode, whenever the item is later read from the keychain. For more information about creating an access control instance, including the various levels of restrictiveness in each dimension, see Restricting Keychain Item Accessibility.

  • 위의 코드는 ‘userPresence’라는 플래그를 사용함. 이 플래그는 나중에 키체인아이템을 읽을 때, 키체인서비스가 바이오메트릭 인증을 요청한다고 말하거나 이 디바이스의 패스코드를 띄우게끔 한다.
  • 다양한 제한단계를 포함하여, access control 인스턴스를 생성하는 것에 대한 더 많은 정보는 다음 문서를 읽기 바람.
  • Restricting Keychain Item Accessibility

Optionally, Provide a Customized Context

Keychain services automatically makes use of the LocalAuthentication framework, and in particular uses an LAContext instance to authenticate the user. You can let keychain services create a new context every time it needs to authenticate. However, if you want to alter the default configuration, you can optionally create a context for it to use instead:

  • 키체인서비스는 자동으로 LocalAuthentication 프레임웍을 사용하도록 만들고, 사용자 인증을 위해 LAContext인스턴스를 일부 사용함.
  • 인증이 필요하다면 키체인서비스가 매번 새로운 context를 생성하도록 할 수 있음.
  • 그러나 기본 설정을 바꿀 경우 다음 코드와 같이 선택적으로 context를 만들어야함.
let context = LAContext()
context.touchIDAuthenticationAllowableReuseDuration = 10

TouchIDAuthenticationAllwableReuseDuration

In this example, you set the context’s touchIDAuthenticationAllowableReuseDuration parameter to a non-zero value. As a result, any Touch ID authentication that keychain services requires is satisfied by the most recent device unlock event, if it happened within the given number of seconds (up to five mintues). This configuration prevents the user from having to authenticate twice in quick succession: once to get into the device, and immediately again to obtain a keychain item. Note that this grace period applies specifically to device unlock with Touch ID, not keychain retrieval authentications.

  • 이 예제처럼 touchIDAuthenticationAllowableReuseDuration 파라미터를 0이 아닌 값으로 설정합니다.
  • 결과적으로 모든 Touch ID 인증은 가장 최근의 언락이벤트로 만족됨, 지정된 초 내에 발생한 경우. (최대 5분)
  • 이 설정은 사용자가 빠른 프로세스 내에서 두번의 인증을 해야하는 것을 막습니다. 예를 들면, 디바이스를 언락하고 즉시 키체인아이템에 접근하는 경우.
  • 이 유예기간은 키체인 검색인증이 아닌 터치아이디로 잠금해제 하기에만 적용됨을 알아두세요.

Add the Keychina Item

Next, put all of the attributes together into a query dictionary:

  • 다음으로 쿼리딕셔너리 안에 속성을 모두 넣는다.
let query: [String: Any] = [kSecClass as String: kSecClassInternetPassword,
                            kSecAttrAccount as String: account,
                            kSecAttrServer as String: server,
                            kSecAttrAccessControl as String: access as Any,
                            kSecUseAuthenticationContext as String: context,
                            kSecValueData as String: password]

This query is very much like the one described in Adding a Password to the Keychain, with the addition of the access control instance and the context. Then use this query to actually create the item:

  • 이 쿼리는 context, access control 인스턴스와 함께 패스워드를 키체인에 추가에 설명된 것과 유사함(??). 이 쿼리는 실제로 키체인아이템을 생성함.
let status = SecItemAdd(query as CFDictionary, nil)
guard status == errSecSuccess else { throw KeychainError(status: status) }

Test the return status and handle error conditions in a way that makes sense for your app. For example, you might handle the errSecDuplicateItem error by attempting to modify the item that already exists. See Using the Keychain to Manage User Secrets for a general discussion of working with keychain items.

  • 내 앱에서 오류조건과 리턴 상태를 테스트합니다. 예를 들어, 이미 있는 항목을 수정해봄으로써 ’errSecDuplicateItem’에러를 핸들링할 수 있습니다.
  • 키체인아이템관련한 내용은 Using the Keychain to Manage User Secrets를 참고

Provide a Prompt When Reading the Item

When reading the protected item, you search for it as described in Searching for Keychain Items. Keychain services works with LocalAuthentication to authenticate the user automatically as needed, using the context you provided, if any. However, there are a few additional query settings you might want to include. First, you can provide a string that the authentication context presents to the user when asking for a TouchID event. Set this string in the kSecUseOperationPrompt attribute of the keychain item search query:

  • 보호된 아이템을 읽을 때, Searching for Keychain Items에서 설명된 것 처럼 검색할 수 있음.
  • 키페인 서비스는 LocalAuthentication을 동작시켜서 앱에서 제공되는 context를 사용하여 유저를 자동으로 인증한다.
  • 그렇지만 몇가지 추가해야하는 쿼리 설정이 있음.
  • 먼저 TouchID 이벤트가 떴을 때 사용자에게 표시되는 인증 context string을 제공할 수 있음.
  • kSecUseOperationPrompt 속성을 사용하여 키체인항목 검색쿼리에 설정한다.
let query: [String: Any] = [kSecClass as String: kSecClassInternetPassword,
                            kSecAttrServer as String: server,
                            kSecMatchLimit as String: kSecMatchLimitOne,
                            kSecReturnAttributes as String: true,
                            kSecUseOperationPrompt as String: "Access your password on the keychain",
                            kSecReturnData as String: true]

Providing this prompt lets the user know why you want them to authenticate. The corresponding dialog already names your app, so you don’t have to include that in the prompt. Additionally, if you don’t want keychain services to prompt for authentication when you search for items, for example, because you’re conducting a broad search and are willing to simply skip any protected items, you can specify the kSecUseAuthenticationUI value with the kSecUseAuthenticationUISkip key.

  • 이 프롬프트를 제공하는 것은 유저가 이 앱이 인증을 원하는 이유를 알게 하기 위해서임.
  • 이미 다이얼로그에서 앱이름을 표시하므로, 프롬프트 string에는 포함하지 않아도 됨.
  • 추가로, 키체인아이템을 검색할 때 인증프롬프트를 원하지 않으면 kSecUseAuthenticationUI, kSecUseAuthenticationUISkip 키를 사용할 수 있다.
  • 예를 들면, 광범위한 검색을 수행하고, 보호된 아이템에 대해서 건너뛰기 위한 경우.
ioskeychain

iOS / iOS App Name Localization

iOS / study / Accessing Keychain Items with Face ID or Touch ID (1)