AzureAD / microsoft-authentication-library-for-java

Microsoft Authentication Library (MSAL) for Java http://aka.ms/aadv2
MIT License
280 stars 137 forks source link

Acquiring Token Interactively without Triggering Firewall? #796

Closed rijami00 closed 3 months ago

rijami00 commented 4 months ago

https://github.com/AzureAD/microsoft-authentication-library-for-java/wiki/Acquiring-Token-Interactively

So when I attempt this, if the java.exe has not been added to windows firewall list, this always triggers a firewall popup to allow java on public/private/domain networks.

For this use case, it really doesn't matter from what I can understand. Even if you dont allow it, the MSAL will still get the token because the browser is redirecting to a port on localhost.

I tried to set redirect URI as http://localhost, http://localhost:xyz and http://127.0.0.1; all triggered the popup. And even if I blocked instead of allowing, the token acquisation was a success for this call and all subsequent calls.

Is there any way to avoid this popup?

Avery-Dunn commented 4 months ago

Hello @rijami00 : I haven't run into this problem before. Just to clarify some things:

By default, MSAL Java just uses some built-in Java functionality to open the default system browser: https://github.com/AzureAD/microsoft-authentication-library-for-java/blob/02da37963cd9f256bb2af52b8a90c5e76f840a1f/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/AcquireTokenByInteractiveFlowSupplier.java#L149

It seems like there are some security settings that don't trust Java applications doing any network calls, unrelated to what MSAL specifically is doing.

You could try making a simple app that just does the same browser stuff that MSAL does (like a main method with just Desktop.getDesktop().browse(URI.create("https://some-real-or-fake-domain.com"));), that will at least help narrow down what part of the program your security settings don't trust.

rijami00 commented 4 months ago

Hi.

You can try the sample I have provided in #789 (except dont set the broker).

I'm not talking about silent acquire. I'm talking about calling interactive repeatedly (just for the sake of it).

So in a plain java file, if you call interactive flow, it will open browser and once logged in, will redirect to localhost:xyz. However, while the browser opens, MSAL also starts listening on localhost:xyz and that triggers windows firewall.

It doens't matter if you allow or block it, the token acquisation is successful (since we are only listening on local).

Now if you run the same plain java file again and again (which is calling interactive), it will succeed without the firewall popup regardless if you have previously allowed it or not. Ofc, browser popup will come up as usual.

If I delete the entries in windows firewall, then the firewall popup will trigger again.

Here you can see I ignored the firewall popup and it blocked java.exe from listening on ports (on network). I don't think it can (or wont) block on purely local.

image

I dont think the issue is with opening browser. the issue is listening on a port.

rijami00 commented 4 months ago

Does that popup happen right before the browser opens, or when you first start your application?

Right when browser opens, as that's when MSAL starts to listen to port. For the sake of testing, I'm not bringing up my app at all; just a plain java file.

Have you tried any other flow other than interactive?

Silent doesn't trigger anything; so all good there.

Do you see any error logs, stack traces, etc.?

Nothing out of ordinary as MSAL works perfectly in this case regardless if the user allows or blocks the application (here: java.exe). It is the popup that I want to avoid as it can create panic to the user and needless friction.

rijami00 commented 4 months ago

I have tried the Desktop open browser code, it opens the browser just fine and no firewall popup.

rijami00 commented 4 months ago

So I tried some sample code in plain java.

Firewall does not trigger for:

but triggers for:

here's the sample code:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

import java.io.*;
import java.net.*;

public class SimpleServer {
    public static void main(String[] args) {
        int port = 12345; // The port number to listen on
        String ipAddress = "localhost";
        // String ipAddress = "127.0.0.1";
        // String ipAddress = "192.168.1.xxx";

        try {
            InetAddress address = InetAddress.getByName(ipAddress);
            try (ServerSocket serverSocket = new ServerSocket(port, 50, address)) {
                System.out.println("Server is listening on IP " + ipAddress + " and port " + port);

                while (true) {
                    try (Socket socket = serverSocket.accept()) {
                        System.out.println("New client connected");

                        BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                        String line = input.readLine(); // Read a line of text
                        System.out.println("Received: " + line);
                    } catch (IOException e) {
                        System.out.println("I/O error: " + e.getMessage());
                    }
                }
            }
        } catch (IOException ex) {
            System.out.println("Server exception: " + ex.getMessage());
            ex.printStackTrace();
        }
    }
}
Avery-Dunn commented 3 months ago

I tried your sample code and couldn't get any firewall popup, so it does seem to be a security configuration issue.

Since that sample code doesn't trigger the pop-up for you for localhost but using localhost in MSAL triggers it, then I'm not sure the listening is the issue.

The only other thing I can think of is you can try disabling instance discovery by setting PublicClientApplication's instanceDiscovery field to false. Instance discovery is a call to a Microsoft endpoint (something similar to https://login.microsoftonline.com/common/discovery/instance) that occurs in parallel with the token acquisition, so that could be the call that's causing the popup.

Other than that, I'm not sure if there's any other advice than to lower your security settings or whitelist Java. I don't suppose you have another device with different security to test the code on?

crimsonvspurple commented 3 months ago

If you ensure firewall is not blocking or allowing java, then you will get prompt (if you have your firewall configured properly) because java is trying to listen on 192.168.x.x which is on the network, not on localhost.

The issue here is binding to all available interfaces in https://github.com/AzureAD/microsoft-authentication-library-for-java/blob/02da37963cd9f256bb2af52b8a90c5e76f840a1f/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/HttpListener.java#L28

crimsonvspurple commented 3 months ago

This will solve the issue: https://github.com/AzureAD/microsoft-authentication-library-for-java/pull/797

On a side note, which JDK are you using for development? I had to fall back to 11 until I was actually able to build the project. Lombok version seemed really old.

Avery-Dunn commented 3 months ago

Thanks for that PR, we'll give it a look and get into an upcoming release if it all looks good (likely this week or next week)

We target Java 8 and above: Java 8 is the default in our internal tests/pipelines so it's just what I usually use, plus 11 and the latest versions to ensure everything works with newer versions. It looks like we're still using a version of Lombok from 2019 which is around when most of the original development happened. In the past we've mainly update dependencies when CVEs are found or we need a specific new feature, but we're planning on being more proactive about it going forward.

crimsonvspurple commented 3 months ago

No problem. While it is mentioned this library works on Java 8+, I think it should be mentioned somewhere that to actually build the project, we need 8 or 11. I tried with 21, 17; took me a while to realize what was going on and fall back to 11.

Avery-Dunn commented 3 months ago

The fix made by @crimsonvspurple in https://github.com/AzureAD/microsoft-authentication-library-for-java/pull/797 has now been released in version 1.15.0 of msal4j. Thanks again for the fix, and if anyone is still having issues or faces new ones feel free to re-open this thread or start a new one.