Skip to content

Commit 27eb113

Browse files
authored
Merge pull request #36 from AzureAD/dev
Release v0.2.0-preview
2 parents 93595af + d3ef054 commit 27eb113

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+1020
-514
lines changed

changelog.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
Version 0.0.1-preview
1+
Version 0.2.0-preview
2+
=============
3+
- Added support for B2C
4+
5+
Version 0.1.0-preview
26
=============
37
Public preview of Microsoft Authentication Library for Java
48
- Feature parity with ADAL Java

pom.xml

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<modelVersion>4.0.0</modelVersion>
44
<groupId>com.microsoft.azure</groupId>
55
<artifactId>msal4j</artifactId>
6-
<version>0.1.0-preview</version>
6+
<version>0.2.0-preview</version>
77
<packaging>jar</packaging>
88
<name>msal4j</name>
99
<description>
@@ -176,14 +176,6 @@
176176
<argLine>-noverify</argLine>
177177
</configuration>
178178
</plugin>
179-
<plugin>
180-
<artifactId>maven-compiler-plugin</artifactId>
181-
<version>3.0</version>
182-
<configuration>
183-
<source>1.7</source>
184-
<target>1.7</target>
185-
</configuration>
186-
</plugin>
187179
<plugin>
188180
<groupId>org.apache.maven.plugins</groupId>
189181
<artifactId>maven-javadoc-plugin</artifactId>

src/integrationtest/java/com.microsoft.aad.msal4j/AuthorizationCodeIT.java

Lines changed: 156 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
import infrastructure.SeleniumExtensions;
2727
import infrastructure.TcpListener;
28+
import labapi.B2CIdentityProvider;
2829
import labapi.FederationProvider;
2930
import labapi.LabResponse;
3031
import labapi.LabUserProvider;
@@ -40,6 +41,7 @@
4041
import org.testng.util.Strings;
4142

4243
import java.io.UnsupportedEncodingException;
44+
import java.net.MalformedURLException;
4345
import java.net.URI;
4446
import java.net.URLEncoder;
4547
import java.util.Collections;
@@ -65,11 +67,11 @@ public void setUpLapUserProvider() {
6567

6668
@AfterMethod
6769
public void cleanUp(){
68-
seleniumDriver.quit();
69-
if(AuthorizationCodeQueue != null){
70-
AuthorizationCodeQueue.clear();
71-
}
72-
tcpListener.close();
70+
seleniumDriver.quit();
71+
if(AuthorizationCodeQueue != null){
72+
AuthorizationCodeQueue.clear();
73+
}
74+
tcpListener.close();
7375
}
7476

7577
@BeforeMethod
@@ -84,7 +86,7 @@ public void acquireTokenWithAuthorizationCode_ManagedUser(){
8486
false);
8587
labUserProvider.getUserPassword(labResponse.getUser());
8688

87-
assertAcquireTokenCommon(labResponse);
89+
assertAcquireTokenAAD(labResponse);
8890
}
8991

9092
@Test
@@ -95,9 +97,9 @@ public void acquireTokenWithAuthorizationCode_ADFSv2019_Federated(){
9597
true);
9698
labUserProvider.getUserPassword(labResponse.getUser());
9799

98-
assertAcquireTokenCommon(labResponse);
100+
assertAcquireTokenAAD(labResponse);
99101
}
100-
102+
101103
@Test
102104
public void acquireTokenWithAuthorizationCode_ADFSv2019_NotFederated(){
103105
LabResponse labResponse = labUserProvider.getAdfsUser(
@@ -106,7 +108,7 @@ public void acquireTokenWithAuthorizationCode_ADFSv2019_NotFederated(){
106108
true);
107109
labUserProvider.getUserPassword(labResponse.getUser());
108110

109-
assertAcquireTokenCommon(labResponse);
111+
assertAcquireTokenAAD(labResponse);
110112
}
111113

112114
@Test
@@ -117,7 +119,7 @@ public void acquireTokenWithAuthorizationCode_ADFSv4_Federated(){
117119
false);
118120
labUserProvider.getUserPassword(labResponse.getUser());
119121

120-
assertAcquireTokenCommon(labResponse);
122+
assertAcquireTokenAAD(labResponse);
121123
}
122124

123125
@Test
@@ -128,7 +130,7 @@ public void acquireTokenWithAuthorizationCode_ADFSv4_NotFederated(){
128130
false);
129131
labUserProvider.getUserPassword(labResponse.getUser());
130132

131-
assertAcquireTokenCommon(labResponse);
133+
assertAcquireTokenAAD(labResponse);
132134
}
133135

134136
@Test
@@ -138,8 +140,8 @@ public void acquireTokenWithAuthorizationCode_ADFSv3_Federated(){
138140
true,
139141
false);
140142
labUserProvider.getUserPassword(labResponse.getUser());
143+
assertAcquireTokenAAD(labResponse);
141144

142-
assertAcquireTokenCommon(labResponse);
143145
}
144146

145147
@Test
@@ -150,7 +152,7 @@ public void acquireTokenWithAuthorizationCode_ADFSv3_NotFederated(){
150152
false);
151153
labUserProvider.getUserPassword(labResponse.getUser());
152154

153-
assertAcquireTokenCommon(labResponse);
155+
assertAcquireTokenAAD(labResponse);
154156
}
155157

156158
@Test
@@ -161,7 +163,7 @@ public void acquireTokenWithAuthorizationCode_ADFSv2_Federated(){
161163
false);
162164
labUserProvider.getUserPassword(labResponse.getUser());
163165

164-
assertAcquireTokenCommon(labResponse);
166+
assertAcquireTokenAAD(labResponse);
165167
}
166168

167169
@Test
@@ -172,12 +174,53 @@ public void acquireTokenWithAuthorizationCode_ADFSv2_NotFederated(){
172174
false);
173175
labUserProvider.getUserPassword(labResponse.getUser());
174176

175-
assertAcquireTokenCommon(labResponse);
177+
assertAcquireTokenAAD(labResponse);
176178
}
177179

178-
private void assertAcquireTokenCommon(LabResponse labResponse){
179-
String authCode = acquireAuthorizationCodeAutomated(labResponse);
180-
AuthenticationResult result = acquireTokenInteractive(labResponse, authCode);
180+
@Test
181+
public void acquireTokenWithAuthorizationCode_B2C_Local(){
182+
LabResponse labResponse = labUserProvider.getB2cUser(
183+
B2CIdentityProvider.LOCAL,
184+
false);
185+
labUserProvider.getUserPassword(labResponse.getUser());
186+
187+
String b2CAppId = "b876a048-55a5-4fc5-9403-f5d90cb1c852";
188+
labResponse.setAppId(b2CAppId);
189+
190+
assertAcquireTokenB2C(labResponse);
191+
}
192+
193+
@Test
194+
public void acquireTokenWithAuthorizationCode_B2C_Google(){
195+
LabResponse labResponse = labUserProvider.getB2cUser(
196+
B2CIdentityProvider.GOOGLE,
197+
false);
198+
labUserProvider.getUserPassword(labResponse.getUser());
199+
200+
String b2CAppId = "b876a048-55a5-4fc5-9403-f5d90cb1c852";
201+
labResponse.setAppId(b2CAppId);
202+
203+
assertAcquireTokenB2C(labResponse);
204+
}
205+
206+
// TODO uncomment when lab fixes facebook test account
207+
// @Test
208+
// public void acquireTokenWithAuthorizationCode_B2C_Facebook(){
209+
// LabResponse labResponse = labUserProvider.getB2cUser(
210+
// B2CIdentityProvider.FACEBOOK,
211+
// false);
212+
// labUserProvider.getUserPassword(labResponse.getUser());
213+
//
214+
// String b2CAppId = "b876a048-55a5-4fc5-9403-f5d90cb1c852";
215+
// labResponse.setAppId(b2CAppId);
216+
//
217+
// assertAcquireTokenB2C(labResponse);
218+
// }
219+
220+
221+
private void assertAcquireTokenAAD(LabResponse labResponse){
222+
String authCode = acquireAuthorizationCodeAutomated(labResponse, AuthorityType.AAD);
223+
AuthenticationResult result = acquireTokenInteractiveAAD(labResponse, authCode);
181224

182225
Assert.assertNotNull(result);
183226
Assert.assertNotNull(result.accessToken());
@@ -187,11 +230,25 @@ private void assertAcquireTokenCommon(LabResponse labResponse){
187230
// Assert.assertEquals(labResponse.getUser().getUpn(), result.getAccountInfo().getUsername());
188231
}
189232

190-
private AuthenticationResult acquireTokenInteractive(LabResponse labResponse,
191-
String authCode){
233+
private void assertAcquireTokenB2C(LabResponse labResponse){
234+
String authCode = acquireAuthorizationCodeAutomated(labResponse, AuthorityType.B2C);
235+
AuthenticationResult result = acquireTokenInteractiveB2C(labResponse, authCode);
236+
237+
Assert.assertNotNull(result);
238+
Assert.assertNotNull(result.accessToken());
239+
Assert.assertNotNull(result.refreshToken());
240+
Assert.assertNotNull(result.idToken());
241+
// TODO AuthenticationResult should have an getAccountInfo API
242+
// Assert.assertEquals(labResponse.getUser().getUpn(), result.getAccountInfo().getUsername());
243+
}
244+
245+
private AuthenticationResult acquireTokenInteractiveAAD(
246+
LabResponse labResponse,
247+
String authCode){
248+
192249
AuthenticationResult result;
193250
try {
194-
PublicClientApplication pca = new PublicClientApplication.Builder(
251+
PublicClientApplication pca = PublicClientApplication.builder(
195252
labResponse.getAppId()).
196253
authority(TestConstants.AUTHORITY_ORGANIZATIONS).
197254
build();
@@ -210,7 +267,34 @@ private AuthenticationResult acquireTokenInteractive(LabResponse labResponse,
210267
return result;
211268
}
212269

213-
private String acquireAuthorizationCodeAutomated(LabResponse labUserData){
270+
private AuthenticationResult acquireTokenInteractiveB2C(LabResponse labResponse,
271+
String authCode) {
272+
AuthenticationResult result;
273+
try{
274+
IClientCredential credential = ClientCredentialFactory.create("=]Y)_A7LX`]6\"]_PoD!)Lo24");
275+
ConfidentialClientApplication cca = ConfidentialClientApplication.builder(
276+
labResponse.getAppId(),
277+
credential)
278+
.b2cAuthority(TestConstants.B2C_AUTHORITY_SIGN_IN)
279+
.build();
280+
281+
result = cca.acquireToken(AuthorizationCodeParameters.builder(
282+
authCode,
283+
new URI(TestConstants.LOCALHOST + tcpListener.getPort()))
284+
.scopes(Collections.singleton(TestConstants.B2C_LAB_SCOPE))
285+
.build())
286+
.get();
287+
} catch (Exception e){
288+
LOG.error("Error acquiring token with authCode: " + e.getMessage());
289+
throw new RuntimeException("Error acquiring token with authCode: " + e.getMessage());
290+
}
291+
return result;
292+
}
293+
294+
295+
private String acquireAuthorizationCodeAutomated(
296+
LabResponse labUserData,
297+
AuthorityType authorityType){
214298
BlockingQueue<Boolean> tcpStartUpNotificationQueue = new LinkedBlockingQueue<>();
215299
startTcpListener(tcpStartUpNotificationQueue);
216300

@@ -222,7 +306,7 @@ private String acquireAuthorizationCodeAutomated(LabResponse labUserData){
222306
if (tcpListenerStarted == null || !tcpListenerStarted){
223307
throw new RuntimeException("Could not start TCP listener");
224308
}
225-
runSeleniumAutomatedLogin(labUserData);
309+
runSeleniumAutomatedLogin(labUserData, authorityType);
226310
authServerResponse = getResponseFromTcpListener();
227311
} catch(Exception e){
228312
if(!Strings.isNullOrEmpty(
@@ -232,14 +316,28 @@ private String acquireAuthorizationCodeAutomated(LabResponse labUserData){
232316
LOG.error("Error running automated selenium login: " + e.getMessage());
233317
throw new RuntimeException("Error running automated selenium login: " + e.getMessage());
234318
}
235-
return parseServerResponse(authServerResponse);
319+
return parseServerResponse(authServerResponse,authorityType);
236320
}
237321

238-
private void runSeleniumAutomatedLogin(LabResponse labUserData) throws
239-
UnsupportedEncodingException{
240-
String url = buildAuthenticationCodeURL(labUserData.getAppId());
322+
private void runSeleniumAutomatedLogin(LabResponse labUserData, AuthorityType authorityType)
323+
throws UnsupportedEncodingException{
324+
String url = buildAuthenticationCodeURL(labUserData.getAppId(), authorityType);
241325
seleniumDriver.navigate().to(url);
242-
SeleniumExtensions.performLogin(seleniumDriver, labUserData.getUser());
326+
if(authorityType == AuthorityType.B2C){
327+
switch(labUserData.getUser().getB2CIdentityProvider()){
328+
case LOCAL:
329+
SeleniumExtensions.performLocalLogin(seleniumDriver, labUserData.getUser());
330+
break;
331+
case GOOGLE:
332+
SeleniumExtensions.performGoogleLogin(seleniumDriver, labUserData.getUser());
333+
break;
334+
case FACEBOOK:
335+
SeleniumExtensions.performFacebookLogin(seleniumDriver, labUserData.getUser());
336+
break;
337+
}
338+
} else {
339+
SeleniumExtensions.performADLogin(seleniumDriver, labUserData.getUser());
340+
}
243341
}
244342

245343
private void startTcpListener(BlockingQueue<Boolean> tcpStartUpNotifierQueue){
@@ -264,9 +362,15 @@ private String getResponseFromTcpListener(){
264362
return response;
265363
}
266364

267-
private String parseServerResponse(String serverResponse){
365+
private String parseServerResponse(String serverResponse, AuthorityType authorityType){
268366
// Response will be a GET request with query parameter ?code=authCode
269-
String regexp = "code=(.*)&";
367+
String regexp;
368+
if(authorityType == AuthorityType.B2C){
369+
regexp = "(?<=code=)(?:(?! HTTP).)*";
370+
} else {
371+
regexp = "(?<=code=)(?:(?!&).)*";
372+
}
373+
270374
Pattern pattern = Pattern.compile(regexp);
271375
Matcher matcher = pattern.matcher(serverResponse);
272376

@@ -275,18 +379,34 @@ private String parseServerResponse(String serverResponse){
275379
throw new IllegalStateException("No authorization code in server response: " +
276380
serverResponse);
277381
}
278-
return matcher.group(1);
382+
return matcher.group(0);
279383
}
280384

281-
private String buildAuthenticationCodeURL(String appId) throws UnsupportedEncodingException{
385+
private String buildAuthenticationCodeURL(String appId, AuthorityType authorityType)
386+
throws UnsupportedEncodingException{
282387
String redirectUrl;
283388
int portNumber = tcpListener.getPort();
284-
redirectUrl = TestConstants.AUTHORITY_ORGANIZATIONS + "oauth2/v2.0/authorize?" +
285-
"response_type=code&" +
286-
"response_mode=query&" +
389+
390+
String authority;
391+
String scope;
392+
if(authorityType == AuthorityType.AAD){
393+
authority = TestConstants.AUTHORITY_ORGANIZATIONS;
394+
scope = TestConstants.GRAPH_DEFAULT_SCOPE;
395+
} else {
396+
authority = TestConstants.B2C_AUTHORITY_URL;
397+
scope = TestConstants.B2C_LAB_SCOPE;
398+
}
399+
400+
redirectUrl = authority + "oauth2/v2.0/authorize?" +
401+
"response_type=code" +
402+
"&response_mode=query" +
287403
"&client_id=" + appId +
288404
"&redirect_uri=" + URLEncoder.encode(TestConstants.LOCALHOST + portNumber, "UTF-8") +
289-
"&scope=" + URLEncoder.encode("openid offline_access profile " + TestConstants.GRAPH_DEFAULT_SCOPE, "UTF-8");
405+
"&scope=" + URLEncoder.encode("openid offline_access profile " + scope, "UTF-8");
406+
407+
if(authorityType == AuthorityType.B2C){
408+
redirectUrl = redirectUrl + "&p=" + TestConstants.B2C_SIGN_IN_POLICY;
409+
}
290410

291411
return redirectUrl;
292412
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ private void runAutomatedDeviceCodeFlow(DeviceCode deviceCode, LabUser user){
106106
new By.ById(continueButtonId));
107107
continueBtn.click();
108108

109-
SeleniumExtensions.performLogin(seleniumDriver, user);
109+
SeleniumExtensions.performADLogin(seleniumDriver, user);
110110
} catch(Exception e){
111111
if(!isRunningLocally){
112112
SeleniumExtensions.takeScreenShot(seleniumDriver);

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,21 @@
2626
public class TestConstants {
2727
public final static String KEYVAULT_DEFAULT_SCOPE = "https://vault.azure.net/.default";
2828
public final static String GRAPH_DEFAULT_SCOPE = "https://graph.windows.net/.default";
29+
public final static String B2C_LAB_SCOPE = "https://msidlabb2c.onmicrosoft.com/msaapp/user_impersonation";
2930

3031
public final static String AUTHORITY_ORGANIZATIONS = "https://login.microsoftonline.com/organizations/";
3132
public final static String AUTHORITY_MICROSOFT = "https://login.microsoftonline.com/microsoft.onmicrosoft.com";
3233

34+
public final static String B2C_AUTHORITY = "https://msidlabb2c.b2clogin.com/tfp/msidlabb2c.onmicrosoft.com/";
35+
public final static String B2C_AUTHORITY_URL = "https://msidlabb2c.b2clogin.com/msidlabb2c.onmicrosoft.com/";
36+
public final static String B2C_ROPC_POLICY = "B2C_1_ROPC_Auth";
37+
public final static String B2C_SIGN_IN_POLICY = "B2C_1_SignInPolicy";
38+
public final static String B2C_AUTHORITY_SIGN_IN = B2C_AUTHORITY + B2C_SIGN_IN_POLICY;
39+
public final static String B2C_AUTHORITY_ROPC = B2C_AUTHORITY + B2C_ROPC_POLICY;
40+
public final static String B2C_READ_SCOPE = "https://msidlabb2c.onmicrosoft.com/msidlabb2capi/read";
41+
public final static String B2C_MICROSOFTLOGIN_AUTHORITY = "https://login.microsoftonline.com/tfp/msidlabb2c.onmicrosoft.com/";
42+
public final static String B2C_MICROSOFTLOGIN_ROPC = B2C_MICROSOFTLOGIN_AUTHORITY + B2C_ROPC_POLICY;
43+
3344
public final static String LOCALHOST = "http://localhost:";
3445
public final static String LOCAL_FLAG_ENV_VAR = "MSAL_JAVA_RUN_LOCAL";
3546
}

0 commit comments

Comments
 (0)