Azure-Samples / ms-identity-java-desktop

A desktop application in Java calling Microsoft Graph API
MIT License
23 stars 23 forks source link

Debugging the MSAL4J errors #11

Closed srivassumit closed 3 years ago

srivassumit commented 4 years ago

I am using the MSAL4j library in my Java 11 Spring Boot web app to authenticate using the username password flow.

I use a service account (work account not personal) to authenticate, and this line:

result = pca.acquireToken(parameters).join();

throws the following error:

org.xml.sax.SAXParseException: The element type "br" must be terminated by the matching end-tag "</br>".
       at java.xml/com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:261) ~[na:na]
       at java.xml/com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:339) ~[na:na]
       at java.xml/javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:122) ~[na:na]
       at com.microsoft.aad.msal4j.MexParser.getPolicy(MexParser.java:76) ~[msal4j-1.4.0.jar!/:1.4.0]
       at com.microsoft.aad.msal4j.MexParser.getWsTrustEndpointFromMexResponse(MexParser.java:112) ~[msal4j-1.4.0.jar!/:1.4.0]
       at com.microsoft.aad.msal4j.WSTrustRequest.execute(WSTrustRequest.java:62) ~[msal4j-1.4.0.jar!/:1.4.0]
       at com.microsoft.aad.msal4j.AcquireTokenByAuthorizationGrantSupplier.processPasswordGrant(AcquireTokenByAuthorizationGrantSupplier.java:76) ~[msal4j-1.4.0.jar!/:1.4.0]
       at com.microsoft.aad.msal4j.AcquireTokenByAuthorizationGrantSupplier.execute(AcquireTokenByAuthorizationGrantSupplier.java:33) ~[msal4j-1.4.0.jar!/:1.4.0]
       at com.microsoft.aad.msal4j.AuthenticationResultSupplier.get(AuthenticationResultSupplier.java:59) ~[msal4j-1.4.0.jar!/:1.4.0]
       at com.microsoft.aad.msal4j.AuthenticationResultSupplier.get(AuthenticationResultSupplier.java:17) ~[msal4j-1.4.0.jar!/:1.4.0]
       at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1700) ~[na:na]
       at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]

based on this error alone, it is not possible for me to to decipher the cause of this issue is and how to debug/fix it.

Providing some debug logs or a more detailed error message would be helpful.

PS: The code works fine as long as I am in the organization network (i.e. locally from my laptop on VPN), but when I deploy it to AWS kubernetes cluster which is outside my org network, it gives the above error.

Avery-Dunn commented 4 years ago

Hello, sorry for the late response, but I noticed you asked this question on StackOverflow around the same time as here, and that question got some answers. Were you able to solve your issue, or are you still running into problems?

srivassumit commented 4 years ago

Hi! Thanks for replying.

The issue was not really fixed with Java library, I ended up using the python library as a proxy for my Java code.

The underlying issue was that the call that the library makes was being blocked by our Org's security policy which sent a HTML response similar to this:

<html><head><title>Request Rejected</title></head><body>The requested URL was rejected. Please consult with your administrator.<br><br>Your support ID is: xxx</body></html>

But, with the Java library there was no way for me to figure out what the actual error is since it does not log the HTML error response anywhere. It only gave me the HTML parsing error that I mentioned above.. (The element type "br" must be terminated by the matching end-tag "</br>".)

Once we figured out the exact error response, we found out that it was happening because the MSAL library is sending a {'Content-Type': 'application/soap+xml'} header in the GET request which gets blocked by the security policy.

The Python library is fixing this error through this PR which is already merged I believe.

I think the issue with Java library is also similar, but I can't be sure of that because there is no way for me to confirm it.

It would be helpful if you could check the same for Java library and get that fixed too. Thanks!

srivassumit commented 4 years ago

hmm,

I think the issue with Java library is also similar

I was wrong, It looks like the Java library doesn't use those headers in its get request as per this and this.

So, now I'm not sure what the issue with the Java library is.

But, I'm sure that is is still being blocked by the security policy because of this reason: HTTP protocol compliance failed: Body in GET or HEAD requests

SomkaPe commented 4 years ago

Msal Java uses {'Content-Type': 'application/soap+xml'} header for WS Trust requests, because content of requests is soap+xml, mentioned "fix" for Python library is to not set that header, which :

  1. does not change the fact that content type of request is soap+xml
  2. it is recommended to set that header - so server does not have to guess format of content in the request
srivassumit commented 4 years ago

The Content-Type header is only required in POST or PUT requests i.e. requests which have a request body, because it specifies the content type of the body. It is not required for GET requests. (Reference)

So, if the request is a Http GET (which was the case in Python library) then it should not be adding the Content-Type header. and they have fixed this with their PR.

Does the Java Library also add the header to a GET request?

srivassumit commented 4 years ago

Btw,

does not change the fact that content type of request is soap+xml

I did not understand what you meant by this?

If it is a GET request, why is Soap/XML content being sent over?

SomkaPe commented 4 years ago

https://github.com/AzureAD/microsoft-authentication-library-for-java/blob/ca87b927f249f7dd00bb422be255137409cbe492/src/main/java/com/microsoft/aad/msal4j/WSTrustRequest.java

It is POST request

srivassumit commented 4 years ago

Ah okay, if it is POST then it won't be blocked due to security policy. It is blocked due to some other reason then.

If there was some way of logging the intermediate HTML response then I could share that with my security team and find out the exact reason why it is blocked.

I'm looking into Springboot actuator to log intermediate requests/responses to see if that helps in figuring out what the intermediate response is.

let me know if you know a better way to log the intermediate HTML responses?

SomkaPe commented 4 years ago

Agree it might be useful to log server-side response which MSAL failed to parse, we probably should consider it. Meanwhile you could debug app to see exact response. MSAL expects XML doc as response for WSTrust request. Based on parsing error - "The element type "br" must be terminated by the matching end-tag "
" - looks like html doc returned