👷‍♂️
Work
  • 💻SNOW
    • Catalog Forms
    • Knowledge Base
  • ☁️Azure
    • Graph Permissions
    • App Registration Auths
      • Postman
      • Graph ROPC Federated Account
        • MSAL UsernamePasswordCredential
        • Java
        • Python
        • C#/VB code Auth
      • Powershell
      • Java Auth x EWS
      • Python Auth x Sharepoint
      • C# Auth x Sharepoint
    • MFA
    • Dynamic Group
    • AAD Device Pending
    • O365 Device Enrollment
    • AAD Device Troubleshoot
    • AAD Mobile Troubleshooting
    • ADO Service Principal
    • External B2B
    • VLSC Admin
    • PowerBI Session Timeout
    • SSO issues
  • 🔓OKTA
    • SVC Account
    • OKTA Integration
    • Access Issues
  • 👷‍♂️Workday
    • Account Lifecycle
    • Coupa
  • 📨O365
    • OOF of Distribution List
    • Mailbox Recovery
    • Mailbox Existence
  • 🦄Misc
    • Windows Terminal
    • Google Auth Export
    • MS Teams Issues
  • 🌥️Cloud Stuff
    • 🚀Benchmarking
      • Vultr
    • 💳Cloud Server
    • ♻️Email and Spams
  • 🔬Open Source
    • Pending
      • Matrix/Synapse
      • Huginn
      • ChangeDetection
    • Tested
      • Codex Docs
      • Ghost Blog
      • n8n Automation
Powered by GitBook
On this page
  1. Azure
  2. App Registration Auths

Java Auth x EWS

Docs and code samples for Java Auth

PreviousPowershellNextPython Auth x Sharepoint

Last updated 2 years ago

This old example is using the "basic auth" method

// Using Microsoft.Identity.Client 4.22.0

// Configure the MSAL client to get tokens
var pcaOptions = new PublicClientApplicationOptions
{
    ClientId = ConfigurationManager.AppSettings["appId"],
    TenantId = ConfigurationManager.AppSettings["tenantId"]
};

var pca = PublicClientApplicationBuilder
    .CreateWithApplicationOptions(pcaOptions).Build();

// The permission scope required for EWS access
var ewsScopes = new string[] { "https://outlook.office365.com/EWS.AccessAsUser.All" };

// Make the interactive token request
var authResult = await pca.AcquireTokenInteractive(ewsScopes).ExecuteAsync();

...then pass the token to the ewsclient

// Configure the ExchangeService with the access token
var ewsClient = new ExchangeService();
ewsClient.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx");
ewsClient.Credentials = new OAuthCredentials(authResult.AccessToken);
private static IAuthenticationResult acquireTokenUsernamePassword() throws Exception {

    // 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)
            .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();

    IAuthenticationResult result;
    try {
        SilentParameters silentParameters =
                SilentParameters
                        .builder(SCOPE, 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
        result = pca.acquireTokenSilently(silentParameters).join();
    } catch (Exception ex) {
        if (ex.getCause() instanceof MsalException) {

            UserNamePasswordParameters parameters =
                    UserNamePasswordParameters
                            .builder(SCOPE, USER_NAME, USER_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();
        } else {
            // Handle other exceptions accordingly
            throw ex;
        }
    }
    return result;
}

Sample codes from Microsoft below

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(account)
                        .build();
        // 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, 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;
}

public static String getAccessToken() throws Exception {
    Set<String> scope = new HashSet<String>();
    scope.add("https://outlook.office365.com/.default");
    String username = "test1@onmicrosoft.com";
    String password = "userPass";
    String clientId = "xxxxxb-f4be-4e2e-95dd-7aa4f5dxxxxx";
    String tenantId = "xxxxx65f-f7e3-4bc3-841f-13b29xxxxx";
    String authority =
            "https://login.microsoftonline.com/" + tenantId + "/oauth2/v2.0/token";
    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();
    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());

    return "";
}

private static IAccount getAccountByUsername(final Set<IAccount> accountsInCache, final String username) {
    if (accountsInCache.isEmpty()) {
        System.out.println("==No accounts in cache");
    } else {
        System.out.println("==Accounts in cache: " + accountsInCache.size());
        for (IAccount account : accountsInCache) {
            if (account.username().equals(username)) {
                return account;
            }
        }
    }
    return null;
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 * Azure resource owner password credential (ROPC) token provider
 * https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth-ropc
 * https://docs.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-authenticate-an-ews-application-by-using-oauth
 * https://portal.azure.com
 * https://developer.microsoft.com/en-us/graph/graph-explorer/#
 * token parser https://jwt.io
 * </p>
 */
class AzureROPCTokenProvider implements ITokenProvider {

    private static final String GRANT_TYPE = "password";

    private final String clientId;
    private final String clientSecret;
    private final String userName;
    private final String password;
    private final String tenant;
    private final String scope;

    private OAuthToken token;

    public AzureROPCTokenProvider(String tenant, String clientId, String clientSecret,
                                  String userName, String password, String[] scopeAr) {
        this.tenant = tenant;
        this.clientId = clientId;
        this.clientSecret = clientSecret;
        this.userName = userName;
        this.password = password;
        this.scope = joinToStr(scopeAr, " ");
    }

    public synchronized OAuthToken getAccessToken(boolean ignoreExistingToken) {
        if (this.token != null && !this.token.getExpired() && !ignoreExistingToken)
            return this.token;
        token = null;

        Map<String, String> tokenArgs = geToken();

        java.util.Calendar c = java.util.Calendar.getInstance();
        c.add(java.util.Calendar.SECOND, Integer.parseInt(tokenArgs.get("expires_in")));
        token = new OAuthToken(tokenArgs.get("access_token"), TokenType.AccessToken, c.getTime());
        return token;
    }

    public final OAuthToken getAccessToken() {
        return getAccessToken(false);
    }

    public void dispose() {
    }

    private String getEncodedParameters() {
        return "client_id=" + urlEncode(clientId) + "&scope=" + urlEncode(scope) + "&username=" + urlEncode(userName)
                + "&password=" + urlEncode(password) + "&grant_type="
                + urlEncode(GRANT_TYPE);
    }

    private String getUri() {
        if (tenant == null || tenant.trim().isEmpty())
            return "https://login.microsoftonline.com/common/oauth2/v2.0/token";
        else
            return "https://login.microsoftonline.com/" + tenant + "/oauth2/v2.0/token";
    }

    private Map<String, String> geToken() {
        try {
            HttpURLConnection connection = (HttpURLConnection) new URL(getUri()).openConnection();
            connection.setRequestMethod("POST");

            byte[] requestData = getEncodedParameters().getBytes(StandardCharsets.UTF_8);

            connection.setUseCaches(false);
            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            connection.setRequestProperty("Content-Length", "" + requestData.length);

            final OutputStream st = connection.getOutputStream();
            try {
                st.write(requestData, 0, requestData.length);
            } finally {
                st.flush();
                st.close();
            }

            connection.connect();

            if (connection.getResponseCode() >= HttpURLConnection.HTTP_BAD_REQUEST) {
                throw new IllegalAccessError("Operation failed: " + connection.getResponseCode() + "/" +
                        connection.getResponseMessage() + "\r\nDetails:\r\n{2}"
                        + readInputStream(connection.getErrorStream()));
            }

            String responseText = readInputStream(connection.getInputStream());

            Map<String, String> result = new HashMap<>();
            String[] fromJsonToKeyValue = responseText.replace("{", "").replace("}", "")
                    .replace("\"", "").replace("\r", "")
                    .replace("\n", "").split(",");
            for (String keyValue : fromJsonToKeyValue) {
                String[] pair = keyValue.split(":");
                String name = pair[0].trim().toLowerCase();
                String value = urlDecode(pair[1].trim());
                result.put(name, value);
            }

            return result;
        } catch (IOException e) {
            throw new IllegalAccessError(e.getMessage());
        }
    }

    static String urlEncode(String value) {
        try {
            return URLEncoder.encode(value, StandardCharsets.UTF_8.toString());
        } catch (UnsupportedEncodingException e) {
            throw new IllegalAccessError(e.getMessage());
        }
    }

    static String urlDecode(String value) {
        try {
            return URLDecoder.decode(value, StandardCharsets.UTF_8.toString());
        } catch (UnsupportedEncodingException e) {
            throw new IllegalAccessError(e.getMessage());
        }
    }

    static String readInputStream(InputStream is) {
        if (is == null)
            return "";

        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder result = new StringBuilder();
        String line;
        try {
            while ((line = reader.readLine()) != null) {
                result.append(line);
            }
        } catch (IOException e) {
            // ignore
        }
        return result.toString();
    }

    static String joinToStr(String[] arr, String sep) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < arr.length; i++) {
            if (i > 0)
                sb.append(sep);
            sb.append(arr[i]);
        }
        return sb.toString();
    }
}

...which needs to be replaced with the code snippets by getting a token first

The example above is using the "Interactive" method for auth; if we need to use the "Non-Interactive" method, we need to use another method to get the token, like .

More examples can be found

☁️
from this document
the guide here
here.
EWS API Example (GitHub)
API Permission for this example