Post

Replies

Boosts

Views

Activity

Sign in with Apple Keychain savedEmail Stored Incorrectly
Using personal physical iPhone for simulations. Can't get Keychain to read or store AppleID name/email. I want to avoid hard reseting physical phone. Logs confirm Keychain is working, but userIdentifier and savedEmail are not being stored correctly. 🔄 Initializing UserManager... ✅ Saved testKeychain to Keychain: Test Value ✅ Retrieved testKeychain from Keychain: Test Value 🔍 Keychain Test - Retrieved Value: Test Value ⚠️ Keychain Retrieve Warning: No stored value found for userIdentifier ⚠️ Keychain Retrieve Warning: No stored value found for savedEmail 🔍 Debug - Retrieved from Keychain: userIdentifier=nil, savedEmail=nil ⚠️ No stored userIdentifier in Keychain. User needs to sign in. 📦 Converting User to CKRecord: Unknown, No Email ✅ User saved locally: Unknown, No Email ✅ User saved to CloudKit: Unknown, No Email Below UserManager.swift if someone can help troubleshoot. Or step by step tutorial to configure a project and build a User Login & User Account creation for Apple Only app. import Foundation import CloudKit import AuthenticationServices import SwiftData @MainActor class UserManager: ObservableObject { @Published var user: User? @Published var isLoggedIn = false @Published var errorMessage: String? private let database = CKContainer.default().publicCloudDatabase init() { print("🔄 Initializing UserManager...") // 🔍 Keychain Debug Test let testKey = "testKeychain" KeychainHelper.shared.save("Test Value", forKey: testKey) let retrievedValue = KeychainHelper.shared.retrieve(forKey: testKey) print("🔍 Keychain Test - Retrieved Value: \(retrievedValue ?? "nil")") fetchUser() // Continue normal initialization } // ✅ Sign in & Save User func handleSignIn(_ authResults: ASAuthorization) { guard let appleIDCredential = authResults.credential as? ASAuthorizationAppleIDCredential else { errorMessage = "Error retrieving Apple credentials" print("❌ ASAuthorization Error: Invalid credentials received") return } let userIdentifier = appleIDCredential.user let fullName = appleIDCredential.fullName?.givenName ?? retrieveSavedName() var email = appleIDCredential.email ?? retrieveSavedEmail() print("🔍 Apple Sign-In Data: userIdentifier=\(userIdentifier), fullName=\(fullName), email=\(email)") // 🔄 If Apple doesn't return an email, check if it exists in Keychain if appleIDCredential.email == nil { print("⚠️ Apple Sign-In didn't return an email. Retrieving saved email from Keychain.") } // ✅ Store userIdentifier & email in Keychain KeychainHelper.shared.save(userIdentifier, forKey: "userIdentifier") KeychainHelper.shared.save(email, forKey: "savedEmail") let newUser = User(fullName: fullName, email: email, userIdentifier: userIdentifier) saveUserToCloudKit(newUser) } func saveUserToCloudKit(_ user: User) { let record = user.toRecord() Task { do { try await database.save(record) DispatchQueue.main.async { self.user = user self.isLoggedIn = true self.saveUserLocally(user) print("✅ User saved to CloudKit: \(user.fullName), \(user.email)") } } catch { DispatchQueue.main.async { self.errorMessage = "Error saving user: \(error.localizedDescription)" print("❌ CloudKit Save Error: \(error.localizedDescription)") } } } } // ✅ Fetch User from CloudKit func fetchUser() { let userIdentifier = KeychainHelper.shared.retrieve(forKey: "userIdentifier") let savedEmail = KeychainHelper.shared.retrieve(forKey: "savedEmail") print("🔍 Debug - Retrieved from Keychain: userIdentifier=\(userIdentifier ?? "nil"), savedEmail=\(savedEmail ?? "nil")") guard let userIdentifier = userIdentifier else { print("⚠️ No stored userIdentifier in Keychain. User needs to sign in.") return } let predicate = NSPredicate(format: "userIdentifier == %@", userIdentifier) let query = CKQuery(recordType: "User", predicate: predicate) Task { [weak self] in guard let self = self else { return } do { let results = try await self.database.records(matching: query, resultsLimit: 1).matchResults if let (_, result) = results.first { switch result { case .success(let record): DispatchQueue.main.async { let fetchedUser = User(record: record) self.user = User( fullName: fetchedUser.fullName, email: savedEmail ?? fetchedUser.email, userIdentifier: userIdentifier ) self.isLoggedIn = true self.saveUserLocally(self.user!) print("✅ User loaded from CloudKit: \(fetchedUser.fullName), \(fetchedUser.email)") } case .failure(let error): DispatchQueue.main.async { print("❌ Error fetching user from CloudKit: \(error.localizedDescription)") } } } } catch { DispatchQueue.main.async { print("❌ CloudKit fetch error: \(error.localizedDescription)") } } } } // ✅ Save User Locally private func saveUserLocally(_ user: User) { if let encoded = try? JSONEncoder().encode(user) { UserDefaults.standard.set(encoded, forKey: "savedUser") UserDefaults.standard.set(user.fullName, forKey: "savedFullName") UserDefaults.standard.set(user.email, forKey: "savedEmail") print("✅ User saved locally: \(user.fullName), \(user.email)") } else { print("❌ Local Save Error: Failed to encode user data") } } // ✅ Retrieve Previously Saved Name private func retrieveSavedName() -> String { return UserDefaults.standard.string(forKey: "savedFullName") ?? "Unknown" } // ✅ Retrieve Previously Saved Email private func retrieveSavedEmail() -> String { return KeychainHelper.shared.retrieve(forKey: "savedEmail") ?? UserDefaults.standard.string(forKey: "savedEmail") ?? "No Email" } // ✅ Sign Out func signOut() { isLoggedIn = false user = nil UserDefaults.standard.removeObject(forKey: "savedUser") print("🚪 Signed Out") } }
0
0
322
Mar ’25
Sign in with Apple Keychain savedEmail Stored Incorrectly
Using personal physical iPhone for simulations. Can't get Keychain to read or store AppleID name/email. I want to avoid hard reseting physical phone. Logs confirm Keychain is working, but userIdentifier and savedEmail are not being stored correctly. 🔄 Initializing UserManager... ✅ Saved testKeychain to Keychain: Test Value ✅ Retrieved testKeychain from Keychain: Test Value 🔍 Keychain Test - Retrieved Value: Test Value ⚠️ Keychain Retrieve Warning: No stored value found for userIdentifier ⚠️ Keychain Retrieve Warning: No stored value found for savedEmail 🔍 Debug - Retrieved from Keychain: userIdentifier=nil, savedEmail=nil ⚠️ No stored userIdentifier in Keychain. User needs to sign in. 📦 Converting User to CKRecord: Unknown, No Email ✅ User saved locally: Unknown, No Email ✅ User saved to CloudKit: Unknown, No Email Below UserManager.swift if someone can help troubleshoot. Or step by step tutorial to configure a project and build a User Login & User Account creation for Apple Only app. import Foundation import CloudKit import AuthenticationServices import SwiftData @MainActor class UserManager: ObservableObject { @Published var user: User? @Published var isLoggedIn = false @Published var errorMessage: String? private let database = CKContainer.default().publicCloudDatabase init() { print("🔄 Initializing UserManager...") // 🔍 Keychain Debug Test let testKey = "testKeychain" KeychainHelper.shared.save("Test Value", forKey: testKey) let retrievedValue = KeychainHelper.shared.retrieve(forKey: testKey) print("🔍 Keychain Test - Retrieved Value: \(retrievedValue ?? "nil")") fetchUser() // Continue normal initialization } // ✅ Sign in & Save User func handleSignIn(_ authResults: ASAuthorization) { guard let appleIDCredential = authResults.credential as? ASAuthorizationAppleIDCredential else { errorMessage = "Error retrieving Apple credentials" print("❌ ASAuthorization Error: Invalid credentials received") return } let userIdentifier = appleIDCredential.user let fullName = appleIDCredential.fullName?.givenName ?? retrieveSavedName() var email = appleIDCredential.email ?? retrieveSavedEmail() print("🔍 Apple Sign-In Data: userIdentifier=\(userIdentifier), fullName=\(fullName), email=\(email)") // 🔄 If Apple doesn't return an email, check if it exists in Keychain if appleIDCredential.email == nil { print("⚠️ Apple Sign-In didn't return an email. Retrieving saved email from Keychain.") } // ✅ Store userIdentifier & email in Keychain KeychainHelper.shared.save(userIdentifier, forKey: "userIdentifier") KeychainHelper.shared.save(email, forKey: "savedEmail") let newUser = User(fullName: fullName, email: email, userIdentifier: userIdentifier) saveUserToCloudKit(newUser) } func saveUserToCloudKit(_ user: User) { let record = user.toRecord() Task { do { try await database.save(record) DispatchQueue.main.async { self.user = user self.isLoggedIn = true self.saveUserLocally(user) print("✅ User saved to CloudKit: \(user.fullName), \(user.email)") } } catch { DispatchQueue.main.async { self.errorMessage = "Error saving user: \(error.localizedDescription)" print("❌ CloudKit Save Error: \(error.localizedDescription)") } } } } // ✅ Fetch User from CloudKit func fetchUser() { let userIdentifier = KeychainHelper.shared.retrieve(forKey: "userIdentifier") let savedEmail = KeychainHelper.shared.retrieve(forKey: "savedEmail") print("🔍 Debug - Retrieved from Keychain: userIdentifier=\(userIdentifier ?? "nil"), savedEmail=\(savedEmail ?? "nil")") guard let userIdentifier = userIdentifier else { print("⚠️ No stored userIdentifier in Keychain. User needs to sign in.") return } let predicate = NSPredicate(format: "userIdentifier == %@", userIdentifier) let query = CKQuery(recordType: "User", predicate: predicate) Task { [weak self] in guard let self = self else { return } do { let results = try await self.database.records(matching: query, resultsLimit: 1).matchResults if let (_, result) = results.first { switch result { case .success(let record): DispatchQueue.main.async { let fetchedUser = User(record: record) self.user = User( fullName: fetchedUser.fullName, email: savedEmail ?? fetchedUser.email, userIdentifier: userIdentifier ) self.isLoggedIn = true self.saveUserLocally(self.user!) print("✅ User loaded from CloudKit: \(fetchedUser.fullName), \(fetchedUser.email)") } case .failure(let error): DispatchQueue.main.async { print("❌ Error fetching user from CloudKit: \(error.localizedDescription)") } } } } catch { DispatchQueue.main.async { print("❌ CloudKit fetch error: \(error.localizedDescription)") } } } } // ✅ Save User Locally private func saveUserLocally(_ user: User) { if let encoded = try? JSONEncoder().encode(user) { UserDefaults.standard.set(encoded, forKey: "savedUser") UserDefaults.standard.set(user.fullName, forKey: "savedFullName") UserDefaults.standard.set(user.email, forKey: "savedEmail") print("✅ User saved locally: \(user.fullName), \(user.email)") } else { print("❌ Local Save Error: Failed to encode user data") } } // ✅ Retrieve Previously Saved Name private func retrieveSavedName() -> String { return UserDefaults.standard.string(forKey: "savedFullName") ?? "Unknown" } // ✅ Retrieve Previously Saved Email private func retrieveSavedEmail() -> String { return KeychainHelper.shared.retrieve(forKey: "savedEmail") ?? UserDefaults.standard.string(forKey: "savedEmail") ?? "No Email" } // ✅ Sign Out func signOut() { isLoggedIn = false user = nil UserDefaults.standard.removeObject(forKey: "savedUser") print("🚪 Signed Out") } }
Replies
0
Boosts
0
Views
322
Activity
Mar ’25
App isn’t properly retrieving the user
The Core Problem After Users sign out from the App, the app isn’t properly retrieving the user on second sign in. Instead, it’s treating the user as “Unknown” and saving a new entry in CloudKit and locally. Is there a tutorial aside from 'Juice' that is recent and up to date?
Replies
3
Boosts
0
Views
411
Activity
Mar ’25