Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 77 additions & 31 deletions src/samples/public-client/IntegratedWindowsAuthenticationFlow.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,67 +8,113 @@
import com.microsoft.aad.msal4j.PublicClientApplication;
import com.microsoft.aad.msal4j.SilentParameters;

import java.io.IOException;
import java.util.Collections;
import java.util.Properties;
import java.util.Set;

public class IntegratedWindowsAuthenticationFlow {

private final static String CLIENT_ID = "";
private final static String AUTHORITY = "https://login.microsoftonline.com/organizations/";
private final static Set<String> SCOPE = Collections.singleton("");
private final static String USER_NAME = "";
private static String authority;
private static Set<String> scope;
private static String clientId;
private static String username;

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

IAuthenticationResult result = acquireTokenIwa();
System.out.println("Access token: " + result.accessToken());
System.out.println("Id token: " + result.idToken());
System.out.println("Account username: " + result.account().username());
}

private static IAuthenticationResult acquireTokenIwa() throws Exception {
setUpSampleData();

// Load token cache from file and initialize token cache aspect. The token cache will have
// dummy data, so the acquireTokenSilently call will fail.
TokenCacheAspect tokenCacheAspect = new TokenCacheAspect("sample_cache.json");

PublicClientApplication pca = PublicClientApplication.builder(CLIENT_ID)
.authority(AUTHORITY)
.setTokenCacheAccessAspect(tokenCacheAspect)
PublicClientApplication pca = PublicClientApplication.builder(clientId)
.authority(authority)
.build();

Set<IAccount> accountsInCache = pca.getAccounts().join();
// Take first account in the cache. In a production application, you would filter
// accountsInCache to get the right account for the user authenticating.
IAccount account = accountsInCache.iterator().next();
IAccount account = getAccountByUsername(accountsInCache, username);

//Attempt to acquire token when user's account is not in the application's token cache
IAuthenticationResult result = acquireTokenIntegratedWindowsAuth(pca, scope, account, username);
System.out.println("Account username: " + result.account().username());
System.out.println("Access token: " + result.accessToken());
System.out.println("Id token: " + result.idToken());
System.out.println();

//Get list of accounts from the application's token cache, and search them for the configured username
//getAccounts() will be empty on this first call, as accounts are added to the cache when acquiring a token
accountsInCache = pca.getAccounts().join();
account = getAccountByUsername(accountsInCache, username);

//Attempt to acquire token again, now that the user's account and a token are in the application's token cache
result = acquireTokenIntegratedWindowsAuth(pca, scope, account, username);
System.out.println("Account username: " + result.account().username());
System.out.println("Access token: " + result.accessToken());
System.out.println("Id token: " + result.idToken());
}

private static IAuthenticationResult acquireTokenIntegratedWindowsAuth( PublicClientApplication pca,
Set<String> scope,
IAccount account,
String username) throws Exception {

IAuthenticationResult result;
try {
SilentParameters silentParameters =
SilentParameters
.builder(SCOPE, account)
.builder(scope)
.account(account)
.build();

// try to acquire token silently. This call will fail since the token cache
// does not have any data for the user you are trying to acquire a token for
// Try to acquire token silently. This will fail on the first acquireTokenIntegratedWindowsAuth() call
// because the token cache does not have any data for the user you are trying to acquire a token for
result = pca.acquireTokenSilently(silentParameters).join();
System.out.println("==acquireTokenSilently call succeeded");
} catch (Exception ex) {
if (ex.getCause() instanceof MsalException) {

System.out.println("==acquireTokenSilently call failed: " + ex.getCause());
IntegratedWindowsAuthenticationParameters parameters =
IntegratedWindowsAuthenticationParameters
.builder(SCOPE, USER_NAME)
.builder(scope, username)
.build();

// Try to acquire a IWA. You will need to generate a Kerberos ticket.
// If successful, you should see the token and account information printed out to
// console
// Try to acquire a token using Integrated Windows Authentication (IWA). You will need to generate a Kerberos ticket.
// If successful, you should see the token and account information printed out to console
result = pca.acquireToken(parameters).join();
System.out.println("==Integrated Windows Authentication flow succeeded");
} else {
// Handle other exceptions accordingly
throw ex;
}
}
return result;
}
}

/**
* Helper function to return an account from a given set of accounts based on the given username,
* or return null if no accounts in the set match
*/
private static IAccount getAccountByUsername(Set<IAccount> accounts, String username) {
if (accounts.isEmpty()) {
System.out.println("==No accounts in cache");
} else {
System.out.println("==Accounts in cache: " + accounts.size());
for (IAccount account : accounts) {
if (account.username().equals(username)) {
return account;
}
}
}
return null;
}

/**
* Helper function unique to this sample setting. In a real application these wouldn't be so hardcoded, for example
* values such as username would come from the user, and different users may require different scopes
*/
private static void setUpSampleData() throws IOException {
// Load properties file and set properties used throughout the sample
Properties properties = new Properties();
properties.load(UsernamePasswordFlow.class.getResourceAsStream("application.properties"));
authority = properties.getProperty("AUTHORITY");
scope = Collections.singleton(properties.getProperty("SCOPE"));
clientId = properties.getProperty("CLIENT_ID");
username = properties.getProperty("USER_NAME");
}
}
103 changes: 76 additions & 27 deletions src/samples/public-client/UsernamePasswordFlow.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,65 +8,114 @@
import com.microsoft.aad.msal4j.SilentParameters;
import com.microsoft.aad.msal4j.UserNamePasswordParameters;

import java.io.IOException;
import java.util.Collections;
import java.util.Properties;
import java.util.Set;

public class UsernamePasswordFlow {

private final static String CLIENT_ID = "";
private final static String AUTHORITY = "https://login.microsoftonline.com/organizations/";
private final static Set<String> SCOPE = Collections.singleton("");
private final static String USER_NAME = "";
private final static String USER_PASSWORD = "";
private static String authority;
private static Set<String> scope;
private static String clientId;
private static String username;
private static String password;

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

IAuthenticationResult result = acquireTokenUsernamePassword();
System.out.println("Access token: " + result.accessToken());
System.out.println("Id token: " + result.idToken());
System.out.println("Account username: " + result.account().username());
}

private static IAuthenticationResult acquireTokenUsernamePassword() throws Exception {
setUpSampleData();

// Load token cache from file and initialize token cache aspect. The token cache will have
// dummy data, so the acquireTokenSilently call will fail.
TokenCacheAspect tokenCacheAspect = new TokenCacheAspect("sample_cache.json");

PublicClientApplication pca = PublicClientApplication.builder(CLIENT_ID)
.authority(AUTHORITY)
.setTokenCacheAccessAspect(tokenCacheAspect)
PublicClientApplication pca = PublicClientApplication.builder(clientId)
.authority(authority)
.build();

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

//Attempt to acquire token when user's account is not in the application's token cache
IAuthenticationResult result = acquireTokenUsernamePassword(pca, scope, account, username, password);
System.out.println("Account username: " + result.account().username());
System.out.println("Access token: " + result.accessToken());
System.out.println("Id token: " + result.idToken());
System.out.println();

accountsInCache = pca.getAccounts().join();
account = getAccountByUsername(accountsInCache, username);

//Attempt to acquire token again, now that the user's account and a token are in the application's token cache
result = acquireTokenUsernamePassword(pca, scope, account, username, password);
System.out.println("Account username: " + result.account().username());
System.out.println("Access token: " + result.accessToken());
System.out.println("Id token: " + result.idToken());
}

private static IAuthenticationResult acquireTokenUsernamePassword(PublicClientApplication pca,
Set<String> scope,
IAccount account,
String username,
String password) throws Exception {
IAuthenticationResult result;
try {
SilentParameters silentParameters =
SilentParameters
.builder(SCOPE, account)
.builder(scope)
.account(account)
.build();
// try to acquire token silently. This call will fail since the token cache
// does not have any data for the user you are trying to acquire a token for
// Try to acquire token silently. This will fail on the first acquireTokenUsernamePassword() call
// because the token cache does not have any data for the user you are trying to acquire a token for
result = pca.acquireTokenSilently(silentParameters).join();
System.out.println("==acquireTokenSilently call succeeded");
} catch (Exception ex) {
if (ex.getCause() instanceof MsalException) {

System.out.println("==acquireTokenSilently call failed: " + ex.getCause());
UserNamePasswordParameters parameters =
UserNamePasswordParameters
.builder(SCOPE, USER_NAME, USER_PASSWORD.toCharArray())
.builder(scope, username, password.toCharArray())
.build();
// Try to acquire a token via username/password. If successful, you should see
// the token and account information printed out to console
result = pca.acquireToken(parameters).join();
System.out.println("==username/password flow succeeded");
} else {
// Handle other exceptions accordingly
throw ex;
}
}
return result;
}

/**
* Helper function to return an account from a given set of accounts based on the given username,
* or return null if no accounts in the set match
*/
private static IAccount getAccountByUsername(Set<IAccount> accounts, String username) {
if (accounts.isEmpty()) {
System.out.println("==No accounts in cache");
} else {
System.out.println("==Accounts in cache: " + accounts.size());
for (IAccount account : accounts) {
if (account.username().equals(username)) {
return account;
}
}
}
return null;
}

/**
* Helper function unique to this sample setting. In a real application these wouldn't be so hardcoded, for example
* values such as username/password would come from the user, and different users may require different scopes
*/
private static void setUpSampleData() throws IOException {
// Load properties file and set properties used throughout the sample
Properties properties = new Properties();
properties.load(UsernamePasswordFlow.class.getResourceAsStream("application.properties"));
authority = properties.getProperty("AUTHORITY");
scope = Collections.singleton(properties.getProperty("SCOPE"));
clientId = properties.getProperty("CLIENT_ID");
username = properties.getProperty("USER_NAME");
password = properties.getProperty("USER_PASSWORD");
}
}
9 changes: 9 additions & 0 deletions src/samples/public-client/application.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
CLIENT_ID=
USER_NAME=
USER_PASSWORD=

# The below properties do not need to be changed for this sample
# In a real situation they would be used to affect authentication behavior, such as changing where token requests are
# sent by using a different authority URL
AUTHORITY=https://login.microsoftonline.com/organizations/
SCOPE=user.read