diff --git a/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/StateMachine/CodeGen/Errors/HostedUIError.swift b/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/StateMachine/CodeGen/Errors/HostedUIError.swift index d426a345f9..d8ba2e8ef1 100644 --- a/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/StateMachine/CodeGen/Errors/HostedUIError.swift +++ b/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/StateMachine/CodeGen/Errors/HostedUIError.swift @@ -27,6 +27,8 @@ enum HostedUIError: Error { case invalidContext + case unableToStartASWebAuthenticationSession + case unknown } diff --git a/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/StateMachine/ErrorMapping/SignInError+Helper.swift b/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/StateMachine/ErrorMapping/SignInError+Helper.swift index 75ba411059..2a5630d898 100644 --- a/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/StateMachine/ErrorMapping/SignInError+Helper.swift +++ b/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/StateMachine/ErrorMapping/SignInError+Helper.swift @@ -104,6 +104,11 @@ extension HostedUIError: AuthErrorConvertible { AuthPluginErrorConstants.hostedUIInvalidPresentation.errorDescription, AuthPluginErrorConstants.hostedUIInvalidPresentation.recoverySuggestion) + case .unableToStartASWebAuthenticationSession: + return .service( + AuthPluginErrorConstants.hostedUIUnableToStartASWebAuthenticationSession.errorDescription, + AuthPluginErrorConstants.hostedUIUnableToStartASWebAuthenticationSession.recoverySuggestion) + case .serviceMessage(let message): return .service(message, AuthPluginErrorConstants.serviceError) diff --git a/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Support/Constants/AuthPluginErrorConstants.swift b/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Support/Constants/AuthPluginErrorConstants.swift index baa46fc0d3..b6bbdfff89 100644 --- a/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Support/Constants/AuthPluginErrorConstants.swift +++ b/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Support/Constants/AuthPluginErrorConstants.swift @@ -40,6 +40,10 @@ enum AuthPluginErrorConstants { "Presentation context provided is invalid or not present", "Retry by providing a presentation context to present the webUI") + static let hostedUIUnableToStartASWebAuthenticationSession: AuthPluginErrorString = ( + "Unable to start a ASWebAuthenticationSession", + "Make sure that the app can present an ASWebAuthenticationSession") + static let hostedUISignInURI: AuthPluginErrorString = ( "SignIn URI could not be created", "Check the configuration to make sure that HostedUI related information are present") @@ -63,6 +67,7 @@ enum AuthPluginErrorConstants { static let userInvalidError: AuthPluginErrorString = ( "Could not validate the user", "Get the current user Auth.getCurrentUser() and make the request") + static let identityIdSignOutError: AuthPluginErrorString = ( "There is no user signed in to retreive identity id", "Call Auth.signIn to sign in a user or enable unauthenticated access in AWS Cognito Identity Pool") diff --git a/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Support/HostedUI/HostedUIASWebAuthenticationSession.swift b/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Support/HostedUI/HostedUIASWebAuthenticationSession.swift index 20f21d5262..c32f91d089 100644 --- a/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Support/HostedUI/HostedUIASWebAuthenticationSession.swift +++ b/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Support/HostedUI/HostedUIASWebAuthenticationSession.swift @@ -67,6 +67,8 @@ class HostedUIASWebAuthenticationSession: NSObject, HostedUISessionBehavior { } if canStart { aswebAuthenticationSession.start() + } else { + continuation.resume( throwing: HostedUIError.unableToStartASWebAuthenticationSession) } } } diff --git a/AmplifyPlugins/Auth/Tests/AWSCognitoAuthPluginUnitTests/Support/HostedUIASWebAuthenticationSessionTests.swift b/AmplifyPlugins/Auth/Tests/AWSCognitoAuthPluginUnitTests/Support/HostedUIASWebAuthenticationSessionTests.swift index eae166c4a6..5e44e233f1 100644 --- a/AmplifyPlugins/Auth/Tests/AWSCognitoAuthPluginUnitTests/Support/HostedUIASWebAuthenticationSessionTests.swift +++ b/AmplifyPlugins/Auth/Tests/AWSCognitoAuthPluginUnitTests/Support/HostedUIASWebAuthenticationSessionTests.swift @@ -112,7 +112,21 @@ class HostedUIASWebAuthenticationSessionTests: XCTestCase { XCTFail("Expected HostedUIError.unknown, got \(error)") } } - + + /// Given: A HostedUIASWebAuthenticationSession + /// When: showHostedUI is invoked and the session factory returns an error + /// Then: A HostedUIError.unableToStartASWebAuthenticationSession should be returned + func testShowHostedUI_withUnableToStartError_shouldReturnServiceError() async { + factory.mockCanStart = false + do { + _ = try await session.showHostedUI() + } catch let error as HostedUIError { + XCTAssertEqual(error, .unableToStartASWebAuthenticationSession) + } catch { + XCTFail("Expected HostedUIError.unknown, got \(error)") + } + } + private func createURL(queryItems: [URLQueryItem] = []) -> URL { var components = URLComponents(string: "https://test.com")! components.queryItems = queryItems @@ -123,6 +137,7 @@ class HostedUIASWebAuthenticationSessionTests: XCTestCase { class ASWebAuthenticationSessionFactory { var mockedURL: URL? var mockedError: Error? + var mockCanStart: Bool? func createSession( url URL: URL, @@ -136,6 +151,7 @@ class ASWebAuthenticationSessionFactory { ) session.mockedURL = mockedURL session.mockedError = mockedError + session.mockCanStart = mockCanStart ?? true return session } } @@ -161,6 +177,11 @@ class MockASWebAuthenticationSession: ASWebAuthenticationSession { callback(mockedURL, mockedError) return presentationContextProvider?.presentationAnchor(for: self) != nil } + + var mockCanStart = true + override var canStart: Bool { + return mockCanStart + } } extension HostedUIASWebAuthenticationSession { diff --git a/AmplifyPlugins/Auth/Tests/AWSCognitoAuthPluginUnitTests/TaskTests/HostedUITests/AWSAuthHostedUISignInTests.swift b/AmplifyPlugins/Auth/Tests/AWSCognitoAuthPluginUnitTests/TaskTests/HostedUITests/AWSAuthHostedUISignInTests.swift index 5a1a14acc1..7bb9e254bd 100644 --- a/AmplifyPlugins/Auth/Tests/AWSCognitoAuthPluginUnitTests/TaskTests/HostedUITests/AWSAuthHostedUISignInTests.swift +++ b/AmplifyPlugins/Auth/Tests/AWSCognitoAuthPluginUnitTests/TaskTests/HostedUITests/AWSAuthHostedUISignInTests.swift @@ -229,6 +229,22 @@ class AWSAuthHostedUISignInTests: XCTestCase { await fulfillment(of: [expectation], timeout: networkTimeout) } + func testUnableToStartASWebAuthenticationSession() async { + mockHostedUIResult = .failure(.unableToStartASWebAuthenticationSession) + let expectation = expectation(description: "SignIn operation should complete") + do { + _ = try await plugin.signInWithWebUI(presentationAnchor: ASPresentationAnchor(), options: nil) + XCTFail("Should not succeed") + } catch { + guard case AuthError.service = error else { + XCTFail("Should not fail with error = \(error)") + return + } + expectation.fulfill() + } + await fulfillment(of: [expectation], timeout: networkTimeout) + } + @MainActor func testTokenParsingFailure() async { mockHostedUIResult = .success([