Stores a deviceId inside the keychain to avoid changes

sync
Laurent 1 year ago
parent 9d3935b563
commit a978bbcbfa
  1. 19
      LeStorage/Services.swift
  2. 21
      LeStorage/StoreCenter.swift
  3. 20
      LeStorage/Utils/KeychainStore.swift

@ -209,7 +209,7 @@ public class Services {
request.httpMethod = method.rawValue request.httpMethod = method.rawValue
request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.setValue("application/json", forHTTPHeaderField: "Content-Type")
if !(requiresToken == false) { if !(requiresToken == false) {
let token = try self.keychainStore.getToken() let token = try self.keychainStore.getValue()
request.addValue("Token \(token)", forHTTPHeaderField: "Authorization") request.addValue("Token \(token)", forHTTPHeaderField: "Authorization")
} }
return request return request
@ -255,7 +255,7 @@ public class Services {
if self._isTokenRequired(type: T.self, method: apiCall.method) { if self._isTokenRequired(type: T.self, method: apiCall.method) {
do { do {
let token = try self.keychainStore.getToken() let token = try self.keychainStore.getValue()
request.setValue("Token \(token)", forHTTPHeaderField: "Authorization") request.setValue("Token \(token)", forHTTPHeaderField: "Authorization")
} catch { } catch {
Logger.log("missing token") Logger.log("missing token")
@ -298,7 +298,10 @@ public class Services {
/// - password: the account's password /// - password: the account's password
public func requestToken(username: String, password: String) async throws -> String { public func requestToken(username: String, password: String) async throws -> String {
var postRequest = try self._baseRequest(conf: .requestToken) var postRequest = try self._baseRequest(conf: .requestToken)
let credentials = Credentials(username: username, password: password, deviceId: StoreCenter.main.deviceId())
let deviceId = StoreCenter.main.deviceId()
Logger.log("deviceId = \(deviceId)")
let credentials = Credentials(username: username, password: password, deviceId: deviceId)
postRequest.httpBody = try jsonEncoder.encode(credentials) postRequest.httpBody = try jsonEncoder.encode(credentials)
let response: AuthResponse = try await self._runRequest(postRequest) let response: AuthResponse = try await self._runRequest(postRequest)
self._storeToken(username: username, token: response.token) self._storeToken(username: username, token: response.token)
@ -311,8 +314,8 @@ public class Services {
/// - token: the token to store /// - token: the token to store
fileprivate func _storeToken(username: String, token: String) { fileprivate func _storeToken(username: String, token: String) {
do { do {
try self.keychainStore.deleteToken() try self.keychainStore.deleteValue()
try self.keychainStore.add(username: username, token: token) try self.keychainStore.add(username: username, value: token)
} catch { } catch {
Logger.error(error) Logger.error(error)
} }
@ -376,13 +379,13 @@ public class Services {
/// Deletes the locally stored token /// Deletes the locally stored token
func deleteToken() throws { func deleteToken() throws {
try self.keychainStore.deleteToken() try self.keychainStore.deleteValue()
} }
/// Returns whether the Service has an associated token /// Returns whether the Service has an associated token
public func hasToken() -> Bool { public func hasToken() -> Bool {
do { do {
_ = try self.keychainStore.getToken() _ = try self.keychainStore.getValue()
return true return true
} catch { } catch {
return false return false
@ -412,7 +415,7 @@ public class Services {
} }
func migrateToken(_ services: Services, userName: String) throws { func migrateToken(_ services: Services, userName: String) throws {
try self._storeToken(username: userName, token: services.keychainStore.getToken()) try self._storeToken(username: userName, token: services.keychainStore.getValue())
} }
} }

@ -115,7 +115,7 @@ public class StoreCenter {
/// Returns the stored token /// Returns the stored token
public func token() -> String? { public func token() -> String? {
return try? self.service().keychainStore.getToken() return try? self.service().keychainStore.getValue()
} }
/// Disconnect the user from the storage and resets collection /// Disconnect the user from the storage and resets collection
@ -133,7 +133,7 @@ public class StoreCenter {
/// Returns whether the system has a user token /// Returns whether the system has a user token
public func hasToken() -> Bool { public func hasToken() -> Bool {
do { do {
_ = try self.service().keychainStore.getToken() _ = try self.service().keychainStore.getValue()
return true return true
} catch { } catch {
return false return false
@ -141,12 +141,19 @@ public class StoreCenter {
} }
func deviceId() -> String { func deviceId() -> String {
let deviceId: String = self._settingsStorage.item.deviceId ?? UIDevice.current.identifierForVendor?.uuidString ?? let keychainStore = KeychainStore(serverId: "lestorage.main")
UUID().uuidString do {
self._settingsStorage.update { settings in return try keychainStore.getValue()
settings.deviceId = deviceId } catch {
let deviceId: String = UIDevice.current.identifierForVendor?.uuidString ??
UUID().uuidString
do {
try keychainStore.add(value: deviceId)
} catch {
Logger.error(error)
}
return deviceId
} }
return deviceId
} }
// MARK: - Api Calls // MARK: - Api Calls

@ -21,18 +21,28 @@ class KeychainStore {
self.serverId = serverId self.serverId = serverId
} }
func add(username: String, token: String) throws { func add(username: String, value: String) throws {
let tokenData = token.data(using: .utf8)! let valueData = value.data(using: .utf8)!
let query: [String: Any] = [kSecClass as String: kSecClassInternetPassword, let query: [String: Any] = [kSecClass as String: kSecClassInternetPassword,
kSecAttrAccount as String: username, kSecAttrAccount as String: username,
kSecAttrServer as String: self.serverId, kSecAttrServer as String: self.serverId,
kSecValueData as String: tokenData] kSecValueData as String: valueData]
let status: OSStatus = SecItemAdd(query as CFDictionary, nil) let status: OSStatus = SecItemAdd(query as CFDictionary, nil)
guard status == errSecSuccess else { throw KeychainError.unhandledError(status: status) } guard status == errSecSuccess else { throw KeychainError.unhandledError(status: status) }
} }
func getToken() throws -> String { func add(value: String) throws {
let valueData = value.data(using: .utf8)!
let query: [String: Any] = [kSecClass as String: kSecClassInternetPassword,
kSecAttrServer as String: self.serverId,
kSecValueData as String: valueData]
let status: OSStatus = SecItemAdd(query as CFDictionary, nil)
guard status == errSecSuccess else { throw KeychainError.unhandledError(status: status) }
}
func getValue() throws -> String {
let query: [String: Any] = [kSecClass as String: kSecClassInternetPassword, let query: [String: Any] = [kSecClass as String: kSecClassInternetPassword,
kSecAttrServer as String: self.serverId, kSecAttrServer as String: self.serverId,
@ -53,7 +63,7 @@ class KeychainStore {
return token return token
} }
func deleteToken() throws { func deleteValue() throws {
let query: [String: Any] = [kSecClass as String: kSecClassInternetPassword, let query: [String: Any] = [kSecClass as String: kSecClassInternetPassword,
kSecAttrServer as String: self.serverId] kSecAttrServer as String: self.serverId]

Loading…
Cancel
Save