Skip to content

Commit cf659cd

Browse files
authored
Sync with changes to Azure-Samples/ms-identity-java-desktop (#259)
1 parent d96e9de commit cf659cd

File tree

3 files changed

+162
-58
lines changed

3 files changed

+162
-58
lines changed

src/samples/public-client/IntegratedWindowsAuthenticationFlow.java

Lines changed: 77 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -8,67 +8,113 @@
88
import com.microsoft.aad.msal4j.PublicClientApplication;
99
import com.microsoft.aad.msal4j.SilentParameters;
1010

11+
import java.io.IOException;
1112
import java.util.Collections;
13+
import java.util.Properties;
1214
import java.util.Set;
1315

1416
public class IntegratedWindowsAuthenticationFlow {
1517

16-
private final static String CLIENT_ID = "";
17-
private final static String AUTHORITY = "https://login.microsoftonline.com/organizations/";
18-
private final static Set<String> SCOPE = Collections.singleton("");
19-
private final static String USER_NAME = "";
18+
private static String authority;
19+
private static Set<String> scope;
20+
private static String clientId;
21+
private static String username;
2022

2123
public static void main(String args[]) throws Exception {
2224

23-
IAuthenticationResult result = acquireTokenIwa();
24-
System.out.println("Access token: " + result.accessToken());
25-
System.out.println("Id token: " + result.idToken());
26-
System.out.println("Account username: " + result.account().username());
27-
}
28-
29-
private static IAuthenticationResult acquireTokenIwa() throws Exception {
25+
setUpSampleData();
3026

31-
// Load token cache from file and initialize token cache aspect. The token cache will have
32-
// dummy data, so the acquireTokenSilently call will fail.
33-
TokenCacheAspect tokenCacheAspect = new TokenCacheAspect("sample_cache.json");
34-
35-
PublicClientApplication pca = PublicClientApplication.builder(CLIENT_ID)
36-
.authority(AUTHORITY)
37-
.setTokenCacheAccessAspect(tokenCacheAspect)
27+
PublicClientApplication pca = PublicClientApplication.builder(clientId)
28+
.authority(authority)
3829
.build();
3930

4031
Set<IAccount> accountsInCache = pca.getAccounts().join();
41-
// Take first account in the cache. In a production application, you would filter
42-
// accountsInCache to get the right account for the user authenticating.
43-
IAccount account = accountsInCache.iterator().next();
32+
IAccount account = getAccountByUsername(accountsInCache, username);
33+
34+
//Attempt to acquire token when user's account is not in the application's token cache
35+
IAuthenticationResult result = acquireTokenIntegratedWindowsAuth(pca, scope, account, username);
36+
System.out.println("Account username: " + result.account().username());
37+
System.out.println("Access token: " + result.accessToken());
38+
System.out.println("Id token: " + result.idToken());
39+
System.out.println();
40+
41+
//Get list of accounts from the application's token cache, and search them for the configured username
42+
//getAccounts() will be empty on this first call, as accounts are added to the cache when acquiring a token
43+
accountsInCache = pca.getAccounts().join();
44+
account = getAccountByUsername(accountsInCache, username);
45+
46+
//Attempt to acquire token again, now that the user's account and a token are in the application's token cache
47+
result = acquireTokenIntegratedWindowsAuth(pca, scope, account, username);
48+
System.out.println("Account username: " + result.account().username());
49+
System.out.println("Access token: " + result.accessToken());
50+
System.out.println("Id token: " + result.idToken());
51+
}
52+
53+
private static IAuthenticationResult acquireTokenIntegratedWindowsAuth( PublicClientApplication pca,
54+
Set<String> scope,
55+
IAccount account,
56+
String username) throws Exception {
4457

4558
IAuthenticationResult result;
4659
try {
4760
SilentParameters silentParameters =
4861
SilentParameters
49-
.builder(SCOPE, account)
62+
.builder(scope)
63+
.account(account)
5064
.build();
51-
52-
// try to acquire token silently. This call will fail since the token cache
53-
// does not have any data for the user you are trying to acquire a token for
65+
// Try to acquire token silently. This will fail on the first acquireTokenIntegratedWindowsAuth() call
66+
// because the token cache does not have any data for the user you are trying to acquire a token for
5467
result = pca.acquireTokenSilently(silentParameters).join();
68+
System.out.println("==acquireTokenSilently call succeeded");
5569
} catch (Exception ex) {
5670
if (ex.getCause() instanceof MsalException) {
57-
71+
System.out.println("==acquireTokenSilently call failed: " + ex.getCause());
5872
IntegratedWindowsAuthenticationParameters parameters =
5973
IntegratedWindowsAuthenticationParameters
60-
.builder(SCOPE, USER_NAME)
74+
.builder(scope, username)
6175
.build();
6276

63-
// Try to acquire a IWA. You will need to generate a Kerberos ticket.
64-
// If successful, you should see the token and account information printed out to
65-
// console
77+
// Try to acquire a token using Integrated Windows Authentication (IWA). You will need to generate a Kerberos ticket.
78+
// If successful, you should see the token and account information printed out to console
6679
result = pca.acquireToken(parameters).join();
80+
System.out.println("==Integrated Windows Authentication flow succeeded");
6781
} else {
6882
// Handle other exceptions accordingly
6983
throw ex;
7084
}
7185
}
7286
return result;
7387
}
74-
}
88+
89+
/**
90+
* Helper function to return an account from a given set of accounts based on the given username,
91+
* or return null if no accounts in the set match
92+
*/
93+
private static IAccount getAccountByUsername(Set<IAccount> accounts, String username) {
94+
if (accounts.isEmpty()) {
95+
System.out.println("==No accounts in cache");
96+
} else {
97+
System.out.println("==Accounts in cache: " + accounts.size());
98+
for (IAccount account : accounts) {
99+
if (account.username().equals(username)) {
100+
return account;
101+
}
102+
}
103+
}
104+
return null;
105+
}
106+
107+
/**
108+
* Helper function unique to this sample setting. In a real application these wouldn't be so hardcoded, for example
109+
* values such as username would come from the user, and different users may require different scopes
110+
*/
111+
private static void setUpSampleData() throws IOException {
112+
// Load properties file and set properties used throughout the sample
113+
Properties properties = new Properties();
114+
properties.load(UsernamePasswordFlow.class.getResourceAsStream("application.properties"));
115+
authority = properties.getProperty("AUTHORITY");
116+
scope = Collections.singleton(properties.getProperty("SCOPE"));
117+
clientId = properties.getProperty("CLIENT_ID");
118+
username = properties.getProperty("USER_NAME");
119+
}
120+
}

src/samples/public-client/UsernamePasswordFlow.java

Lines changed: 76 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,65 +8,114 @@
88
import com.microsoft.aad.msal4j.SilentParameters;
99
import com.microsoft.aad.msal4j.UserNamePasswordParameters;
1010

11+
import java.io.IOException;
1112
import java.util.Collections;
13+
import java.util.Properties;
1214
import java.util.Set;
1315

1416
public class UsernamePasswordFlow {
1517

16-
private final static String CLIENT_ID = "";
17-
private final static String AUTHORITY = "https://login.microsoftonline.com/organizations/";
18-
private final static Set<String> SCOPE = Collections.singleton("");
19-
private final static String USER_NAME = "";
20-
private final static String USER_PASSWORD = "";
18+
private static String authority;
19+
private static Set<String> scope;
20+
private static String clientId;
21+
private static String username;
22+
private static String password;
2123

2224
public static void main(String args[]) throws Exception {
2325

24-
IAuthenticationResult result = acquireTokenUsernamePassword();
25-
System.out.println("Access token: " + result.accessToken());
26-
System.out.println("Id token: " + result.idToken());
27-
System.out.println("Account username: " + result.account().username());
28-
}
29-
30-
private static IAuthenticationResult acquireTokenUsernamePassword() throws Exception {
26+
setUpSampleData();
3127

32-
// Load token cache from file and initialize token cache aspect. The token cache will have
33-
// dummy data, so the acquireTokenSilently call will fail.
34-
TokenCacheAspect tokenCacheAspect = new TokenCacheAspect("sample_cache.json");
35-
36-
PublicClientApplication pca = PublicClientApplication.builder(CLIENT_ID)
37-
.authority(AUTHORITY)
38-
.setTokenCacheAccessAspect(tokenCacheAspect)
28+
PublicClientApplication pca = PublicClientApplication.builder(clientId)
29+
.authority(authority)
3930
.build();
4031

32+
//Get list of accounts from the application's token cache, and search them for the configured username
33+
//getAccounts() will be empty on this first call, as accounts are added to the cache when acquiring a token
4134
Set<IAccount> accountsInCache = pca.getAccounts().join();
42-
// Take first account in the cache. In a production application, you would filter
43-
// accountsInCache to get the right account for the user authenticating.
44-
IAccount account = accountsInCache.iterator().next();
35+
IAccount account = getAccountByUsername(accountsInCache, username);
4536

37+
//Attempt to acquire token when user's account is not in the application's token cache
38+
IAuthenticationResult result = acquireTokenUsernamePassword(pca, scope, account, username, password);
39+
System.out.println("Account username: " + result.account().username());
40+
System.out.println("Access token: " + result.accessToken());
41+
System.out.println("Id token: " + result.idToken());
42+
System.out.println();
43+
44+
accountsInCache = pca.getAccounts().join();
45+
account = getAccountByUsername(accountsInCache, username);
46+
47+
//Attempt to acquire token again, now that the user's account and a token are in the application's token cache
48+
result = acquireTokenUsernamePassword(pca, scope, account, username, password);
49+
System.out.println("Account username: " + result.account().username());
50+
System.out.println("Access token: " + result.accessToken());
51+
System.out.println("Id token: " + result.idToken());
52+
}
53+
54+
private static IAuthenticationResult acquireTokenUsernamePassword(PublicClientApplication pca,
55+
Set<String> scope,
56+
IAccount account,
57+
String username,
58+
String password) throws Exception {
4659
IAuthenticationResult result;
4760
try {
4861
SilentParameters silentParameters =
4962
SilentParameters
50-
.builder(SCOPE, account)
63+
.builder(scope)
64+
.account(account)
5165
.build();
52-
// try to acquire token silently. This call will fail since the token cache
53-
// does not have any data for the user you are trying to acquire a token for
66+
// Try to acquire token silently. This will fail on the first acquireTokenUsernamePassword() call
67+
// because the token cache does not have any data for the user you are trying to acquire a token for
5468
result = pca.acquireTokenSilently(silentParameters).join();
69+
System.out.println("==acquireTokenSilently call succeeded");
5570
} catch (Exception ex) {
5671
if (ex.getCause() instanceof MsalException) {
57-
72+
System.out.println("==acquireTokenSilently call failed: " + ex.getCause());
5873
UserNamePasswordParameters parameters =
5974
UserNamePasswordParameters
60-
.builder(SCOPE, USER_NAME, USER_PASSWORD.toCharArray())
75+
.builder(scope, username, password.toCharArray())
6176
.build();
6277
// Try to acquire a token via username/password. If successful, you should see
6378
// the token and account information printed out to console
6479
result = pca.acquireToken(parameters).join();
80+
System.out.println("==username/password flow succeeded");
6581
} else {
6682
// Handle other exceptions accordingly
6783
throw ex;
6884
}
6985
}
7086
return result;
7187
}
88+
89+
/**
90+
* Helper function to return an account from a given set of accounts based on the given username,
91+
* or return null if no accounts in the set match
92+
*/
93+
private static IAccount getAccountByUsername(Set<IAccount> accounts, String username) {
94+
if (accounts.isEmpty()) {
95+
System.out.println("==No accounts in cache");
96+
} else {
97+
System.out.println("==Accounts in cache: " + accounts.size());
98+
for (IAccount account : accounts) {
99+
if (account.username().equals(username)) {
100+
return account;
101+
}
102+
}
103+
}
104+
return null;
105+
}
106+
107+
/**
108+
* Helper function unique to this sample setting. In a real application these wouldn't be so hardcoded, for example
109+
* values such as username/password would come from the user, and different users may require different scopes
110+
*/
111+
private static void setUpSampleData() throws IOException {
112+
// Load properties file and set properties used throughout the sample
113+
Properties properties = new Properties();
114+
properties.load(UsernamePasswordFlow.class.getResourceAsStream("application.properties"));
115+
authority = properties.getProperty("AUTHORITY");
116+
scope = Collections.singleton(properties.getProperty("SCOPE"));
117+
clientId = properties.getProperty("CLIENT_ID");
118+
username = properties.getProperty("USER_NAME");
119+
password = properties.getProperty("USER_PASSWORD");
120+
}
72121
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CLIENT_ID=
2+
USER_NAME=
3+
USER_PASSWORD=
4+
5+
# The below properties do not need to be changed for this sample
6+
# In a real situation they would be used to affect authentication behavior, such as changing where token requests are
7+
# sent by using a different authority URL
8+
AUTHORITY=https://login.microsoftonline.com/organizations/
9+
SCOPE=user.read

0 commit comments

Comments
 (0)