Skip to content

Commit 03f5208

Browse files
committed
Merge branch 'dev' into antonioalwan/12_add_automation_wpj_token_binding
* dev: (42 commits) Uninstall xcpretty version 0.4.0 before installing version 0.3.0 Move pipeline to run with Xcode 16 on MacOS 14 (#2456) Revert "Switch PR validation to proper macOS version" Switch PR validation to proper macOS version Revert "Skipping failing E2E tests for macOS due to Keychain access required by the Kevault component" Skipping failing E2E tests for macOS due to Keychain access required by the Kevault component Pass the local test Address comments Use OTP instead of password to customURL Revert "Revert "Address comments"" Revert "Address comments" Address comments Revert "Address comments" Address comments wrong key trigger pipeline tenant_id + replicate name add signInCustomDomain2InSuccess and skip Verify Custom URL Domain - Sign In remove correlation id one because it's out of scope ...
2 parents cfb4bc1 + 3170a7f commit 03f5208

11 files changed

+642
-17
lines changed

MSAL/MSAL.xcodeproj/project.pbxproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@
9595
0D96DB3C27850F0F00DEAF87 /* MSALWipeCacheForAllAccountsConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 0D96DB2E27850E1300DEAF87 /* MSALWipeCacheForAllAccountsConfig.h */; settings = {ATTRIBUTES = (Public, ); }; };
9696
0D96DB3D27850F1100DEAF87 /* MSALWipeCacheForAllAccountsConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 0D96DB2E27850E1300DEAF87 /* MSALWipeCacheForAllAccountsConfig.h */; settings = {ATTRIBUTES = (Public, ); }; };
9797
0D96DB3E27850F1200DEAF87 /* MSALWipeCacheForAllAccountsConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 0D96DB2E27850E1300DEAF87 /* MSALWipeCacheForAllAccountsConfig.h */; settings = {ATTRIBUTES = (Public, ); }; };
98+
12E2160B2D11D3920000F44C /* AuthorityURLFormat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12E2160A2D11D3920000F44C /* AuthorityURLFormat.swift */; };
99+
12E2160C2D11D3920000F44C /* AuthorityURLFormat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12E2160A2D11D3920000F44C /* AuthorityURLFormat.swift */; };
98100
1E04572324BD5A7D00444756 /* MSALCacheItemDetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E04572024BD5A7D00444756 /* MSALCacheItemDetailViewController.m */; };
99101
1E06CD6524D116F800E3D0E5 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D6A206371FC510B500755A51 /* Security.framework */; };
100102
1E1A2E042256D12F001009ED /* MSALTestAppSettings.m in Sources */ = {isa = PBXBuildFile; fileRef = D61A64B01E5AAC5C0086D120 /* MSALTestAppSettings.m */; };
@@ -1922,6 +1924,7 @@
19221924
04D32CCF1FD8AFF3000B123E /* MSALErrorConverterTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MSALErrorConverterTests.m; sourceTree = "<group>"; };
19231925
0D96DB2E27850E1300DEAF87 /* MSALWipeCacheForAllAccountsConfig.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MSALWipeCacheForAllAccountsConfig.h; sourceTree = "<group>"; };
19241926
0D96DB3627850E3900DEAF87 /* MSALWipeCacheForAllAccountsConfig.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MSALWipeCacheForAllAccountsConfig.m; sourceTree = "<group>"; };
1927+
12E2160A2D11D3920000F44C /* AuthorityURLFormat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthorityURLFormat.swift; sourceTree = "<group>"; };
19251928
1E04571F24BD5A7D00444756 /* MSALCacheItemDetailViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MSALCacheItemDetailViewController.h; sourceTree = "<group>"; };
19261929
1E04572024BD5A7D00444756 /* MSALCacheItemDetailViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MSALCacheItemDetailViewController.m; sourceTree = "<group>"; };
19271930
1E1A2E052256D194001009ED /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
@@ -3425,6 +3428,7 @@
34253428
9B235D9E2A3CFB4300657331 /* MSALNativeAuthEndToEndBaseTestCase.swift */,
34263429
2809E8342C3C37B7009F14D7 /* MSALNativeAuthEndToEndPasswordTestCase.swift */,
34273430
280095EA2C32CAFC00F1653E /* ClientIdType.swift */,
3431+
12E2160A2D11D3920000F44C /* AuthorityURLFormat.swift */,
34283432
);
34293433
path = end_to_end;
34303434
sourceTree = "<group>";
@@ -6367,6 +6371,7 @@
63676371
281A0E182C21E1FD00CB30CB /* SignInDelegateSpies.swift in Sources */,
63686372
28A277D92C22ED5E00D95E00 /* MSALNativeAuthEmailCodeRetriever.swift in Sources */,
63696373
E24CE9CC2C57F1160069E2E4 /* AttributesStub.swift in Sources */,
6374+
12E2160B2D11D3920000F44C /* AuthorityURLFormat.swift in Sources */,
63706375
281A0E1B2C21E20600CB30CB /* MSALNativeAuthEndToEndBaseTestCase.swift in Sources */,
63716376
28188F652C8F4C1100CFDD05 /* MFADelegateSpies.swift in Sources */,
63726377
281A0E192C21E20000CB30CB /* MSALNativeAuthResetPasswordEndToEndTests.swift in Sources */,
@@ -7418,6 +7423,7 @@
74187423
DE1BD1062C3C284900B0888E /* SignInDelegateSpies.swift in Sources */,
74197424
DE1BD1072C3C284C00B0888E /* MSALNativeAuthResetPasswordEndToEndTests.swift in Sources */,
74207425
DE9EB8622C5CE44B00328AA4 /* AttributesStub.swift in Sources */,
7426+
12E2160C2D11D3920000F44C /* AuthorityURLFormat.swift in Sources */,
74217427
DE1BD1012C3C283C00B0888E /* MSALNativeAuthSignUpUsernameEndToEndTests.swift in Sources */,
74227428
28188F662C8F4C1100CFDD05 /* MFADelegateSpies.swift in Sources */,
74237429
DE1BD1032C3C284100B0888E /* SignUpDelegateSpies.swift in Sources */,
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//
2+
// Copyright (c) Microsoft Corporation.
3+
// All rights reserved.
4+
//
5+
// This code is licensed under the MIT License.
6+
//
7+
// Permission is hereby granted, free of charge, to any person obtaining a copy
8+
// of this software and associated documentation files(the "Software"), to deal
9+
// in the Software without restriction, including without limitation the rights
10+
// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
11+
// copies of the Software, and to permit persons to whom the Software is
12+
// furnished to do so, subject to the following conditions :
13+
//
14+
// The above copyright notice and this permission notice shall be included in
15+
// all copies or substantial portions of the Software.
16+
//
17+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+
// THE SOFTWARE.
24+
25+
26+
import Foundation
27+
28+
enum AuthorityURLFormat {
29+
case tenantSubdomainShortVersion
30+
case tenantSubdomainLongVersion
31+
case tenantSubdomainTenantId
32+
}

MSAL/test/integration/native_auth/end_to_end/MSALNativeAuthEndToEndBaseTestCase.swift

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ class MSALNativeAuthEndToEndBaseTestCase: XCTestCase {
3333
static let clientIdEmailPasswordAttributesKey = "email_password_attributes_client_id"
3434
static let clientIdEmailCodeAttributesKey = "email_code_attributes_client_id"
3535
static let tenantSubdomainKey = "tenant_subdomain"
36+
static let tenantIdKey = "tenant_id"
3637
static let signInEmailPasswordUsernameKey = "sign_in_email_password_username"
3738
static let signInEmailPasswordMFAUsernameKey = "sign_in_email_password_mfa_username"
3839
static let signInEmailPasswordMFANoDefaultAuthMethodUsernameKey = "sign_in_email_password_mfa_no_default_username"
@@ -71,14 +72,55 @@ class MSALNativeAuthEndToEndBaseTestCase: XCTestCase {
7172

7273
func initialisePublicClientApplication(
7374
clientIdType: ClientIdType = .password,
74-
challengeTypes: MSALNativeAuthChallengeTypes = [.OOB, .password]
75+
challengeTypes: MSALNativeAuthChallengeTypes = [.OOB, .password],
76+
customAuthorityURLFormat: AuthorityURLFormat? = nil
7577
) -> MSALNativeAuthPublicClientApplication? {
7678
let clientIdKey = getClientIdKey(type: clientIdType)
77-
guard let clientId = MSALNativeAuthEndToEndBaseTestCase.nativeAuthConfFileContent?[clientIdKey] as? String, let tenantSubdomain = MSALNativeAuthEndToEndBaseTestCase.nativeAuthConfFileContent?[Constants.tenantSubdomainKey] as? String else {
78-
XCTFail("ClientId or tenantSubdomain not found in conf.json")
79+
guard let clientId = MSALNativeAuthEndToEndBaseTestCase.nativeAuthConfFileContent?[clientIdKey] as? String else {
80+
XCTFail("ClientId not found in conf.json")
7981
return nil
8082
}
81-
return try? MSALNativeAuthPublicClientApplication(clientId: clientId, tenantSubdomain: tenantSubdomain, challengeTypes: challengeTypes)
83+
84+
guard let tenantSubdomain = MSALNativeAuthEndToEndBaseTestCase.nativeAuthConfFileContent?[Constants.tenantSubdomainKey] as? String else {
85+
XCTFail("TenantSubdomain not found in conf.json")
86+
return nil
87+
}
88+
89+
guard let tenantId = MSALNativeAuthEndToEndBaseTestCase.nativeAuthConfFileContent?[Constants.tenantIdKey] as? String else {
90+
XCTFail("TenantId not found in conf.json")
91+
return nil
92+
}
93+
94+
95+
if let customAuthorityURLFormat = customAuthorityURLFormat {
96+
let customSubdomain = getAuthorityURLString(
97+
tenantSubdomain: tenantSubdomain,
98+
tenantId: tenantId,
99+
format: customAuthorityURLFormat
100+
)
101+
102+
let authority = try? MSALCIAMAuthority(
103+
url: URL(string: customSubdomain)!,
104+
validateFormat: false
105+
)
106+
107+
let configuration = MSALPublicClientApplicationConfig(
108+
clientId: clientId,
109+
redirectUri: nil,
110+
authority: authority
111+
)
112+
113+
return try? MSALNativeAuthPublicClientApplication(
114+
configuration: configuration,
115+
challengeTypes: challengeTypes
116+
)
117+
} else {
118+
return try? MSALNativeAuthPublicClientApplication(
119+
clientId: clientId,
120+
tenantSubdomain: tenantSubdomain,
121+
challengeTypes: challengeTypes
122+
)
123+
}
82124
}
83125

84126
func generateSignUpRandomEmail() -> String {
@@ -129,4 +171,15 @@ class MSALNativeAuthEndToEndBaseTestCase: XCTestCase {
129171
return Constants.clientIdEmailCodeAttributesKey
130172
}
131173
}
174+
175+
private func getAuthorityURLString(tenantSubdomain: String, tenantId: String, format: AuthorityURLFormat) -> String {
176+
switch format {
177+
case .tenantSubdomainShortVersion:
178+
return String(format: "https://%@.ciamlogin.com/", tenantSubdomain)
179+
case .tenantSubdomainLongVersion:
180+
return String(format: "https://%@.ciamlogin.com/%@.onmicrosoft.com", tenantSubdomain, tenantSubdomain)
181+
case .tenantSubdomainTenantId:
182+
return String(format: "https://%@.ciamlogin.com/%@", tenantSubdomain, tenantId)
183+
}
184+
}
132185
}

MSAL/test/integration/native_auth/end_to_end/mfa/MSALNativeAuthSignInWithMFAEndToEndTests.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ import MSAL
2929
final class MSALNativeAuthSignInWithMFAEndToEndTests: MSALNativeAuthEndToEndPasswordTestCase {
3030

3131
func test_signInUsingPasswordWithMFASubmitWrongChallengeResendChallengeThen_completeSuccessfully() async throws {
32+
#if os(macOS)
33+
throw XCTSkip("For some reason this test now requires Keychain access, reason needs to be investigated")
34+
#endif
3235
guard let username = retrieveUsernameForSignInUsernamePasswordAndMFA(),
3336
let password = await retrievePasswordForSignInUsername(),
3437
let awaitingMFAState = await signInUsernameAndPassword(username: username, password: password)
@@ -85,6 +88,9 @@ final class MSALNativeAuthSignInWithMFAEndToEndTests: MSALNativeAuthEndToEndPass
8588
}
8689

8790
func test_signInUsingPasswordWithMFAGetAuthMethods_thenCompleteSuccessfully() async throws {
91+
#if os(macOS)
92+
throw XCTSkip("For some reason this test now requires Keychain access, reason needs to be investigated")
93+
#endif
8894
guard let username = retrieveUsernameForSignInUsernamePasswordAndMFA(),
8995
let password = await retrievePasswordForSignInUsername(),
9096
let awaitingMFAState = await signInUsernameAndPassword(username: username, password: password)
@@ -140,6 +146,9 @@ final class MSALNativeAuthSignInWithMFAEndToEndTests: MSALNativeAuthEndToEndPass
140146
}
141147

142148
func test_signInUsingPasswordWithMFANoDefaultAuthMethod_completeSuccessfully() async throws {
149+
#if os(macOS)
150+
throw XCTSkip("For some reason this test now requires Keychain access, reason needs to be investigated")
151+
#endif
143152
guard let username = retrieveUsernameForSignInUsernamePasswordAndMFANoDefaultAuthMethod(),
144153
let password = await retrievePasswordForSignInUsername(),
145154
let awaitingMFAState = await signInUsernameAndPassword(username: username, password: password)

MSAL/test/integration/native_auth/end_to_end/sign_in/MSALNativeAuthSignInUserNameAndPasswordEndToEndTests.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ final class MSALNativeAuthSignInUsernameAndPasswordEndToEndTests: MSALNativeAuth
6666

6767
// Hero Scenario 1.2.1. Sign in - Use email and password to get token
6868
func test_signInUsingPasswordWithKnownUsernameResultsInSuccess() async throws {
69+
#if os(macOS)
70+
throw XCTSkip("For some reason this test now requires Keychain access, reason needs to be investigated")
71+
#endif
6972
guard let sut = initialisePublicClientApplication(), let username = retrieveUsernameForSignInUsernameAndPassword(), let password = await retrievePasswordForSignInUsername() else {
7073
XCTFail("Missing information")
7174
return

MSAL/test/integration/native_auth/end_to_end/sign_in/MSALNativeAuthSignInUsernameEndToEndTests.swift

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,4 +125,130 @@ final class MSALNativeAuthSignInUsernameEndToEndTests: MSALNativeAuthEndToEndBas
125125
XCTAssertNotNil(signInVerifyCodeDelegateSpy.result?.idToken)
126126
XCTAssertEqual(signInVerifyCodeDelegateSpy.result?.account.username, username)
127127
}
128+
129+
// Sign In - Verify Custom URL Domain - "https://<tenantName>.ciamlogin.com/<tenantName>.onmicrosoft.com"
130+
func test_signInCustomSubdomainLongInSuccess() async throws {
131+
guard let sut = initialisePublicClientApplication(clientIdType: .code, customAuthorityURLFormat: .tenantSubdomainLongVersion), let username = retrieveUsernameForSignInCode() else {
132+
XCTFail("Missing information")
133+
return
134+
}
135+
136+
let signInExpectation = expectation(description: "signing in")
137+
let signInDelegateSpy = SignInStartDelegateSpy(expectation: signInExpectation)
138+
139+
sut.signIn(username: username, correlationId: correlationId, delegate: signInDelegateSpy)
140+
141+
await fulfillment(of: [signInExpectation])
142+
143+
guard signInDelegateSpy.onSignInCodeRequiredCalled else {
144+
XCTFail("onSignInCodeRequired not called")
145+
return
146+
}
147+
148+
XCTAssertNotNil(signInDelegateSpy.newStateCodeRequired)
149+
XCTAssertNotNil(signInDelegateSpy.sentTo)
150+
151+
// Now submit the code..
152+
153+
guard let code = await retrieveCodeFor(email: username) else {
154+
XCTFail("OTP code could not be retrieved")
155+
return
156+
}
157+
158+
let verifyCodeExpectation = expectation(description: "verifying code")
159+
let signInVerifyCodeDelegateSpy = SignInVerifyCodeDelegateSpy(expectation: verifyCodeExpectation)
160+
161+
signInDelegateSpy.newStateCodeRequired?.submitCode(code: code, delegate: signInVerifyCodeDelegateSpy)
162+
163+
await fulfillment(of: [verifyCodeExpectation])
164+
165+
XCTAssertTrue(signInVerifyCodeDelegateSpy.onSignInCompletedCalled)
166+
XCTAssertNotNil(signInVerifyCodeDelegateSpy.result)
167+
XCTAssertNotNil(signInVerifyCodeDelegateSpy.result?.idToken)
168+
XCTAssertEqual(signInVerifyCodeDelegateSpy.result?.account.username, username)
169+
}
170+
171+
// Sign In - Verify Custom URL Domain - "https://<tenantName>.ciamlogin.com/<tenantId>"
172+
func test_signInCustomSubdomainIdInSuccess() async throws {
173+
guard let sut = initialisePublicClientApplication(clientIdType: .code, customAuthorityURLFormat: .tenantSubdomainTenantId), let username = retrieveUsernameForSignInCode() else {
174+
XCTFail("Missing information")
175+
return
176+
}
177+
178+
let signInExpectation = expectation(description: "signing in")
179+
let signInDelegateSpy = SignInStartDelegateSpy(expectation: signInExpectation)
180+
181+
sut.signIn(username: username, correlationId: correlationId, delegate: signInDelegateSpy)
182+
183+
await fulfillment(of: [signInExpectation])
184+
185+
guard signInDelegateSpy.onSignInCodeRequiredCalled else {
186+
XCTFail("onSignInCodeRequired not called")
187+
return
188+
}
189+
190+
XCTAssertNotNil(signInDelegateSpy.newStateCodeRequired)
191+
XCTAssertNotNil(signInDelegateSpy.sentTo)
192+
193+
// Now submit the code..
194+
195+
guard let code = await retrieveCodeFor(email: username) else {
196+
XCTFail("OTP code could not be retrieved")
197+
return
198+
}
199+
200+
let verifyCodeExpectation = expectation(description: "verifying code")
201+
let signInVerifyCodeDelegateSpy = SignInVerifyCodeDelegateSpy(expectation: verifyCodeExpectation)
202+
203+
signInDelegateSpy.newStateCodeRequired?.submitCode(code: code, delegate: signInVerifyCodeDelegateSpy)
204+
205+
await fulfillment(of: [verifyCodeExpectation])
206+
207+
XCTAssertTrue(signInVerifyCodeDelegateSpy.onSignInCompletedCalled)
208+
XCTAssertNotNil(signInVerifyCodeDelegateSpy.result)
209+
XCTAssertNotNil(signInVerifyCodeDelegateSpy.result?.idToken)
210+
XCTAssertEqual(signInVerifyCodeDelegateSpy.result?.account.username, username)
211+
}
212+
213+
// Sign In - Verify Custom URL Domain - "https://<tenantName>.ciamlogin.com/"
214+
func test_signInCustomSubdomainShortInSuccess() async throws {
215+
guard let sut = initialisePublicClientApplication(clientIdType: .code, customAuthorityURLFormat: .tenantSubdomainShortVersion), let username = retrieveUsernameForSignInCode() else {
216+
XCTFail("Missing information")
217+
return
218+
}
219+
220+
let signInExpectation = expectation(description: "signing in")
221+
let signInDelegateSpy = SignInStartDelegateSpy(expectation: signInExpectation)
222+
223+
sut.signIn(username: username, correlationId: correlationId, delegate: signInDelegateSpy)
224+
225+
await fulfillment(of: [signInExpectation])
226+
227+
guard signInDelegateSpy.onSignInCodeRequiredCalled else {
228+
XCTFail("onSignInCodeRequired not called")
229+
return
230+
}
231+
232+
XCTAssertNotNil(signInDelegateSpy.newStateCodeRequired)
233+
XCTAssertNotNil(signInDelegateSpy.sentTo)
234+
235+
// Now submit the code..
236+
237+
guard let code = await retrieveCodeFor(email: username) else {
238+
XCTFail("OTP code could not be retrieved")
239+
return
240+
}
241+
242+
let verifyCodeExpectation = expectation(description: "verifying code")
243+
let signInVerifyCodeDelegateSpy = SignInVerifyCodeDelegateSpy(expectation: verifyCodeExpectation)
244+
245+
signInDelegateSpy.newStateCodeRequired?.submitCode(code: code, delegate: signInVerifyCodeDelegateSpy)
246+
247+
await fulfillment(of: [verifyCodeExpectation])
248+
249+
XCTAssertTrue(signInVerifyCodeDelegateSpy.onSignInCompletedCalled)
250+
XCTAssertNotNil(signInVerifyCodeDelegateSpy.result)
251+
XCTAssertNotNil(signInVerifyCodeDelegateSpy.result?.idToken)
252+
XCTAssertEqual(signInVerifyCodeDelegateSpy.result?.account.username, username)
253+
}
128254
}

0 commit comments

Comments
 (0)