Persist Authentication in Keychain

This commit is contained in:
Marcus Kida 2023-05-26 11:36:08 +02:00 committed by Nathan Mattes
parent d570d3ef09
commit 06c72a022a
3 changed files with 34 additions and 3 deletions

View File

@ -18,6 +18,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
let appContext = AppContext()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
AuthenticationServiceProvider.shared.restore()
AppSecret.default.register()

View File

@ -4,13 +4,20 @@ import Foundation
import Combine
import CoreDataStack
import MastodonSDK
import KeychainAccess
import MastodonCommon
public class AuthenticationServiceProvider: ObservableObject {
public static let shared = AuthenticationServiceProvider()
private static let keychain = Keychain(service: "org.joinmastodon.app.authentications", accessGroup: AppName.groupID)
private init() {}
@Published public var authentications: [MastodonAuthentication] = []
@Published public var authentications: [MastodonAuthentication] = [] {
didSet {
persist() // todo: Is this too heavy and too often here???
}
}
func update(instance: Instance, where domain: String) {
authentications = authentications.map { authentication in
@ -46,4 +53,23 @@ public extension AuthenticationServiceProvider {
func sortByActivation() { // fixme: why do we need this?
authentications = authentications.sorted(by: { $0.activedAt > $1.activedAt })
}
func restore() {
authentications = Self.keychain.allKeys().compactMap {
guard
let encoded = Self.keychain[$0],
let data = Data(base64Encoded: encoded)
else { return nil }
return try? JSONDecoder().decode(MastodonAuthentication.self, from: data)
}
}
}
// MARK: - Private
private extension AuthenticationServiceProvider {
func persist() {
for authentication in authentications {
Self.keychain[authentication.persistenceIdentifier] = try? JSONEncoder().encode(authentication).base64EncodedString()
}
}
}

View File

@ -23,6 +23,10 @@ public struct MastodonAuthentication: Codable, Hashable {
public private(set) var userID: String
public private(set) var instanceObjectIdURI: URL?
internal var persistenceIdentifier: String {
"\(username)@\(domain)"
}
public static func createFrom(
domain: String,
userID: String,
@ -34,7 +38,7 @@ public struct MastodonAuthentication: Codable, Hashable {
) -> Self {
let now = Date()
return MastodonAuthentication(
identifier: .init(), // fixme
identifier: .init(),
domain: domain,
username: username,
appAccessToken: appAccessToken,