How to fix 'com.microsoft.aad.msal4j.MsalClientException: java.net.SocketTimeoutException: Read timed out' exception?

Akriti Sinha 15 Reputation points
2023-07-07T12:44:50.1766667+00:00

Hi Team!

I have an issue. We are using the Azure's MSAL library for Java for generating and refreshing tokens for one of our system and lately we've been getting an exception 'com.microsoft.aad.msal4j.MsalClientException: java.net.SocketTimeoutException: Read timed out'.
The dependency that we're using for it is-

      <dependency>

            <groupId>com.microsoft.azure</groupId>

            <artifactId>msal4j</artifactId>

            <version>1.13.7</version>

        </dependency>

Is this a version issue or some other issue and how do we fix it?

Appreciate the help!!

Microsoft Security | Microsoft Entra | Microsoft Entra ID
{count} votes

2 answers

Sort by: Most helpful
  1. Noa Silberstein 5 Reputation points Microsoft Employee
    2023-09-27T14:13:51.4966667+00:00

    Hi @Alfredo Revilla - Upwork Top Talent | IAM SWE SWA

    We have the same issue :) we are using msal version 1.13.8.

    Acquiring token with this function:

    clientApplication.acquireToken
    
    

    This is the log and correlation ID:

    [Correlation ID: 7f28fdbd-bebb-45f1-99a1-1ce072f383e0] Execution of class com.microsoft.aad.msal4j.AcquireTokenByClientCredentialSupplier failed.
    

    This is the stack trace:

    com.microsoft.aad.msal4j.MsalClientException: java.net.SocketTimeoutException: Read timed out
    	at com.microsoft.aad.msal4j.HttpHelper.executeHttpRequest(HttpHelper.java:56)
    	at com.microsoft.aad.msal4j.OAuthHttpRequest.send(OAuthHttpRequest.java:33)
    	at com.microsoft.aad.msal4j.TokenRequestExecutor.executeTokenRequest(TokenRequestExecutor.java:33)
    	at com.microsoft.aad.msal4j.AbstractClientApplicationBase.acquireTokenCommon(AbstractClientApplicationBase.java:129)
    	at com.microsoft.aad.msal4j.AcquireTokenByAuthorizationGrantSupplier.execute(AcquireTokenByAuthorizationGrantSupplier.java:63)
    	at com.microsoft.aad.msal4j.AcquireTokenByClientCredentialSupplier.acquireTokenByClientCredential(AcquireTokenByClientCredentialSupplier.java:86)
    	at com.microsoft.aad.msal4j.AcquireTokenByClientCredentialSupplier.execute(AcquireTokenByClientCredentialSupplier.java:49)
    	at com.microsoft.aad.msal4j.AuthenticationResultSupplier.get(AuthenticationResultSupplier.java:69)
    	at com.microsoft.aad.msal4j.AuthenticationResultSupplier.get(AuthenticationResultSupplier.java:18)
    	at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1604)
    	at java.lang.Thread.run(Thread.java:750)
    Caused by: java.net.SocketTimeoutException: Read timed out
    	at java.net.SocketInputStream.socketRead0(Native Method)
    	at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
    	at java.net.SocketInputStream.read(SocketInputStream.java:171)
    	at java.net.SocketInputStream.read(SocketInputStream.java:141)
    	at sun.security.ssl.SSLSocketInputRecord.read(SSLSocketInputRecord.java:464)
    	at sun.security.ssl.SSLSocketInputRecord.bytesInCompletePacket(SSLSocketInputRecord.java:68)
    	at sun.security.ssl.SSLSocketImpl.readApplicationRecord(SSLSocketImpl.java:1346)
    	at sun.security.ssl.SSLSocketImpl.access$300(SSLSocketImpl.java:73)
    	at sun.security.ssl.SSLSocketImpl$AppInputStream.read(SSLSocketImpl.java:962)
    	at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
    	at java.io.BufferedInputStream.read1(BufferedInputStream.java:286)
    	at java.io.BufferedInputStream.read(BufferedInputStream.java:345)
    	at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:743)
    	at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:678)
    	at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1595)
    	at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1500)
    	at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
    	at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:352)
    	at com.microsoft.aad.msal4j.DefaultHttpClient.readResponseFromConnection(DefaultHttpClient.java:105)
    	at com.microsoft.aad.msal4j.DefaultHttpClient.executeHttpPost(DefaultHttpClient.java:63)
    	at com.microsoft.aad.msal4j.DefaultHttpClient.send(DefaultHttpClient.java:37)
    	at com.microsoft.aad.msal4j.HttpHelper.executeHttpRequestWithRetries(HttpHelper.java:99)
    	at com.microsoft.aad.msal4j.HttpHelper.executeHttpRequest(HttpHelper.java:52)
    	... 10 common frames omitted
    		
    
    
    

    Would appreciate your help with this.

    Thanks,

    Noa

    1 person found this answer helpful.

  2. David Norena Giraldo 0 Reputation points
    2024-04-15T13:24:58.2733333+00:00

    Hi everyone. For anyone is reading this, the solution that worked for me is checking the firewall.

    This error commonly dont came from development, this came from java.net.* which manages the http/https request to exchange the authCode to a Token using the url "login.microsoftonline.com/{tenant_id}/oauth2/token".

    Im using this sample: https://github.com/Azure-Samples/ms-identity-msal-java-samples/tree/main/3-java-servlet-web-app/3-Authorization-II/groups

    This is how i checked.

    1. Using Java 8 i've created a class and a method which receive the authcode. At this point the error is when exchanging the token, not getting the authCode. The method just return the token using the authCode. Call this class and method where the app is failling, if you get the same error, then continue with the next validation.
    import java.io.BufferedReader;
    import java.io.DataOutputStream;
    import java.io.InputStreamReader;
    import java.net.HttpURLConnection;
    import java.net.URL;
    import java.net.URLEncoder;
    import java.util.HashMap;
    import java.util.Map;
    public class AzureADTokenRequest {
        
        public static String getTokenByAuthCode(String authcode) {
            String CLIENT_ID = "";
            String SECRET = "";
            String REDIRECT_URI = "";
            String AUTHORITY = "";
            String resp = null;
            try {
          
                // Build token request parameters
                Map<String, String> params = new HashMap<>();
                params.put("client_id", CLIENT_ID);
                params.put("client_secret", SECRET);
                params.put("redirect_uri", REDIRECT_URI);
                params.put("code", authcode);
                params.put("grant_type", "authorization_code");
    
                // Create URL for token endpoint
                URL tokenUrl = new URL(AUTHORITY + "/oauth2/token");
    
                // Build URL-encoded form data
                StringBuilder postData = new StringBuilder();
                for (Map.Entry<String, String> param : params.entrySet()) {
                    if (postData.length() != 0) {
                        postData.append('&');
                    }
                    postData.append(URLEncoder.encode(param.getKey(), "UTF-8"));
                    postData.append('=');
                    postData.append(URLEncoder.encode(String.valueOf(param.getValue()), "UTF-8"));
                }
                byte[] postDataBytes = postData.toString().getBytes("UTF-8");
    
                // Create connection
                HttpURLConnection connection = (HttpURLConnection) tokenUrl.openConnection();
                connection.setRequestMethod("POST");
                connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
                connection.setRequestProperty("Content-Length",         	String.valueOf(postDataBytes.length));
                connection.setDoOutput(true);
    
                // Write form data to request body
                try (DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream())) {
                    outputStream.write(postDataBytes);
                }
    
                // Read response
                int responseCode = connection.getResponseCode();
                BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                StringBuilder response = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    response.append(line);
                }
                reader.close();
    
                // Close connection
                connection.disconnect();
                resp = response.toString();
    
                return resp;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return resp;
        }
    }
    
    1. Using postman. Use the authCode to check if the app registry have the right config. Dont change the grant_type.

    If this return the token then check out the firewall configurations. The app is fully configurated and is ready to use.User's image

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.