키체인 사용하면서 생긴 문제점

Untitled

키체인 사용 시 생긴 버그에 대해 작성해본닷

먼저 위에 사진이 지금 내가 겪고 있는 버그 …. 인데 지금 내가 쓰고 있는 프로세스는 아래와 같다

<aside> ♻️ 키체인 프로세스

  1. 로그인
  2. 액세스, 리프레시 토큰 헤더로 발급
  3. 액세스, 리프레시 각각 헤더에서 추출
  4. 액세스. 리프레시 각각 키체인에 저장
  5. 키체인에 저장
    1. 이미 있는 키체인이면 자동으로 저장 안되기 때문에 기존 키체인 검색 후 업데이트
  6. API 통신 할 때 키체인 읽어오기 </aside>

지금 키체인에 저장하는 값들 종류로는 아래와 같이 총 4가지가 있음 (점점 추가될 예정)

enum KeychainKey {
    case access
    case refresh
    case accessAndRefresh
    case socialAuth
}

그래서 키체인들을 구별하기 위한 label 비스무리한게 있어야 하는데 그걸 위한 용도로 kSecAttrLabel 을 사용했다

let query: [String: Any] = [
    kSecClass as String: kSecClassGenericPassword,
    kSecAttrService as String: serviceName,
    **kSecAttrLabel as String: key.label**
]

( 당연히 Label 이라길래 저게 구분할 수 있을 줄 알았지… )

그리고 저 querySecItemUpdate, SecItemRead 등등을 진행하는데, 그 과정에서 자꾸 accessrefresh 둘 중 하나만 읽어지는 문제가 발생하는 것이다 !!

문제 해결 !

이러저러한 구글링과 디버깅 결과 ! 문제점은 저 kSecAttrLabel 에 있었다 !

위에 적어둔 것처럼 당연히 Label 이라길래 구분할 수 있게 하는 줄 알았는데, 저 값으로는 구분하지 못하는 것 같다 !

구글링하다가 다른 사람들은 여러 개의 키체인을 어떻게 관리하나 봤는데, 아래 블로그에서 해답을 얻었다

[iOS] Keychain 구현해보기

<4. 키체인으로 갱신> 을 보면 아래 코드가 있는데

private func updateKeychain(userIdValue: String, passwordValue: String) -> Bool {
    // make query
    let account = userIdValue.trimmingCharacters(in: .whitespacesAndNewlines)
    let password = passwordValue.data(using: .utf8) as Any
    let query: [String: Any] = [kSecClass as String: kSecClassGenericPassword,
                                kSecAttrService as String: service]
    let attributes: [String: Any] = [**kSecAttrAccount as String: account,**
                                     kSecValueData as String: password]
		// ...

여기서 눈에 띄는 차이점은 kSecAttrAccount 이다 !

let query: [String: Any] = [
    kSecClass as String: kSecClassGenericPassword,
    kSecAttrService as String: serviceName,
    kSecAttrAccount as String: key.label,
		// ...
]

위 코드에서는 account 라는 변수로 키체인을 구분한다고 이해했고, 내 코드에도 위와 같이 적용해 본 결과 !

Untitled

크킄 해결 !!

결론

여러 개의 키체인을 구분할 때에는 kSecAttrLabel 이 아니라 kSecAttrAccount 를 사용하자 !

그리고 눈에 보이는걸로 판단하지 말자 ! (?)