-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feat] make keychain #183
[Feat] make keychain #183
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
// | ||
// KeychainWrapper.swift | ||
// KkuMulKum | ||
// | ||
// Created by μ΄μ§ν on 7/15/24. | ||
// | ||
|
||
import Foundation | ||
import SwiftKeychainWrapper | ||
|
||
protocol KeychainAccessible { | ||
func saveToken(_ key: String, _ value: String) | ||
func saveExpiresIn(_ key: String, _ value: Int) | ||
func getToken(_ key: String) -> String? | ||
func getExpiresIn(_ Key: String) -> Int? | ||
func remove(_ key: String) | ||
func removeAll() | ||
} | ||
|
||
class DefaultKeychainAccessible: KeychainAccessible { | ||
private let keychain = KeychainWrapper.standard | ||
|
||
func saveToken(_ key: String, _ value: String) { | ||
keychain.set(value, forKey: key) | ||
} | ||
|
||
func saveExpiresIn(_ key: String, _ value: Int) { | ||
keychain.set(value, forKey: key) | ||
} | ||
|
||
func getToken(_ key: String) -> String? { | ||
keychain.string(forKey: key) | ||
} | ||
|
||
func getExpiresIn(_ Key: String) -> Int? { | ||
keychain.integer(forKey: Key) | ||
} | ||
|
||
func remove(_ key: String) { | ||
keychain.removeObject(forKey: key) | ||
} | ||
|
||
func removeAll() { | ||
keychain.removeAllKeys() | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
// | ||
// KeychainService.swift | ||
// KkuMulKum | ||
// | ||
// Created by μ΄μ§ν on 7/15/24. | ||
// | ||
|
||
import Foundation | ||
import SwiftKeychainWrapper | ||
import Security | ||
|
||
protocol KeychainService { | ||
var accessToken: String? { get set } | ||
var refreshToken: String? { get set } | ||
func removeAllTokens() | ||
func verifyKeychainAccess() | ||
} | ||
|
||
class DefaultKeychainService: KeychainService { | ||
static let shared = DefaultKeychainService() | ||
|
||
private let keychain: KeychainWrapper | ||
|
||
private struct Key { | ||
static let accessToken = "accessToken" | ||
static let refreshToken = "refreshToken" | ||
} | ||
|
||
init() { | ||
let serviceName = Bundle.main.privacyInfo?["ServiceName"] as? String ?? Bundle.main.bundleIdentifier ?? "DefaultServiceName" | ||
self.keychain = KeychainWrapper(serviceName: serviceName) | ||
print("Keychain initialized with service name: \(serviceName)") | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. μ΄ λΆλΆμ μμ ν΄λ μ’μ κ² κ°μ΅λλ€. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. λ°μμ |
||
|
||
var accessToken: String? { | ||
get { | ||
let token = keychain.string(forKey: Key.accessToken) | ||
print("Reading Access Token: \(token ?? "nil")") | ||
return token | ||
} | ||
set { | ||
if let newValue = newValue { | ||
let success = keychain.set(newValue, forKey: Key.accessToken) | ||
print("Setting Access Token: \(newValue)") | ||
if success { | ||
print("Access Token saved successfully") | ||
// μ μ₯ ν μ¦μ μ½μ΄ νμΈ | ||
if let savedToken = keychain.string(forKey: Key.accessToken) { | ||
print("Verified Access Token: \(savedToken)") | ||
} else { | ||
print("Failed to verify Access Token after saving") | ||
} | ||
} else { | ||
print("Failed to save Access Token") | ||
printKeychainError(forKey: Key.accessToken) | ||
} | ||
} else { | ||
let success = keychain.removeObject(forKey: Key.accessToken) | ||
print(success ? "Access Token removed successfully" : "Failed to remove Access Token") | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. λμ€ μ’ μ€μ¬μ£ΌμΈμ! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. λ°μμ |
||
} | ||
} | ||
|
||
var refreshToken: String? { | ||
get { | ||
let token = keychain.string(forKey: Key.refreshToken) | ||
print("Reading Refresh Token: \(token ?? "nil")") | ||
return token | ||
} | ||
set { | ||
if let newValue = newValue { | ||
let success = keychain.set(newValue, forKey: Key.refreshToken) | ||
print("Setting Refresh Token: \(newValue)") | ||
if success { | ||
print("Refresh Token saved successfully") | ||
// μ μ₯ ν μ¦μ μ½μ΄ νμΈ | ||
if let savedToken = keychain.string(forKey: Key.refreshToken) { | ||
print("Verified Refresh Token: \(savedToken)") | ||
} else { | ||
print("Failed to verify Refresh Token after saving") | ||
} | ||
} else { | ||
print("Failed to save Refresh Token") | ||
printKeychainError(forKey: Key.refreshToken) | ||
} | ||
} else { | ||
let success = keychain.removeObject(forKey: Key.refreshToken) | ||
print(success ? "Refresh Token removed successfully" : "Failed to remove Refresh Token") | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. μ¬κΈ°λ λμ€ μ€μ¬μ£ΌμΈμ! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. λ°μμ |
||
} | ||
} | ||
|
||
func removeAllTokens() { | ||
keychain.removeObject(forKey: Key.accessToken) | ||
keychain.removeObject(forKey: Key.refreshToken) | ||
print("All tokens removed from keychain") | ||
} | ||
|
||
func verifyKeychainAccess() { | ||
let testKey = "TestKeychainAccess" | ||
let testValue = "TestValue" | ||
|
||
// ν€μ²΄μΈμ ν μ€νΈ κ° μ μ₯ | ||
let saveSuccess = keychain.set(testValue, forKey: testKey) | ||
if saveSuccess { | ||
print("Test value saved to keychain successfully") | ||
|
||
// μ μ₯λ κ° μ½κΈ° | ||
if let retrievedValue = keychain.string(forKey: testKey) { | ||
print("Test value retrieved successfully: \(retrievedValue)") | ||
} else { | ||
print("Failed to retrieve test value") | ||
} | ||
|
||
// ν μ€νΈ κ° μμ | ||
let removeSuccess = keychain.removeObject(forKey: testKey) | ||
print(removeSuccess ? "Test value removed successfully" : "Failed to remove test value") | ||
} else { | ||
print("Failed to save test value to keychain") | ||
printKeychainError(forKey: testKey) | ||
} | ||
} | ||
|
||
private func printKeychainError(forKey key: String) { | ||
let query: [String: Any] = [ | ||
kSecClass as String: kSecClassGenericPassword, | ||
kSecAttrAccount as String: key, | ||
kSecAttrService as String: keychain.serviceName, | ||
kSecReturnData as String: true | ||
] | ||
|
||
var item: CFTypeRef? | ||
let status = SecItemCopyMatching(query as CFDictionary, &item) | ||
print("Keychain error for key '\(key)': \(SecCopyErrorMessageString(status, nil) ?? "Unknown error" as CFString)") | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
structλ μμ±μ΄ κ°λ₯νκΈ° λλ¬Έμ, μΌλ°μ μΌλ‘ enumμΌλ‘ μ μΈνκ³€ νλ΅λλ€.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ν μ°Έκ³ νκ²μ΅λλ€!