|
8 | 8 | import com.microsoft.aad.msal4j.SilentParameters;
|
9 | 9 | import com.microsoft.aad.msal4j.UserNamePasswordParameters;
|
10 | 10 |
|
| 11 | +import java.io.IOException; |
11 | 12 | import java.util.Collections;
|
| 13 | +import java.util.Properties; |
12 | 14 | import java.util.Set;
|
13 | 15 |
|
14 | 16 | public class UsernamePasswordFlow {
|
15 | 17 |
|
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; |
21 | 23 |
|
22 | 24 | public static void main(String args[]) throws Exception {
|
23 | 25 |
|
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(); |
31 | 27 |
|
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) |
39 | 30 | .build();
|
40 | 31 |
|
| 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 |
41 | 34 | 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); |
45 | 36 |
|
| 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 { |
46 | 59 | IAuthenticationResult result;
|
47 | 60 | try {
|
48 | 61 | SilentParameters silentParameters =
|
49 | 62 | SilentParameters
|
50 |
| - .builder(SCOPE, account) |
| 63 | + .builder(scope) |
| 64 | + .account(account) |
51 | 65 | .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 |
54 | 68 | result = pca.acquireTokenSilently(silentParameters).join();
|
| 69 | + System.out.println("==acquireTokenSilently call succeeded"); |
55 | 70 | } catch (Exception ex) {
|
56 | 71 | if (ex.getCause() instanceof MsalException) {
|
57 |
| - |
| 72 | + System.out.println("==acquireTokenSilently call failed: " + ex.getCause()); |
58 | 73 | UserNamePasswordParameters parameters =
|
59 | 74 | UserNamePasswordParameters
|
60 |
| - .builder(SCOPE, USER_NAME, USER_PASSWORD.toCharArray()) |
| 75 | + .builder(scope, username, password.toCharArray()) |
61 | 76 | .build();
|
62 | 77 | // Try to acquire a token via username/password. If successful, you should see
|
63 | 78 | // the token and account information printed out to console
|
64 | 79 | result = pca.acquireToken(parameters).join();
|
| 80 | + System.out.println("==username/password flow succeeded"); |
65 | 81 | } else {
|
66 | 82 | // Handle other exceptions accordingly
|
67 | 83 | throw ex;
|
68 | 84 | }
|
69 | 85 | }
|
70 | 86 | return result;
|
71 | 87 | }
|
| 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 | + } |
72 | 121 | }
|
0 commit comments