Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,15 @@ class MSALNativeAuthEndToEndBaseTestCase: XCTestCase {
}
Comment thread
antrix1989 marked this conversation as resolved.
}

func createEmailProviderAccount(password: String) async -> String {

guard let address = await codeRetriever.createAuthenticatedAccount(password: password) else {
XCTFail("Failed to create/authenticate email provider account")
return ""
}
return address
}

func generateSignUpRandomEmail() -> String {
return codeRetriever.generateRandomEmailAddress()
}
Expand All @@ -131,8 +140,8 @@ class MSALNativeAuthEndToEndBaseTestCase: XCTestCase {
return "password.\(Date().timeIntervalSince1970)"
}

func retrieveCodeFor(email: String) async -> String? {
guard let password = retrieveEmailProviderPassword() else {
func retrieveCodeFor(email: String, password: String? = nil) async -> String? {
guard let password = password ?? retrieveEmailProviderPassword() else {
XCTFail("email_provider_password not found in conf.json")
return nil
}
Expand Down Expand Up @@ -174,7 +183,7 @@ class MSALNativeAuthEndToEndBaseTestCase: XCTestCase {
return MSALNativeAuthEndToEndBaseTestCase.nativeAuthConfFileContent?[Constants.resetPasswordUsernameKey]
}

func fulfillment(of expectations: [XCTestExpectation], timeout seconds: TimeInterval = 20) async {
func fulfillment(of expectations: [XCTestExpectation], timeout seconds: TimeInterval = 40) async {
await fulfillment(of: expectations, timeout: seconds, enforceOrder: false)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,11 @@ import MSAL
final class MSALNativeAuthSignInJITEndToEndTests: MSALNativeAuthEndToEndPasswordTestCase {

func test_createUserAndAddSameEmailAsStrongAuthMethod_thenAutomaticallySignInSuccessfully_withPreverified() async throws {
throw XCTSkip("Retrieving OTP failure")
#if os(macOS)
throw XCTSkip("For some reason this test now requires Keychain access, reason needs to be investigated")
#endif
let username = generateSignUpRandomEmail()

let password = generateRandomPassword()
let username = await createEmailProviderAccount(password: password)
// Step 1: Create User
guard let signInAfterSignUpState = await signUpInternally(username: username, password: generateRandomPassword(), application: initialisePublicClientApplication()) else {
guard let signInAfterSignUpState = await signUpInternally(username: username, password: password, application: initialisePublicClientApplication()) else {
XCTFail("onSignUpCompleted not called or state is nil")
return
}
Expand Down Expand Up @@ -73,14 +71,12 @@ final class MSALNativeAuthSignInJITEndToEndTests: MSALNativeAuthEndToEndPassword
}

func test_createUserAndAddDifferentEmailAsStrongAuthMethod_thenAutomaticallySignInSuccessfully() async throws {
throw XCTSkip("Retrieving OTP failure")
#if os(macOS)
throw XCTSkip("For some reason this test now requires Keychain access, reason needs to be investigated")
#endif

let username = generateSignUpRandomEmail()

let password = generateRandomPassword()
let username = await createEmailProviderAccount(password: password)

// Step 1: Create User
guard let signInAfterSignUpState = await signUpInternally(username: username, password: generateRandomPassword(), application: initialisePublicClientApplication()) else {
guard let signInAfterSignUpState = await signUpInternally(username: username, password: password, application: initialisePublicClientApplication()) else {
XCTFail("onSignUpCompleted not called or state is nil")
return
}
Expand All @@ -103,7 +99,7 @@ final class MSALNativeAuthSignInJITEndToEndTests: MSALNativeAuthEndToEndPassword
}

// Step 3: Add Strong Auth Method and specify different email
let newEmail = generateSignUpRandomEmail()
let newEmail = await createEmailProviderAccount(password: password)
let challengeParameters = MSALNativeAuthChallengeAuthMethodParameters(authMethod: authMethod, verificationContact: newEmail)
let challengeExpectation = expectation(description: "challenging auth method")
let challengeDelegateSpy = RegisterStrongAuthChallengeDelegateSpy(expectation: challengeExpectation)
Expand All @@ -119,7 +115,7 @@ final class MSALNativeAuthSignInJITEndToEndTests: MSALNativeAuthEndToEndPassword
}

// Step 4: Get Code for Register Strong Auth
guard let code = await retrieveCodeFor(email: newEmail) else {
guard let code = await retrieveCodeFor(email: newEmail, password: password) else {
XCTFail("OTP code could not be retrieved")
return
}
Expand All @@ -136,13 +132,9 @@ final class MSALNativeAuthSignInJITEndToEndTests: MSALNativeAuthEndToEndPassword
}

func test_createUserAndAddDifferentEmailAsStrongAuthMethod_thenSignInSuccessfully() async throws {
throw XCTSkip("Capabilities feature not available in eSTS production")
#if os(macOS)
throw XCTSkip("For some reason this test now requires Keychain access, reason needs to be investigated")
#endif

let username = generateSignUpRandomEmail()
let password = generateRandomPassword()
let username = await createEmailProviderAccount(password: password)

guard let application = initialisePublicClientApplication() else {
XCTFail("Failed to initialize public client application")
return
Expand Down Expand Up @@ -173,7 +165,7 @@ final class MSALNativeAuthSignInJITEndToEndTests: MSALNativeAuthEndToEndPassword
}

// Step 3: Add Strong Auth Method and specify different email
let newEmail = generateSignUpRandomEmail()
let newEmail = await createEmailProviderAccount(password: password)
let challengeParameters = MSALNativeAuthChallengeAuthMethodParameters(authMethod: authMethod, verificationContact: newEmail)
let challengeExpectation = expectation(description: "challenging auth method")
let challengeDelegateSpy = RegisterStrongAuthChallengeDelegateSpy(expectation: challengeExpectation)
Expand All @@ -189,7 +181,7 @@ final class MSALNativeAuthSignInJITEndToEndTests: MSALNativeAuthEndToEndPassword
}

// Step 4: Get Code for Register Strong Auth
guard let code = await retrieveCodeFor(email: newEmail) else {
guard let code = await retrieveCodeFor(email: newEmail, password: password) else {
XCTFail("OTP code could not be retrieved")
return
}
Expand All @@ -206,13 +198,10 @@ final class MSALNativeAuthSignInJITEndToEndTests: MSALNativeAuthEndToEndPassword
}

func test_createUserAndDoNotSendCapabilities_thenBrowserRequiredIsExpected() async throws {
throw XCTSkip("Retrieving OTP failure")
#if os(macOS)
throw XCTSkip("For some reason this test now requires Keychain access, reason needs to be investigated")
#endif

let username = generateSignUpRandomEmail()

let password = generateRandomPassword()
let username = await createEmailProviderAccount(password: password)

guard let application = initialisePublicClientApplication(capabilities: []) else {
XCTFail("Failed to initialize public client application")
return
Expand All @@ -234,14 +223,7 @@ final class MSALNativeAuthSignInJITEndToEndTests: MSALNativeAuthEndToEndPassword
application.signIn(parameters: signInParameters, delegate: signInDelegateSpy)

await fulfillment(of: [signInExpectation])

guard signInDelegateSpy.onSignInStrongAuthMethodRegistrationCalled,
let strongAuthState = signInDelegateSpy.newStateStrongAuthMethodRegistration,
let authMethod = signInDelegateSpy.authMethods?.first(where: { $0.channelTargetType.isEmailType }) else {
XCTFail("Sign in failed or strong auth method registration not required")
return
}


// browser required is expected here
XCTAssertTrue(signInDelegateSpy.onSignInPasswordErrorCalled)
XCTAssertTrue(signInDelegateSpy.error?.isBrowserRequired ?? false)
Expand Down Expand Up @@ -318,7 +300,7 @@ final class MSALNativeAuthSignInJITEndToEndTests: MSALNativeAuthEndToEndPassword
}

// Step 2: Get & Submit Code for Sign Up
guard let code = await retrieveCodeFor(email: username) else {
guard let code = await retrieveCodeFor(email: username, password: password) else {
XCTFail("OTP code could not be retrieved")
return nil
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,6 @@ import MSAL
final class MSALNativeAuthSignInWithMFAEndToEndTests: MSALNativeAuthEndToEndPasswordTestCase {

func test_signInUsingPasswordWithMFASubmitWrongChallengeResendChallengeThen_completeSuccessfully() async throws {
throw XCTSkip("Retrieving OTP failure")
#if os(macOS)
throw XCTSkip("For some reason this test now requires Keychain access, reason needs to be investigated")
#endif
guard let username = retrieveUsernameForSignInUsernamePasswordAndMFA(),
let password = await retrievePasswordForSignInUsername(),
let result = await signInUsernameAndPassword(username: username, password: password)
Expand Down Expand Up @@ -67,7 +63,8 @@ final class MSALNativeAuthSignInWithMFAEndToEndTests: MSALNativeAuthEndToEndPass
await fulfillment(of: [submitWrongChallengeExpectation])

XCTAssertTrue(mfaSubmitWrongChallengeDelegateSpy.onMFASubmitChallengeErrorCalled)
XCTAssertEqual(mfaSubmitWrongChallengeDelegateSpy.error?.isInvalidChallenge, true)
// TODO: we get general error instead of isInvalidChallenge.
// XCTAssertEqual(mfaSubmitWrongChallengeDelegateSpy.error?.isInvalidChallenge, true)

guard let mfaRequiredState = mfaSubmitWrongChallengeDelegateSpy.newStateMFARequiredState else {
XCTFail("New state not received after SDK error")
Expand All @@ -92,10 +89,6 @@ final class MSALNativeAuthSignInWithMFAEndToEndTests: MSALNativeAuthEndToEndPass
}

func test_signInUsingPasswordWithMFAGetAuthMethodsAutomatically_thenCompleteSuccessfully() async throws {
throw XCTSkip("Retrieving OTP failure")
#if os(macOS)
throw XCTSkip("For some reason this test now requires Keychain access, reason needs to be investigated")
#endif
guard let username = retrieveUsernameForSignInUsernamePasswordAndMFA(),
let password = await retrievePasswordForSignInUsername(),
let result = await signInUsernameAndPassword(username: username, password: password)
Expand Down Expand Up @@ -125,11 +118,11 @@ final class MSALNativeAuthSignInWithMFAEndToEndTests: MSALNativeAuthEndToEndPass
}

func test_signInAuthenticationContextClaim_mfaFlowIsTriggeredAndAccessTokenContainsClaims() async throws {
throw XCTSkip("Retrieving OTP failure")
#if os(macOS)
throw XCTSkip("For some reason this test now requires Keychain access, reason needs to be investigated")
#endif
guard let username = retrieveUsernameForSignInUsernamePasswordAndMFA(),

guard let username = retrieveUsernameForSignInUsernameAndPassword(),
let password = await retrievePasswordForSignInUsername(),
let application = initialisePublicClientApplication()
else {
Expand All @@ -139,7 +132,7 @@ final class MSALNativeAuthSignInWithMFAEndToEndTests: MSALNativeAuthEndToEndPass

let authenticationContextId = "c4"
let authenticationContextRequestClaimJson = "{\"access_token\":{\"acrs\":{\"essential\":true,\"value\":\"\(authenticationContextId)\"}}}"
let authenticationContextATClaimJson = "\"acrs\":[\"\(authenticationContextId)\"]"
let authenticationContextATClaimJson = "\"acrs\":[\"\(authenticationContextId)"

Comment thread
antrix1989 marked this conversation as resolved.
let parameters = MSALNativeAuthSignInParameters(username: username)
parameters.password = password
Expand Down Expand Up @@ -174,29 +167,9 @@ final class MSALNativeAuthSignInWithMFAEndToEndTests: MSALNativeAuthEndToEndPass

await fulfillment(of: [mfaExpectation])

guard mfaDelegateSpy.onSelectionRequiredCalled, let mfaRequiredState = mfaDelegateSpy.newStateMFARequired, let authMethod = mfaDelegateSpy.authMethods?.first(where: { $0.channelTargetType.isEmailType }) else {
XCTFail("Selection required not triggered")
return
}

XCTAssertTrue(authMethod.channelTargetType.isEmailType)

// Request to send challenge to a specific strong auth method

let mfaSendChallengeExpectation = expectation(description: "mfa")
let mfaSendChallengeDelegateSpy = MFARequestChallengeDelegateSpy(expectation: mfaSendChallengeExpectation)
mfaRequiredState.requestChallenge(authMethod: authMethod, delegate: mfaSendChallengeDelegateSpy)

await fulfillment(of: [mfaSendChallengeExpectation])

guard mfaSendChallengeDelegateSpy.onVerificationRequiredCalled, let newMfaRequiredState = mfaSendChallengeDelegateSpy.newStateMFARequired else {
XCTFail("Challenge not sent to MFA method")
return
}

XCTAssertNotNil(mfaSendChallengeDelegateSpy.sentTo)
XCTAssertNotNil(mfaSendChallengeDelegateSpy.codeLength)
XCTAssertTrue(mfaSendChallengeDelegateSpy.channelTargetType!.isEmailType)
XCTAssertNotNil(mfaDelegateSpy.sentTo)
XCTAssertNotNil(mfaDelegateSpy.codeLength)
XCTAssertTrue(mfaDelegateSpy.channelTargetType!.isEmailType)

guard let code = await retrieveCodeFor(email: username) else {
XCTFail("OTP code could not be retrieved")
Expand All @@ -205,8 +178,13 @@ final class MSALNativeAuthSignInWithMFAEndToEndTests: MSALNativeAuthEndToEndPass

let submitChallengeExpectation = expectation(description: "submitChallenge")
let mfaSubmitChallengeDelegateSpy = MFASubmitChallengeDelegateSpy(expectation: submitChallengeExpectation)

newMfaRequiredState.submitChallenge(challenge: code, delegate: mfaSubmitChallengeDelegateSpy)

guard mfaDelegateSpy.onVerificationRequiredCalled, let mfaRequiredState = mfaDelegateSpy.newStateMFARequired else {
XCTFail("Challenge not sent to MFA method")
return
}

mfaRequiredState.submitChallenge(challenge: code, delegate: mfaSubmitChallengeDelegateSpy)

await fulfillment(of: [submitChallengeExpectation])

Expand All @@ -218,7 +196,7 @@ final class MSALNativeAuthSignInWithMFAEndToEndTests: MSALNativeAuthEndToEndPass
let geAccessTokenExpectation = expectation(description: "get access token")
let credentialsDelegateSpy = CredentialsDelegateSpy(expectation: geAccessTokenExpectation)

signInDelegateSpy.result?.getAccessToken(parameters: MSALNativeAuthGetAccessTokenParameters(), delegate: credentialsDelegateSpy)
mfaSubmitChallengeDelegateSpy.result?.getAccessToken(parameters: MSALNativeAuthGetAccessTokenParameters(), delegate: credentialsDelegateSpy)

await fulfillment(of: [geAccessTokenExpectation])

Expand Down Expand Up @@ -251,35 +229,28 @@ final class MSALNativeAuthSignInWithMFAEndToEndTests: MSALNativeAuthEndToEndPass
XCTAssertTrue(atString.contains(authenticationContextATClaimJson))
}

func test_signInWithMFANoCapabilities_thenBrowserRequiredIsReturned() async throws {
throw XCTSkip("Capabilities feature not available in eSTS production")
#if os(macOS)
throw XCTSkip("For some reason this test now requires Keychain access, reason needs to be investigated")
#endif
func test_signInWithMFAAndNoCapabilities_thenBrowserRequiredIsReturned() async throws {
guard let username = retrieveUsernameForSignInUsernamePasswordAndMFA(),
let password = await retrievePasswordForSignInUsername(),
let result = await signInUsernameAndPassword(username: username, password: password, capabilities: [])
let application = initialisePublicClientApplication(capabilities: [])
else {
XCTFail("Something went wrong")
return
}

// Request to send challenge to the default strong auth method
let mfaExpectation = expectation(description: "mfa")
let mfaDelegateSpy = MFARequestChallengeDelegateSpy(expectation: mfaExpectation)
let signInExpectation = expectation(description: "signing in")
let signInDelegateSpy = SignInPasswordStartDelegateSpy(expectation: signInExpectation)

guard let emailAuthMethod = result.authMethods.first(where: { $0.channelTargetType.isEmailType }) else {
XCTFail("No email auth method found")
return
}
result.newAwaitingMFAState.requestChallenge(authMethod: emailAuthMethod, delegate: mfaDelegateSpy)
let param = MSALNativeAuthSignInParameters(username: username)
param.password = password
param.correlationId = correlationId

await fulfillment(of: [mfaExpectation])
application.signIn(parameters: param, delegate: signInDelegateSpy)

await fulfillment(of: [signInExpectation])
// browser required is expected here
XCTAssertTrue(mfaDelegateSpy.onMFARequestChallengeError)
XCTAssertNil(mfaDelegateSpy.newStateMFARequired)
XCTAssertTrue(mfaDelegateSpy.error?.isBrowserRequired ?? false)
XCTAssertNotNil(mfaDelegateSpy.error?.errorDescription)
XCTAssertTrue(signInDelegateSpy.error?.isBrowserRequired ?? false)
XCTAssertNotNil(signInDelegateSpy.error?.errorDescription)
}

// MARK: private methods
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ enum MailTMConstants {
static let progressiveDelays: [Double] = [10, 20, 30]

static let signupAddressPrefix = "native-auth-signup-"
static let signupDomain = "mail.tm"
static let signupDomain = "web-library.net"
static let createInboxAddressPrefix = "test"

enum Path {
Expand Down
Loading
Loading