From 06207f431b4ef8a9db6089af9134f892229e2a2b Mon Sep 17 00:00:00 2001 From: Sebastian Villena <97059974+ruisebas@users.noreply.github.com> Date: Mon, 9 Dec 2024 13:11:18 -0500 Subject: [PATCH 1/7] fix: Fixing the WebAuthn integration tests (#3933) --- .github/workflows/integ_test_auth.yml | 15 ++++++++++----- .../AuthWebAuthnAppUITests.swift | 8 +++----- .../AuthWebAuthnAppUITests/LocalServer.swift | 2 +- .../Tests/AuthWebAuthnApp/LocalServer/index.mjs | 2 +- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/.github/workflows/integ_test_auth.yml b/.github/workflows/integ_test_auth.yml index 5cbceea4f7..f7c9b0e1db 100644 --- a/.github/workflows/integ_test_auth.yml +++ b/.github/workflows/integ_test_auth.yml @@ -22,6 +22,11 @@ on: required: true default: true type: boolean + webauthn-ios: + description: '🔐 WebAuthn iOS' + required: true + default: true + type: boolean workflow_call: permissions: @@ -59,8 +64,8 @@ jobs: timeout-minutes: 30 secrets: inherit - # Disabling the integration test because the job is not able to connect to the local server - # auth-webauthn-integration-test-iOS: - # name: Auth WebAuthn Integration Tests (iOS) - # uses: ./.github/workflows/integ_test_auth_webauthn.yml - # secrets: inherit + auth-webauthn-integration-test-iOS: + if: ${{ inputs.webauthn-ios != 'false' }} + name: Auth WebAuthn Integration Tests (iOS) + uses: ./.github/workflows/integ_test_auth_webauthn.yml + secrets: inherit diff --git a/AmplifyPlugins/Auth/Tests/AuthWebAuthnApp/AuthWebAuthnAppUITests/AuthWebAuthnAppUITests.swift b/AmplifyPlugins/Auth/Tests/AuthWebAuthnApp/AuthWebAuthnAppUITests/AuthWebAuthnAppUITests.swift index a314bd2fb3..e6283ebdc6 100644 --- a/AmplifyPlugins/Auth/Tests/AuthWebAuthnApp/AuthWebAuthnAppUITests/AuthWebAuthnAppUITests.swift +++ b/AmplifyPlugins/Auth/Tests/AuthWebAuthnApp/AuthWebAuthnAppUITests/AuthWebAuthnAppUITests.swift @@ -19,7 +19,9 @@ final class AuthWebAuthnAppUITests: XCTestCase { private var deleteButton: XCUIElement! private var deleteUserButton: XCUIElement! private var springboard: XCUIApplication! - private var continueButton: XCUIElement! + private var continueButton: XCUIElement! { + springboard.otherElements["ASAuthorizationControllerContinueButton"] + } private lazy var deviceIdentifier: String = { let paths = Bundle.main.bundleURL.pathComponents @@ -57,7 +59,6 @@ final class AuthWebAuthnAppUITests: XCTestCase { signInButton = nil deleteButton = nil deleteUserButton = nil - continueButton = nil springboard = nil try await uninstallApp() } @@ -233,9 +234,6 @@ final class AuthWebAuthnAppUITests: XCTestCase { signOutButton = app.buttons["SignOut"] springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard") - // The Continue button only appears when a FaceID operation is triggered, - // so we're also not checking for its existance - continueButton = springboard.otherElements["ASAuthorizationControllerContinueButton"] } @MainActor diff --git a/AmplifyPlugins/Auth/Tests/AuthWebAuthnApp/AuthWebAuthnAppUITests/LocalServer.swift b/AmplifyPlugins/Auth/Tests/AuthWebAuthnApp/AuthWebAuthnAppUITests/LocalServer.swift index 07e7c02a3c..59a9438da1 100644 --- a/AmplifyPlugins/Auth/Tests/AuthWebAuthnApp/AuthWebAuthnAppUITests/LocalServer.swift +++ b/AmplifyPlugins/Auth/Tests/AuthWebAuthnApp/AuthWebAuthnAppUITests/LocalServer.swift @@ -8,7 +8,7 @@ import Foundation enum LocalServer { - static let endpoint = "http://127.0.0.1:9293" + static let endpoint = "http://127.0.0.1:9294" case boot(String) case enroll(String) diff --git a/AmplifyPlugins/Auth/Tests/AuthWebAuthnApp/LocalServer/index.mjs b/AmplifyPlugins/Auth/Tests/AuthWebAuthnApp/LocalServer/index.mjs index 1ca545833c..4d019007b7 100644 --- a/AmplifyPlugins/Auth/Tests/AuthWebAuthnApp/LocalServer/index.mjs +++ b/AmplifyPlugins/Auth/Tests/AuthWebAuthnApp/LocalServer/index.mjs @@ -72,6 +72,6 @@ app.post('/match', async (req, res) => { } }) -app.listen(9293, () => { +app.listen(9294, () => { console.log("Simulator server started!") }) From e0d088046b6ab3e4f1232c677cc2003f72164b02 Mon Sep 17 00:00:00 2001 From: Harshdeep Singh <6162866+harsh62@users.noreply.github.com> Date: Wed, 11 Dec 2024 11:22:47 -0500 Subject: [PATCH 2/7] fix(auth): fix credential decoding --- .../AWSCognitoAuthCredentialStore.swift | 8 ++-- .../Models/AuthFlowType.swift | 42 ++++++++++++++++--- 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/CredentialStorage/AWSCognitoAuthCredentialStore.swift b/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/CredentialStorage/AWSCognitoAuthCredentialStore.swift index 1e8b1f77f5..dd55162b57 100644 --- a/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/CredentialStorage/AWSCognitoAuthCredentialStore.swift +++ b/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/CredentialStorage/AWSCognitoAuthCredentialStore.swift @@ -133,8 +133,8 @@ extension AWSCognitoAuthCredentialStore: AmplifyAuthCredentialStoreBehavior { func retrieveCredential() throws -> AmplifyCredentials { let authCredentialStoreKey = generateSessionKey(for: authConfiguration) let authCredentialData = try keychain._getData(authCredentialStoreKey) - let awsCredential: AmplifyCredentials = try decode(data: authCredentialData) - return awsCredential + let amplifyCredential: AmplifyCredentials = try decode(data: authCredentialData) + return amplifyCredential } func deleteCredential() throws { @@ -191,7 +191,7 @@ private extension AWSCognitoAuthCredentialStore { do { return try JSONEncoder().encode(object) } catch { - throw KeychainStoreError.codingError("Error occurred while encoding AWSCredentials", error) + throw KeychainStoreError.codingError("Error occurred while encoding credentials", error) } } @@ -199,7 +199,7 @@ private extension AWSCognitoAuthCredentialStore { do { return try JSONDecoder().decode(T.self, from: data) } catch { - throw KeychainStoreError.codingError("Error occurred while decoding AWSCredentials", error) + throw KeychainStoreError.codingError("Error occurred while decoding credentials", error) } } diff --git a/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Models/AuthFlowType.swift b/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Models/AuthFlowType.swift index 46b701bcd3..9f611fdd92 100644 --- a/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Models/AuthFlowType.swift +++ b/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Models/AuthFlowType.swift @@ -38,6 +38,8 @@ public enum AuthFlowType { switch rawValue { case "CUSTOM_AUTH": self = .customWithSRP + case "CUSTOM_AUTH_WITHOUT_SRP": + self = .customWithoutSRP case "USER_SRP_AUTH": self = .userSRP case "USER_PASSWORD_AUTH": @@ -51,8 +53,10 @@ public enum AuthFlowType { var rawValue: String { switch self { - case .custom, .customWithSRP, .customWithoutSRP: + case .custom, .customWithSRP: return "CUSTOM_AUTH" + case .customWithoutSRP: + return "CUSTOM_AUTH_WITHOUT_SRP" case .userSRP: return "USER_SRP_AUTH" case .userPassword: @@ -62,6 +66,23 @@ public enum AuthFlowType { } } + internal static func legacyInit(rawValue: String) -> Self? { + switch rawValue { + case "userSRP": + return .userSRP + case "userPassword": + return .userPassword + case "custom": + return .custom + case "customWithSRP": + return .customWithSRP + case "customWithoutSRP": + return .customWithoutSRP + default: + return nil + } + } + public static var userAuth: AuthFlowType { return .userAuth(preferredFirstFactor: nil) } @@ -110,9 +131,21 @@ extension AuthFlowType: Codable { // Decoding the enum public init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) + let container: KeyedDecodingContainer + do { + container = try decoder.container(keyedBy: CodingKeys.self) + } catch DecodingError.typeMismatch { + let legacyContainer = try decoder.singleValueContainer() + let type = try legacyContainer.decode(String.self) + guard let authFlowType = AuthFlowType.legacyInit(rawValue: type) else { + throw DecodingError.dataCorruptedError(in: legacyContainer, debugDescription: "Invalid AuthFlowType value") + } + self = authFlowType + return + } catch { + throw error + } - // Decode the type (raw value) let type = try container.decode(String.self, forKey: .type) // Initialize based on the type @@ -130,7 +163,7 @@ extension AuthFlowType: Codable { if let preferredFirstFactor = AuthFactorType(rawValue: preferredFirstFactorString) { self = .userAuth(preferredFirstFactor: preferredFirstFactor) } else { - throw DecodingError.dataCorruptedError(forKey: .type, in: container, debugDescription: "Unable to decode preferredFirstFactor value") + throw DecodingError.dataCorruptedError(forKey: .preferredFirstFactor, in: container, debugDescription: "Unable to decode preferredFirstFactor value") } default: throw DecodingError.dataCorruptedError(forKey: .type, in: container, debugDescription: "Invalid AuthFlowType value") @@ -152,5 +185,4 @@ extension AuthFlowType { return .userAuth } } - } From 478d460b337d75c94c872850f70f0e54d70a87db Mon Sep 17 00:00:00 2001 From: Harshdeep Singh <6162866+harsh62@users.noreply.github.com> Date: Wed, 11 Dec 2024 11:34:32 -0500 Subject: [PATCH 3/7] update comments --- .../Models/AuthFlowType.swift | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Models/AuthFlowType.swift b/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Models/AuthFlowType.swift index 9f611fdd92..903d530490 100644 --- a/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Models/AuthFlowType.swift +++ b/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Models/AuthFlowType.swift @@ -36,7 +36,7 @@ public enum AuthFlowType { internal init?(rawValue: String) { switch rawValue { - case "CUSTOM_AUTH": + case "CUSTOM_AUTH", "CUSTOM_AUTH_WITH_SRP": self = .customWithSRP case "CUSTOM_AUTH_WITHOUT_SRP": self = .customWithoutSRP @@ -54,7 +54,7 @@ public enum AuthFlowType { var rawValue: String { switch self { case .custom, .customWithSRP: - return "CUSTOM_AUTH" + return "CUSTOM_AUTH_WITH_SRP" case .customWithoutSRP: return "CUSTOM_AUTH_WITHOUT_SRP" case .userSRP: @@ -66,6 +66,7 @@ public enum AuthFlowType { } } + // This initializer has been added to migrate credentials that were created in the pre-passwordless era internal static func legacyInit(rawValue: String) -> Self? { switch rawValue { case "userSRP": @@ -135,6 +136,9 @@ extension AuthFlowType: Codable { do { container = try decoder.container(keyedBy: CodingKeys.self) } catch DecodingError.typeMismatch { + // The type mismatch has been added to handle a scenario where the user is migrating passwordless flows. + // Passwordless flow added a new enum case with a associated type. The association resulted in encoding structure changes that is different from the non-passwordless flows. + // The structure change causes the type mismatch exception and this code block tries to retrieve the legacy structure and decode it. let legacyContainer = try decoder.singleValueContainer() let type = try legacyContainer.decode(String.self) guard let authFlowType = AuthFlowType.legacyInit(rawValue: type) else { @@ -152,10 +156,10 @@ extension AuthFlowType: Codable { switch type { case "USER_SRP_AUTH": self = .userSRP - case "CUSTOM_AUTH": - // Depending on your needs, choose either `.custom`, `.customWithSRP`, or `.customWithoutSRP` - // In this case, we'll default to `.custom` - self = .custom + case "CUSTOM_AUTH", "CUSTOM_AUTH_WITH_SRP": + self = .customWithSRP + case "CUSTOM_AUTH_WITHOUT_SRP": + self = .customWithoutSRP case "USER_PASSWORD_AUTH": self = .userPassword case "USER_AUTH": From 426cf993833ea17a8c502fa5592913cc0a13f62d Mon Sep 17 00:00:00 2001 From: Harshdeep Singh <6162866+harsh62@users.noreply.github.com> Date: Wed, 11 Dec 2024 11:43:01 -0500 Subject: [PATCH 4/7] update comment --- .../AWSCognitoAuthPlugin/Models/AuthFlowType.swift | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Models/AuthFlowType.swift b/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Models/AuthFlowType.swift index 903d530490..110f4005a3 100644 --- a/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Models/AuthFlowType.swift +++ b/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Models/AuthFlowType.swift @@ -137,7 +137,8 @@ extension AuthFlowType: Codable { container = try decoder.container(keyedBy: CodingKeys.self) } catch DecodingError.typeMismatch { // The type mismatch has been added to handle a scenario where the user is migrating passwordless flows. - // Passwordless flow added a new enum case with a associated type. The association resulted in encoding structure changes that is different from the non-passwordless flows. + // Passwordless flow added a new enum case with a associated type. + // The association resulted in encoding structure changes that is different from the non-passwordless flows. // The structure change causes the type mismatch exception and this code block tries to retrieve the legacy structure and decode it. let legacyContainer = try decoder.singleValueContainer() let type = try legacyContainer.decode(String.self) @@ -167,7 +168,10 @@ extension AuthFlowType: Codable { if let preferredFirstFactor = AuthFactorType(rawValue: preferredFirstFactorString) { self = .userAuth(preferredFirstFactor: preferredFirstFactor) } else { - throw DecodingError.dataCorruptedError(forKey: .preferredFirstFactor, in: container, debugDescription: "Unable to decode preferredFirstFactor value") + throw DecodingError.dataCorruptedError( + forKey: .preferredFirstFactor, + in: container, + debugDescription: "Unable to decode preferredFirstFactor value") } default: throw DecodingError.dataCorruptedError(forKey: .type, in: container, debugDescription: "Invalid AuthFlowType value") From 7dc8bbc87e60e414bf7534f19a7f7524f0e0ab40 Mon Sep 17 00:00:00 2001 From: Harshdeep Singh <6162866+harsh62@users.noreply.github.com> Date: Wed, 11 Dec 2024 12:29:07 -0500 Subject: [PATCH 5/7] add unit tests --- .../Models/AuthFlowType.swift | 17 ++- .../AuthFlowTypeTests.swift | 143 ++++++++++++++++++ 2 files changed, 153 insertions(+), 7 deletions(-) create mode 100644 AmplifyPlugins/Auth/Tests/AWSCognitoAuthPluginUnitTests/ConfigurationTests/AuthFlowTypeTests.swift diff --git a/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Models/AuthFlowType.swift b/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Models/AuthFlowType.swift index 110f4005a3..b352e873c5 100644 --- a/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Models/AuthFlowType.swift +++ b/AmplifyPlugins/Auth/Sources/AWSCognitoAuthPlugin/Models/AuthFlowType.swift @@ -164,14 +164,17 @@ extension AuthFlowType: Codable { case "USER_PASSWORD_AUTH": self = .userPassword case "USER_AUTH": - let preferredFirstFactorString = try container.decode(String.self, forKey: .preferredFirstFactor) - if let preferredFirstFactor = AuthFactorType(rawValue: preferredFirstFactorString) { - self = .userAuth(preferredFirstFactor: preferredFirstFactor) + if let preferredFirstFactorString = try container.decodeIfPresent(String.self, forKey: .preferredFirstFactor) { + if let preferredFirstFactor = AuthFactorType(rawValue: preferredFirstFactorString) { + self = .userAuth(preferredFirstFactor: preferredFirstFactor) + } else { + throw DecodingError.dataCorruptedError( + forKey: .preferredFirstFactor, + in: container, + debugDescription: "Unable to decode preferredFirstFactor value") + } } else { - throw DecodingError.dataCorruptedError( - forKey: .preferredFirstFactor, - in: container, - debugDescription: "Unable to decode preferredFirstFactor value") + self = .userAuth(preferredFirstFactor: nil) } default: throw DecodingError.dataCorruptedError(forKey: .type, in: container, debugDescription: "Invalid AuthFlowType value") diff --git a/AmplifyPlugins/Auth/Tests/AWSCognitoAuthPluginUnitTests/ConfigurationTests/AuthFlowTypeTests.swift b/AmplifyPlugins/Auth/Tests/AWSCognitoAuthPluginUnitTests/ConfigurationTests/AuthFlowTypeTests.swift new file mode 100644 index 0000000000..36671f3dde --- /dev/null +++ b/AmplifyPlugins/Auth/Tests/AWSCognitoAuthPluginUnitTests/ConfigurationTests/AuthFlowTypeTests.swift @@ -0,0 +1,143 @@ +// +// Copyright Amazon.com Inc. or its affiliates. +// All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 +// + + +import XCTest +@testable import AWSCognitoAuthPlugin + +class AuthFlowTypeTests: XCTestCase { + + func testRawValue() { + XCTAssertEqual(AuthFlowType.userSRP.rawValue, "USER_SRP_AUTH") + XCTAssertEqual(AuthFlowType.customWithSRP.rawValue, "CUSTOM_AUTH_WITH_SRP") + XCTAssertEqual(AuthFlowType.customWithoutSRP.rawValue, "CUSTOM_AUTH_WITHOUT_SRP") + XCTAssertEqual(AuthFlowType.userPassword.rawValue, "USER_PASSWORD_AUTH") + XCTAssertEqual(AuthFlowType.userAuth(preferredFirstFactor: nil).rawValue, "USER_AUTH") + } + + func testInitWithRawValue() { + XCTAssertEqual(AuthFlowType(rawValue: "USER_SRP_AUTH"), .userSRP) + XCTAssertEqual(AuthFlowType(rawValue: "CUSTOM_AUTH"), .customWithSRP) + XCTAssertEqual(AuthFlowType(rawValue: "CUSTOM_AUTH_WITH_SRP"), .customWithSRP) + XCTAssertEqual(AuthFlowType(rawValue: "CUSTOM_AUTH_WITHOUT_SRP"), .customWithoutSRP) + XCTAssertEqual(AuthFlowType(rawValue: "USER_PASSWORD_AUTH"), .userPassword) + XCTAssertEqual(AuthFlowType(rawValue: "USER_AUTH"), .userAuth(preferredFirstFactor: nil)) + XCTAssertNil(AuthFlowType(rawValue: "INVALID_AUTH")) + } + + func testDeprecatedCustom() { + // This test is to ensure the deprecated case is still functional + XCTAssertEqual(AuthFlowType.custom.rawValue, "CUSTOM_AUTH_WITH_SRP") + } + + func testEncoding() throws { + let encoder = JSONEncoder() + let userSRP = try encoder.encode(AuthFlowType.userSRP) + XCTAssertEqual(String(data: userSRP, encoding: .utf8), "{\"type\":\"USER_SRP_AUTH\"}") + + let customWithSRP = try encoder.encode(AuthFlowType.customWithSRP) + XCTAssertEqual(String(data: customWithSRP, encoding: .utf8), "{\"type\":\"CUSTOM_AUTH_WITH_SRP\"}") + + let customWithoutSRP = try encoder.encode(AuthFlowType.customWithoutSRP) + XCTAssertEqual(String(data: customWithoutSRP, encoding: .utf8), "{\"type\":\"CUSTOM_AUTH_WITHOUT_SRP\"}") + + let userPassword = try encoder.encode(AuthFlowType.userPassword) + XCTAssertEqual(String(data: userPassword, encoding: .utf8), "{\"type\":\"USER_PASSWORD_AUTH\"}") + + let userAuth = try encoder.encode(AuthFlowType.userAuth(preferredFirstFactor: nil)) + XCTAssertEqual(String(data: userAuth, encoding: .utf8), "{\"preferredFirstFactor\":null,\"type\":\"USER_AUTH\"}") + } + + func testDecoding() throws { + let decoder = JSONDecoder() + let userSRP = try decoder.decode(AuthFlowType.self, from: "{\"type\":\"USER_SRP_AUTH\"}".data(using: .utf8)!) + XCTAssertEqual(userSRP, .userSRP) + + let customWithSRP = try decoder.decode(AuthFlowType.self, from: "{\"type\":\"CUSTOM_AUTH_WITH_SRP\"}".data(using: .utf8)!) + XCTAssertEqual(customWithSRP, .customWithSRP) + + let customWithoutSRP = try decoder.decode(AuthFlowType.self, from: "{\"type\":\"CUSTOM_AUTH_WITHOUT_SRP\"}".data(using: .utf8)!) + XCTAssertEqual(customWithoutSRP, .customWithoutSRP) + + let userPassword = try decoder.decode(AuthFlowType.self, from: "{\"type\":\"USER_PASSWORD_AUTH\"}".data(using: .utf8)!) + XCTAssertEqual(userPassword, .userPassword) + + let userAuth = try decoder.decode(AuthFlowType.self, from: "{\"type\":\"USER_AUTH\"}".data(using: .utf8)!) + XCTAssertEqual(userAuth, .userAuth(preferredFirstFactor: nil)) + } + + func testDecodingWithPreferredFirstFactor() throws { + let decoder = JSONDecoder() + let json = """ + { + "type": "USER_AUTH", + "preferredFirstFactor": "SMS_OTP" + } + """.data(using: .utf8)! + let authFlowType = try decoder.decode(AuthFlowType.self, from: json) + XCTAssertEqual(authFlowType, .userAuth(preferredFirstFactor: .smsOTP)) + } + + func testDecodingLegacyStructure() throws { + let decoder = JSONDecoder() + var legacyJson = "\"userSRP\"".data(using: .utf8)! + var authFlowType = try decoder.decode(AuthFlowType.self, from: legacyJson) + XCTAssertEqual(authFlowType, .userSRP) + + legacyJson = "\"userPassword\"".data(using: .utf8)! + authFlowType = try decoder.decode(AuthFlowType.self, from: legacyJson) + XCTAssertEqual(authFlowType, .userPassword) + + legacyJson = "\"customWithSRP\"".data(using: .utf8)! + authFlowType = try decoder.decode(AuthFlowType.self, from: legacyJson) + XCTAssertEqual(authFlowType, .customWithSRP) + + legacyJson = "\"customWithoutSRP\"".data(using: .utf8)! + authFlowType = try decoder.decode(AuthFlowType.self, from: legacyJson) + XCTAssertEqual(authFlowType, .customWithoutSRP) + + legacyJson = "\"custom\"".data(using: .utf8)! + authFlowType = try decoder.decode(AuthFlowType.self, from: legacyJson) + XCTAssertEqual(authFlowType, .custom) + } + + func testDecodingInvalidType() { + let decoder = JSONDecoder() + let invalidJson = "{\"type\":\"INVALID_AUTH\"}".data(using: .utf8)! + XCTAssertThrowsError(try decoder.decode(AuthFlowType.self, from: invalidJson)) { error in + guard case DecodingError.dataCorrupted(let context) = error else { + return XCTFail("Expected dataCorrupted error") + } + XCTAssertEqual(context.debugDescription, "Invalid AuthFlowType value") + } + } + + func testDecodingInvalidPreferredFirstFactor() { + let decoder = JSONDecoder() + let invalidJson = """ + { + "type": "USER_AUTH", + "preferredFirstFactor": "INVALID_FACTOR" + } + """.data(using: .utf8)! + XCTAssertThrowsError(try decoder.decode(AuthFlowType.self, from: invalidJson)) { error in + guard case DecodingError.dataCorrupted(let context) = error else { + return XCTFail("Expected dataCorrupted error") + } + XCTAssertEqual(context.debugDescription, "Unable to decode preferredFirstFactor value") + } + } + + func testGetClientFlowType() { + XCTAssertEqual(AuthFlowType.custom.getClientFlowType(), .customAuth) + XCTAssertEqual(AuthFlowType.customWithSRP.getClientFlowType(), .customAuth) + XCTAssertEqual(AuthFlowType.customWithoutSRP.getClientFlowType(), .customAuth) + XCTAssertEqual(AuthFlowType.userSRP.getClientFlowType(), .userSrpAuth) + XCTAssertEqual(AuthFlowType.userPassword.getClientFlowType(), .userPasswordAuth) + XCTAssertEqual(AuthFlowType.userAuth(preferredFirstFactor: nil).getClientFlowType(), .userAuth) + } +} From e7d3237b1254296b973f5d27d813ebcd1cb991cb Mon Sep 17 00:00:00 2001 From: Harshdeep Singh <6162866+harsh62@users.noreply.github.com> Date: Wed, 11 Dec 2024 12:48:45 -0500 Subject: [PATCH 6/7] test fix --- .../ConfigurationTests/AuthFlowTypeTests.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/AmplifyPlugins/Auth/Tests/AWSCognitoAuthPluginUnitTests/ConfigurationTests/AuthFlowTypeTests.swift b/AmplifyPlugins/Auth/Tests/AWSCognitoAuthPluginUnitTests/ConfigurationTests/AuthFlowTypeTests.swift index 36671f3dde..5baf8443f4 100644 --- a/AmplifyPlugins/Auth/Tests/AWSCognitoAuthPluginUnitTests/ConfigurationTests/AuthFlowTypeTests.swift +++ b/AmplifyPlugins/Auth/Tests/AWSCognitoAuthPluginUnitTests/ConfigurationTests/AuthFlowTypeTests.swift @@ -49,7 +49,8 @@ class AuthFlowTypeTests: XCTestCase { XCTAssertEqual(String(data: userPassword, encoding: .utf8), "{\"type\":\"USER_PASSWORD_AUTH\"}") let userAuth = try encoder.encode(AuthFlowType.userAuth(preferredFirstFactor: nil)) - XCTAssertEqual(String(data: userAuth, encoding: .utf8), "{\"preferredFirstFactor\":null,\"type\":\"USER_AUTH\"}") + XCTAssertTrue(String(data: userAuth, encoding: .utf8)?.contains("\"preferredFirstFactor\":null")) + XCTAssertTrue(String(data: userAuth, encoding: .utf8)?.contains("\"type\":\"USER_AUTH\"")) } func testDecoding() throws { From fb0eb55d73968fa7fd07fa6533094a6aa4b27d95 Mon Sep 17 00:00:00 2001 From: Harshdeep Singh <6162866+harsh62@users.noreply.github.com> Date: Wed, 11 Dec 2024 13:02:24 -0500 Subject: [PATCH 7/7] failed build --- .../ConfigurationTests/AuthFlowTypeTests.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AmplifyPlugins/Auth/Tests/AWSCognitoAuthPluginUnitTests/ConfigurationTests/AuthFlowTypeTests.swift b/AmplifyPlugins/Auth/Tests/AWSCognitoAuthPluginUnitTests/ConfigurationTests/AuthFlowTypeTests.swift index 5baf8443f4..c56c02f0cf 100644 --- a/AmplifyPlugins/Auth/Tests/AWSCognitoAuthPluginUnitTests/ConfigurationTests/AuthFlowTypeTests.swift +++ b/AmplifyPlugins/Auth/Tests/AWSCognitoAuthPluginUnitTests/ConfigurationTests/AuthFlowTypeTests.swift @@ -49,8 +49,8 @@ class AuthFlowTypeTests: XCTestCase { XCTAssertEqual(String(data: userPassword, encoding: .utf8), "{\"type\":\"USER_PASSWORD_AUTH\"}") let userAuth = try encoder.encode(AuthFlowType.userAuth(preferredFirstFactor: nil)) - XCTAssertTrue(String(data: userAuth, encoding: .utf8)?.contains("\"preferredFirstFactor\":null")) - XCTAssertTrue(String(data: userAuth, encoding: .utf8)?.contains("\"type\":\"USER_AUTH\"")) + XCTAssertTrue(String(data: userAuth, encoding: .utf8)?.contains("\"preferredFirstFactor\":null") == true) + XCTAssertTrue(String(data: userAuth, encoding: .utf8)?.contains("\"type\":\"USER_AUTH\"") == true) } func testDecoding() throws {