Skip to content

Commit a965fbb

Browse files
authored
Merge pull request #626 from AzureAD/add-ciam-authority
Support new CIAM authority
2 parents 891ddfe + 9d4e1dd commit a965fbb

File tree

14 files changed

+206
-31
lines changed

14 files changed

+206
-31
lines changed

msal4j-sdk/src/integrationtest/java/com.microsoft.aad.msal4j/AcquireTokenInteractiveIT.java

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,7 @@
33

44
package com.microsoft.aad.msal4j;
55

6-
import labapi.AzureEnvironment;
7-
import labapi.B2CProvider;
8-
import labapi.FederationProvider;
9-
import labapi.User;
6+
import labapi.*;
107
import org.slf4j.Logger;
118
import org.slf4j.LoggerFactory;
129
import org.testng.Assert;
@@ -16,6 +13,8 @@
1613
import java.net.URI;
1714
import java.net.URL;
1815
import java.util.Collections;
16+
import java.util.HashMap;
17+
import java.util.Map;
1918
import java.util.concurrent.ExecutionException;
2019

2120
public class AcquireTokenInteractiveIT extends SeleniumTest {
@@ -73,7 +72,45 @@ public void acquireTokenInteractive_ADFSv2_Federated(String environment) {
7372
public void acquireTokenInteractive_Ciam() {
7473
User user = labUserProvider.getCiamUser();
7574

76-
assertAcquireTokenCommon(user, TestConstants.CIAM_AUTHORITY, TestConstants.GRAPH_DEFAULT_SCOPE);
75+
Map<String, String> extraQueryParameters = new HashMap<>();
76+
extraQueryParameters.put("dc","ESTS-PUB-EUS-AZ1-FD000-TEST1");
77+
78+
PublicClientApplication pca;
79+
try {
80+
pca = PublicClientApplication.builder(
81+
user.getAppId()).
82+
authority("https://" + user.getLabName() + ".ciamlogin.com/")
83+
.build();
84+
} catch (MalformedURLException ex) {
85+
throw new RuntimeException(ex.getMessage());
86+
}
87+
88+
IAuthenticationResult result;
89+
try {
90+
URI url = new URI("http://localhost:8080");
91+
92+
SystemBrowserOptions browserOptions =
93+
SystemBrowserOptions
94+
.builder()
95+
.openBrowserAction(new SeleniumOpenBrowserAction(user, pca))
96+
.build();
97+
98+
InteractiveRequestParameters parameters = InteractiveRequestParameters
99+
.builder(url)
100+
.scopes(Collections.singleton(TestConstants.GRAPH_DEFAULT_SCOPE))
101+
.extraQueryParameters(extraQueryParameters)
102+
.systemBrowserOptions(browserOptions)
103+
.build();
104+
105+
result = pca.acquireToken(parameters).get();
106+
107+
} catch (Exception e) {
108+
LOG.error("Error acquiring token with authCode: " + e.getMessage());
109+
throw new RuntimeException("Error acquiring token with authCode: " + e.getMessage());
110+
}
111+
112+
assertTokenResultNotNull(result);
113+
Assert.assertEquals(user.getUpn(), result.account().username());
77114
}
78115

79116
@Test(dataProvider = "environments", dataProviderClass = EnvironmentsProvider.class)

msal4j-sdk/src/integrationtest/java/com.microsoft.aad.msal4j/ClientCredentialsIT.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import labapi.AppCredentialProvider;
77
import labapi.AzureEnvironment;
88
import labapi.LabUserProvider;
9+
import labapi.User;
910
import org.testng.Assert;
1011
import org.testng.annotations.BeforeClass;
1112
import org.testng.annotations.DataProvider;
@@ -18,6 +19,8 @@
1819
import java.security.UnrecoverableKeyException;
1920
import java.security.cert.CertificateException;
2021
import java.util.Collections;
22+
import java.util.HashMap;
23+
import java.util.Map;
2124
import java.util.concurrent.Callable;
2225

2326
import static com.microsoft.aad.msal4j.TestConstants.KEYVAULT_DEFAULT_SCOPE;
@@ -62,11 +65,29 @@ public void acquireTokenClientCredentials_ClientAssertion() throws Exception {
6265

6366
@Test
6467
public void acquireTokenClientCredentials_ClientSecret_Ciam() throws Exception {
65-
String clientId = labUserProvider.getCiamUser().getAppId();
68+
69+
User user = labUserProvider.getCiamUser();
70+
String clientId = user.getAppId();
71+
72+
Map<String, String> extraQueryParameters = new HashMap<>();
73+
extraQueryParameters.put("dc","ESTS-PUB-EUS-AZ1-FD000-TEST1");
6674

6775
AppCredentialProvider appProvider = new AppCredentialProvider(AzureEnvironment.CIAM);
6876
IClientCredential credential = ClientCredentialFactory.createFromSecret(appProvider.getOboAppPassword());
6977

78+
ConfidentialClientApplication cca = ConfidentialClientApplication.builder(
79+
clientId, credential).
80+
authority("https://" + user.getLabName() + ".ciamlogin.com/").
81+
build();
82+
83+
IAuthenticationResult result = cca.acquireToken(ClientCredentialParameters
84+
.builder(Collections.singleton(TestConstants.GRAPH_DEFAULT_SCOPE))
85+
.extraQueryParameters(extraQueryParameters)
86+
.build())
87+
.get();
88+
89+
Assert.assertNotNull(result);
90+
Assert.assertNotNull(result.accessToken());
7091
assertAcquireTokenCommon(clientId, credential, TestConstants.CIAM_AUTHORITY);
7192
}
7293

msal4j-sdk/src/integrationtest/java/com.microsoft.aad.msal4j/DeviceCodeIT.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,7 @@ public void DeviceCodeFlowADTest(String environment) throws Exception {
4343
authority(cfg.tenantSpecificAuthority()).
4444
build();
4545

46-
Consumer<DeviceCode> deviceCodeConsumer = (DeviceCode deviceCode) -> {
47-
runAutomatedDeviceCodeFlow(deviceCode, user);
48-
};
46+
Consumer<DeviceCode> deviceCodeConsumer = (DeviceCode deviceCode) -> runAutomatedDeviceCodeFlow(deviceCode, user);
4947

5048
IAuthenticationResult result = pca.acquireToken(DeviceCodeFlowParameters
5149
.builder(Collections.singleton(cfg.graphDefaultScope()),
@@ -119,7 +117,7 @@ public void DeviceCodeFlowCiamTest() throws Exception {
119117

120118
PublicClientApplication pca = PublicClientApplication.builder(
121119
user.getAppId()).
122-
authority(TestConstants.CIAM_AUTHORITY).
120+
authority("https://" + user.getLabName() + ".ciamlogin.com/").
123121
build();
124122

125123
Consumer<DeviceCode> deviceCodeConsumer = (DeviceCode deviceCode) -> {
@@ -174,7 +172,7 @@ private void runAutomatedDeviceCodeFlow(DeviceCode deviceCode, User user) {
174172
if (isADFS2019) {
175173
SeleniumExtensions.performADFS2019Login(seleniumDriver, user);
176174
} else {
177-
SeleniumExtensions.performADLogin(seleniumDriver, user);
175+
SeleniumExtensions.performADOrCiamLogin(seleniumDriver, user);
178176
}
179177
} catch (Exception e) {
180178
if (!isRunningLocally) {

msal4j-sdk/src/integrationtest/java/com.microsoft.aad.msal4j/SeleniumTest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,11 @@ void runSeleniumAutomatedLogin(User user, AbstractClientApplicationBase app) {
5151
break;
5252
}
5353
} else if (authorityType == AuthorityType.AAD) {
54-
SeleniumExtensions.performADLogin(seleniumDriver, user);
54+
SeleniumExtensions.performADOrCiamLogin(seleniumDriver, user);
5555
} else if (authorityType == AuthorityType.ADFS) {
5656
SeleniumExtensions.performADFS2019Login(seleniumDriver, user);
57+
} else if (authorityType == AuthorityType.CIAM) {
58+
SeleniumExtensions.performADOrCiamLogin(seleniumDriver, user);
5759
}
5860
}
5961
}

msal4j-sdk/src/integrationtest/java/com.microsoft.aad.msal4j/TestConstants.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,10 @@ public class TestConstants {
3434

3535
public final static String REGIONAL_MICROSOFT_AUTHORITY_BASIC_HOST_EASTUS = "eastus.login.microsoft.com";
3636

37-
public final static String CIAM_AUTHORITY = MICROSOFT_AUTHORITY_HOST + "msidlabciam1.onmicrosoft.com";
37+
// public final static String CIAM_AUTHORITY = MICROSOFT_AUTHORITY_HOST + "msidlabciam1.onmicrosoft.com";
38+
public final static String CIAM_AUTHORITY = "https://msidlabciam1.ciamlogin.com/" + "msidlabciam1.onmicrosoft.com";
39+
40+
public final static String CIAM_TEST_AUTHORITY = "https://contoso0781.ciamlogin.com/6babcaad-604b-40ac-a9d7-9fd97c0b779f/v2.0/.well-known/openid-configuration?dc=ESTS-PUB-EUS-AZ1-FD000-TEST1&ciamhost=true";
3841

3942
public final static String ARLINGTON_ORGANIZATIONS_AUTHORITY = ARLINGTON_MICROSOFT_AUTHORITY_HOST + "organizations/";
4043
public final static String ARLINGTON_TENANT_SPECIFIC_AUTHORITY = ARLINGTON_MICROSOFT_AUTHORITY_HOST + ARLINGTON_AUTHORITY_TENANT;

msal4j-sdk/src/integrationtest/java/com.microsoft.aad.msal4j/UsernamePasswordIT.java

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
import org.testng.annotations.Test;
1010

1111
import java.util.Collections;
12+
import java.util.HashMap;
13+
import java.util.Map;
1214

1315
@Test()
1416
public class UsernamePasswordIT {
@@ -100,10 +102,24 @@ public void acquireTokenWithUsernamePassword_ADFSv2(String environment) throws E
100102
@Test
101103
public void acquireTokenWithUsernamePassword_Ciam() throws Exception {
102104

105+
Map<String, String> extraQueryParameters = new HashMap<>();
106+
extraQueryParameters.put("dc","ESTS-PUB-EUS-AZ1-FD000-TEST1");
107+
103108
User user = labUserProvider.getCiamUser();
109+
PublicClientApplication pca = PublicClientApplication.builder(user.getAppId())
110+
.authority("https://" + user.getLabName() + ".ciamlogin.com/")
111+
.build();
104112

105-
assertAcquireTokenCommon(user, TestConstants.CIAM_AUTHORITY, TestConstants.GRAPH_DEFAULT_SCOPE,
106-
user.getAppId());
113+
114+
IAuthenticationResult result = pca.acquireToken(UserNamePasswordParameters.
115+
builder(Collections.singleton(TestConstants.GRAPH_DEFAULT_SCOPE),
116+
user.getUpn(),
117+
user.getPassword().toCharArray())
118+
.extraQueryParameters(extraQueryParameters)
119+
.build())
120+
.get();
121+
122+
Assert.assertNotNull(result.accessToken());
107123
}
108124

109125
@Test
@@ -125,6 +141,7 @@ private void assertAcquireTokenCommonAAD(User user) throws Exception {
125141

126142
private void assertAcquireTokenCommon(User user, String authority, String scope, String appId)
127143
throws Exception {
144+
128145
PublicClientApplication pca = PublicClientApplication.builder(
129146
appId).
130147
authority(authority).
@@ -135,6 +152,7 @@ private void assertAcquireTokenCommon(User user, String authority, String scope,
135152
user.getUpn(),
136153
user.getPassword().toCharArray())
137154
.build())
155+
138156
.get();
139157

140158
assertTokenResultNotNull(result);

msal4j-sdk/src/integrationtest/java/infrastructure/SeleniumExtensions.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ public static WebElement waitForElementToBeVisibleAndEnable(WebDriver driver, By
6565
return waitForElementToBeVisibleAndEnable(driver, by, DEFAULT_TIMEOUT_IN_SEC);
6666
}
6767

68-
public static void performADLogin(WebDriver driver, User user) {
69-
LOG.info("PerformADLogin");
68+
public static void performADOrCiamLogin(WebDriver driver, User user) {
69+
LOG.info("performADOrCiamLogin");
7070

7171
UserInformationFields fields = new UserInformationFields(user);
7272

@@ -76,7 +76,7 @@ public static void performADLogin(WebDriver driver, User user) {
7676
LOG.info("Loggin in ... Clicking <Next> after username");
7777
driver.findElement(new By.ById(fields.getAadSignInButtonId())).click();
7878

79-
if (user.getFederationProvider() == FederationProvider.ADFS_2 &&
79+
if (user.getFederationProvider().equals(FederationProvider.ADFS_2) &&
8080
!user.getLabName().equals(LabConstants.ARLINGTON_LAB_NAME)) {
8181

8282
LOG.info("Loggin in ... ADFS-V2 - Entering the username in ADFSv2 form");
@@ -96,6 +96,7 @@ public static void performADLogin(WebDriver driver, User user) {
9696
checkAuthenticationCompletePage(driver);
9797
return;
9898
} catch (TimeoutException ex) {
99+
LOG.error(ex.getMessage());
99100
}
100101

101102
LOG.info("Checking optional questions");
@@ -107,6 +108,7 @@ public static void performADLogin(WebDriver driver, User user) {
107108
LOG.info("Are you trying to sign in to ... ? click Continue");
108109

109110
} catch (TimeoutException ex) {
111+
LOG.error(ex.getMessage());
110112
}
111113

112114
try {
@@ -115,6 +117,7 @@ public static void performADLogin(WebDriver driver, User user) {
115117
click();
116118
LOG.info("Stay signed in? click NO");
117119
} catch (TimeoutException ex) {
120+
LOG.error(ex.getMessage());
118121
}
119122
}
120123

msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/AbstractClientApplicationBase.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ public T authority(String val) throws MalformedURLException {
357357
authority = Authority.enforceTrailingSlash(val);
358358

359359
URL authorityURL = new URL(authority);
360-
Authority.validateAuthority(authorityURL);
360+
361361

362362
switch (Authority.detectAuthorityType(authorityURL)) {
363363
case AAD:
@@ -366,10 +366,15 @@ public T authority(String val) throws MalformedURLException {
366366
case ADFS:
367367
authenticationAuthority = new ADFSAuthority(authorityURL);
368368
break;
369+
case CIAM:
370+
authenticationAuthority = new CIAMAuthority(authorityURL);
371+
break;
369372
default:
370373
throw new IllegalArgumentException("Unsupported authority type.");
371374
}
372375

376+
Authority.validateAuthority(authenticationAuthority.canonicalAuthorityUrl());
377+
373378
return self();
374379
}
375380

msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/Authority.java

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -54,19 +54,22 @@ private void setCommonAuthorityProperties() {
5454
this.host = canonicalAuthorityUrl.getAuthority().toLowerCase();
5555
}
5656

57-
static Authority createAuthority(URL authorityUrl) {
58-
validateAuthority(authorityUrl);
59-
57+
static Authority createAuthority(URL authorityUrl) throws MalformedURLException{
58+
Authority createdAuthority;
6059
AuthorityType authorityType = detectAuthorityType(authorityUrl);
6160
if (authorityType == AuthorityType.AAD) {
62-
return new AADAuthority(authorityUrl);
61+
createdAuthority = new AADAuthority(authorityUrl);
6362
} else if (authorityType == AuthorityType.B2C) {
64-
return new B2CAuthority(authorityUrl);
63+
createdAuthority = new B2CAuthority(authorityUrl);
6564
} else if (authorityType == AuthorityType.ADFS) {
66-
return new ADFSAuthority(authorityUrl);
65+
createdAuthority = new ADFSAuthority(authorityUrl);
66+
} else if(authorityType == AuthorityType.CIAM){
67+
createdAuthority = new CIAMAuthority(authorityUrl);
6768
} else {
6869
throw new IllegalArgumentException("Unsupported Authority Type");
6970
}
71+
validateAuthority(createdAuthority.canonicalAuthorityUrl());
72+
return createdAuthority;
7073
}
7174

7275
static AuthorityType detectAuthorityType(URL authorityUrl) {
@@ -76,6 +79,9 @@ static AuthorityType detectAuthorityType(URL authorityUrl) {
7679

7780
final String path = authorityUrl.getPath().substring(1);
7881
if (StringHelper.isBlank(path)) {
82+
if(isCiamAuthority(authorityUrl.getHost())){
83+
return AuthorityType.CIAM;
84+
}
7985
throw new IllegalArgumentException(
8086
"authority Uri should have at least one segment in the path (i.e. https://<host>/<path>/...)");
8187
}
@@ -87,7 +93,9 @@ static AuthorityType detectAuthorityType(URL authorityUrl) {
8793
return AuthorityType.B2C;
8894
} else if (isAdfsAuthority(firstPath)) {
8995
return AuthorityType.ADFS;
90-
} else {
96+
} else if(isCiamAuthority(host)){
97+
return AuthorityType.CIAM;
98+
} else{
9199
return AuthorityType.AAD;
92100
}
93101
}
@@ -154,6 +162,10 @@ private static boolean isB2CAuthority(final String host, final String firstPath)
154162
return host.contains(B2C_HOST_SEGMENT) || firstPath.compareToIgnoreCase(B2C_PATH_SEGMENT) == 0;
155163
}
156164

165+
private static boolean isCiamAuthority(final String host){
166+
return host.endsWith(CIAMAuthority.CIAM_HOST_SEGMENT);
167+
}
168+
157169
String deviceCodeEndpoint() {
158170
return deviceCodeEndpoint;
159171
}

msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/AuthorityType.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@
44
package com.microsoft.aad.msal4j;
55

66
enum AuthorityType {
7-
AAD, ADFS, B2C
7+
AAD, ADFS, B2C, CIAM
88
}

0 commit comments

Comments
 (0)