From ee8fec20b69a16f30a188fcc448fb864c5588d9a Mon Sep 17 00:00:00 2001 From: Harshdeep Singh <6162866+harsh62@users.noreply.github.com> Date: Tue, 6 May 2025 18:51:32 -0400 Subject: [PATCH 1/3] fix(auth): add protected data unavailable error --- .../AWSCognitoAuthPlugin+Configure.swift | 12 ++++++++++++ .../Models/Errors/AWSCognitoAuthError.swift | 5 +++++ .../Support/Constants/AuthPluginErrorConstants.swift | 5 +++++ .../Task/Protocols/AmplifyAuthTask.swift | 12 ++++++++++++ 4 files changed, 34 insertions(+) diff --git a/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/AWSCognitoAuthPlugin+Configure.swift b/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/AWSCognitoAuthPlugin+Configure.swift index 8c26cb155e..f2ae779c0d 100644 --- a/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/AWSCognitoAuthPlugin+Configure.swift +++ b/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/AWSCognitoAuthPlugin+Configure.swift @@ -16,6 +16,9 @@ import AWSClientRuntime @_spi(InternalHttpEngineProxy) import AWSPluginsCore import SmithyRetriesAPI import SmithyRetries +#if canImport(UIKit) +import UIKit +#endif extension AWSCognitoAuthPlugin { @@ -38,6 +41,15 @@ extension AWSCognitoAuthPlugin { AuthPluginErrorConstants.decodeConfigurationError.recoverySuggestion) } +#if canImport(UIKit) + guard UIApplication.shared.isProtectedDataAvailable else { + throw PluginError.pluginConfigurationError( + AuthPluginErrorConstants.protectedDataUnavailableError.errorDescription, + AuthPluginErrorConstants.protectedDataUnavailableError.recoverySuggestion, + AWSCognitoAuthError.protectedDataUnavailable) + } +#endif + let credentialStoreResolver = CredentialStoreState.Resolver().eraseToAnyResolver() let credentialEnvironment = credentialStoreEnvironment(authConfiguration: authConfiguration) let credentialStoreMachine = StateMachine(resolver: credentialStoreResolver, diff --git a/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Models/Errors/AWSCognitoAuthError.swift b/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Models/Errors/AWSCognitoAuthError.swift index 5f3553979c..c53662f85b 100644 --- a/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Models/Errors/AWSCognitoAuthError.swift +++ b/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Models/Errors/AWSCognitoAuthError.swift @@ -111,6 +111,9 @@ public enum AWSCognitoAuthError: Error { /// The WebAuthn configuration is missing or incomplete case webAuthnConfigurationMissing + + /// Protected data is not yet available (iOS prewarming or locked state) + case protectedDataUnavailable } extension AWSCognitoAuthError: LocalizedError { @@ -185,6 +188,8 @@ extension AWSCognitoAuthError: LocalizedError { message = "The relying party ID doesn't match." case .webAuthnConfigurationMissing: message = "The WebAuthn configuration is missing or incomplete." + case .protectedDataUnavailable: + message = "Protected data is not yet available." } return "\(String(describing: Self.self)).\(self): \(message)" } diff --git a/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Support/Constants/AuthPluginErrorConstants.swift b/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Support/Constants/AuthPluginErrorConstants.swift index fe4ad79eb9..624c930cfe 100644 --- a/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Support/Constants/AuthPluginErrorConstants.swift +++ b/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Support/Constants/AuthPluginErrorConstants.swift @@ -16,6 +16,11 @@ typealias AuthPluginValidationErrorString = (field: Field, enum AuthPluginErrorConstants { + static let protectedDataUnavailableError: AuthPluginErrorString = ( + "Protected data is not yet available", + "Delay Amplify calls until `UIApplication.shared.isProtectedDataAvailable` returns true or listen to `UIApplication.protectedDataDidBecomeAvailableNotification`" + ) + static let decodeConfigurationError: AuthPluginErrorString = ( "Unable to decode configuration", "Make sure the plugin configuration is JSONValue") diff --git a/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Task/Protocols/AmplifyAuthTask.swift b/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Task/Protocols/AmplifyAuthTask.swift index de7fec46ff..5b49f294a4 100644 --- a/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Task/Protocols/AmplifyAuthTask.swift +++ b/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Task/Protocols/AmplifyAuthTask.swift @@ -7,6 +7,10 @@ import Foundation import Amplify +#if canImport(UIKit) +import UIKit +#endif + protocol AmplifyAuthTask { associatedtype Success @@ -30,6 +34,14 @@ extension AmplifyAuthTask where Self: DefaultLogger { get async throws { do { log.info("Starting execution for \(eventName)") +#if canImport(UIKit) + guard await UIApplication.shared.isProtectedDataAvailable else { + throw AuthError.configuration( + AuthPluginErrorConstants.protectedDataUnavailableError.errorDescription, + AuthPluginErrorConstants.protectedDataUnavailableError.recoverySuggestion, + AWSCognitoAuthError.protectedDataUnavailable) + } +#endif let valueReturned = try await execute() log.info("Successfully completed execution for \(eventName) with result:\n\(valueReturned)") dispatch(result: .success(valueReturned)) From 479cfb88bb6354d42b542ad5f94016d39514d667 Mon Sep 17 00:00:00 2001 From: Harshdeep Singh <6162866+harsh62@users.noreply.github.com> Date: Tue, 6 May 2025 18:59:20 -0400 Subject: [PATCH 2/3] shorten the message --- .../Support/Constants/AuthPluginErrorConstants.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Support/Constants/AuthPluginErrorConstants.swift b/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Support/Constants/AuthPluginErrorConstants.swift index 624c930cfe..80bce64891 100644 --- a/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Support/Constants/AuthPluginErrorConstants.swift +++ b/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Support/Constants/AuthPluginErrorConstants.swift @@ -18,7 +18,7 @@ enum AuthPluginErrorConstants { static let protectedDataUnavailableError: AuthPluginErrorString = ( "Protected data is not yet available", - "Delay Amplify calls until `UIApplication.shared.isProtectedDataAvailable` returns true or listen to `UIApplication.protectedDataDidBecomeAvailableNotification`" + "Delay Amplify calls until `UIApplication.shared.isProtectedDataAvailable` returns true" ) static let decodeConfigurationError: AuthPluginErrorString = ( From c26eebbdbd47743d5047552d3ecdb7cc83df4f62 Mon Sep 17 00:00:00 2001 From: Harshdeep Singh <6162866+harsh62@users.noreply.github.com> Date: Wed, 7 May 2025 12:18:24 -0400 Subject: [PATCH 3/3] add ios check --- .../AWSCognitoAuthPlugin/AWSCognitoAuthPlugin+Configure.swift | 4 ++-- .../AWSCognitoAuthPlugin/Task/Protocols/AmplifyAuthTask.swift | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/AWSCognitoAuthPlugin+Configure.swift b/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/AWSCognitoAuthPlugin+Configure.swift index f2ae779c0d..b81e60a8ae 100644 --- a/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/AWSCognitoAuthPlugin+Configure.swift +++ b/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/AWSCognitoAuthPlugin+Configure.swift @@ -16,7 +16,7 @@ import AWSClientRuntime @_spi(InternalHttpEngineProxy) import AWSPluginsCore import SmithyRetriesAPI import SmithyRetries -#if canImport(UIKit) +#if os(iOS) && canImport(UIKit) import UIKit #endif @@ -41,7 +41,7 @@ extension AWSCognitoAuthPlugin { AuthPluginErrorConstants.decodeConfigurationError.recoverySuggestion) } -#if canImport(UIKit) +#if os(iOS) && canImport(UIKit) guard UIApplication.shared.isProtectedDataAvailable else { throw PluginError.pluginConfigurationError( AuthPluginErrorConstants.protectedDataUnavailableError.errorDescription, diff --git a/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Task/Protocols/AmplifyAuthTask.swift b/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Task/Protocols/AmplifyAuthTask.swift index 5b49f294a4..14d772025b 100644 --- a/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Task/Protocols/AmplifyAuthTask.swift +++ b/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Task/Protocols/AmplifyAuthTask.swift @@ -7,7 +7,7 @@ import Foundation import Amplify -#if canImport(UIKit) +#if os(iOS) && canImport(UIKit) import UIKit #endif @@ -34,7 +34,7 @@ extension AmplifyAuthTask where Self: DefaultLogger { get async throws { do { log.info("Starting execution for \(eventName)") -#if canImport(UIKit) +#if os(iOS) && canImport(UIKit) guard await UIApplication.shared.isProtectedDataAvailable else { throw AuthError.configuration( AuthPluginErrorConstants.protectedDataUnavailableError.errorDescription,