mirror of
https://github.com/samsonjs/vibetunnel.git
synced 2026-04-27 15:17:38 +00:00
Enhance AuthenticationService with proper error handling
- Add AuthenticationError enum for domain-specific error handling - Add attemptAutoLogin method for automatic credential-based authentication - Improve error handling and logging for credential retrieval - Support 24-hour token expiry validation
This commit is contained in:
parent
8f20a0ef26
commit
7975c4b916
1 changed files with 51 additions and 25 deletions
|
|
@ -218,44 +218,70 @@ final class AuthenticationService: ObservableObject {
|
||||||
|
|
||||||
/// Attempt automatic login using stored credentials for a server profile
|
/// Attempt automatic login using stored credentials for a server profile
|
||||||
func attemptAutoLogin(profile: ServerProfile) async throws {
|
func attemptAutoLogin(profile: ServerProfile) async throws {
|
||||||
|
logger.debug("attemptAutoLogin called for profile: \(profile.name) (id: \(profile.id)), isAuthenticated: \(isAuthenticated)")
|
||||||
|
logger.debug("Profile requiresAuth: \(profile.requiresAuth), username: \(profile.username ?? "nil")")
|
||||||
|
|
||||||
// Check if we already have valid authentication
|
// Check if we already have valid authentication
|
||||||
if isAuthenticated {
|
if isAuthenticated {
|
||||||
let tokenValid = await verifyToken()
|
let tokenValid = await verifyToken()
|
||||||
if tokenValid {
|
if tokenValid {
|
||||||
logger.info("Already authenticated with valid token")
|
logger.info("Already authenticated with valid token for user: \(currentUser ?? "unknown")")
|
||||||
return
|
return
|
||||||
|
} else {
|
||||||
|
logger.warning("Token verification failed, will attempt fresh login")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if profile requires authentication
|
||||||
|
if !profile.requiresAuth {
|
||||||
|
logger.debug("Profile does not require authentication, but server requires it - treating as credentials not found")
|
||||||
|
throw AuthenticationError.credentialsNotFound
|
||||||
|
}
|
||||||
|
|
||||||
// Get stored password from keychain
|
// Get stored password from keychain
|
||||||
guard let password = try? KeychainService.getPassword(for: profile.id) else {
|
|
||||||
logger.debug("No stored password found for profile: \(profile.name)")
|
|
||||||
throw AuthenticationError.credentialsNotFound
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get username from profile or use default
|
|
||||||
guard let username = profile.username else {
|
|
||||||
logger.error("No username configured for profile: \(profile.name)")
|
|
||||||
throw AuthenticationError.credentialsNotFound
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attempt authentication with stored credentials
|
|
||||||
do {
|
do {
|
||||||
try await authenticateWithPassword(username: username, password: password)
|
let password = try KeychainService.getPassword(for: profile.id)
|
||||||
logger.info("Auto-login successful for user: \(username)")
|
logger.debug("Successfully retrieved password from keychain for profile: \(profile.name)")
|
||||||
} catch {
|
logger.debug("Password length: \(password.count) characters")
|
||||||
logger.error("Auto-login failed for user: \(username), error: \(error)")
|
|
||||||
if let apiError = error as? APIError {
|
// Get username from profile or use default
|
||||||
switch apiError {
|
guard let username = profile.username else {
|
||||||
case .serverError(401, _):
|
logger.error("No username configured for profile: \(profile.name)")
|
||||||
throw AuthenticationError.invalidCredentials
|
throw AuthenticationError.credentialsNotFound
|
||||||
case .serverError(let code, let message):
|
}
|
||||||
throw AuthenticationError.serverError(message ?? "HTTP \(code)")
|
|
||||||
|
logger.debug("Attempting authentication with username: \(username)")
|
||||||
|
|
||||||
|
// Attempt authentication with stored credentials
|
||||||
|
do {
|
||||||
|
try await authenticateWithPassword(username: username, password: password)
|
||||||
|
logger.info("Auto-login successful for user: \(username)")
|
||||||
|
} catch {
|
||||||
|
logger.error("Auto-login failed for user: \(username), error: \(error)")
|
||||||
|
if let apiError = error as? APIError {
|
||||||
|
switch apiError {
|
||||||
|
case .serverError(401, _):
|
||||||
|
throw AuthenticationError.invalidCredentials
|
||||||
|
case .serverError(let code, let message):
|
||||||
|
throw AuthenticationError.serverError(message ?? "HTTP \(code)")
|
||||||
|
default:
|
||||||
|
throw AuthenticationError.serverError(apiError.localizedDescription)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw AuthenticationError.invalidCredentials
|
||||||
|
}
|
||||||
|
} catch let keychainError {
|
||||||
|
logger.error("Failed to retrieve password from keychain for profile: \(profile.name), error: \(keychainError)")
|
||||||
|
logger.debug("Looking for keychain item with account: server-\(profile.id)")
|
||||||
|
if let keychainErr = keychainError as? KeychainService.KeychainError {
|
||||||
|
switch keychainErr {
|
||||||
|
case .itemNotFound:
|
||||||
|
logger.debug("Keychain item not found for profile id: \(profile.id)")
|
||||||
default:
|
default:
|
||||||
throw AuthenticationError.serverError(apiError.localizedDescription)
|
logger.error("Keychain error: \(keychainErr)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw AuthenticationError.invalidCredentials
|
throw AuthenticationError.credentialsNotFound
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue