Fork me on GitHub
#java
<
2021-01-07
>
orestis14:01:21

I’m having Java issues with Microsoft authentication library https://github.com/AzureAD/microsoft-authentication-library-for-java I’m starting from this code:

IClientCredential credential = ClientCredentialFactory.createFromSecret(CLIENT_SECRET);
ConfidentialClientApplication app = 
    ConfidentialClientApplication
        .builder(PUBLIC_CLIENT_ID, credential)
        .authority(AUTHORITY)
        .build();
I have translated this to
(let [credential (ClientCredentialFactory/createFromSecret secret-value)
      builder ^ConfidentialClientApplication$Builder
      (ConfidentialClientApplication/builder client-id credential)]
  (->
    builder
    (.authority authority)
    (.build)))
But I’m getting this exception:
; (err) Execution error (IllegalArgumentException) at nosco.azure/eval85548 (REPL:35).
; (err) No matching method authority found taking 1 args for class com.microsoft.aad.msal4j.ConfidentialClientApplication$Builder

orestis14:01:28

Turning on reflection warnings says:

call to method authority on com.microsoft.aad.msal4j.ConfidentialClientApplication$Builder can't be resolved (argument types: java.lang.String).

alexmiller15:01:32

Lombok .... rolls eyes

orestis15:01:13

Well at least they had the source available... saved me another day of fumbling in the dark.

orestis15:01:52

@alexmiller I take it it’s a known thing? Can I brute force my way around it? I just want to do a PoC this time round.

orestis15:01:41

This looks to be a thick layer on top of some http apis anyway so I might just go underneath eventually but I was hoping for a quick demo.

alexmiller15:01:12

Lombok is all about pretending Java was less cumbersome to use

alexmiller15:01:40

by giving you alternate syntax (hey, just use Clojure!) :)

alexmiller15:01:54

but it may be obscuring what the actual method looks like

alexmiller15:01:43

is the real method maybe getAuthority()?

alexmiller15:01:04

or setAuthority() ?

orestis15:01:50

(->
  (r/reflect ConfidentialClientApplication$Builder)
  :members
  (->> (map :name)))

alexmiller15:01:55

might be useful to use the reflection API directly and see what the actual methods are (or use clojure.reflect/reflect)

orestis15:01:01

(com.microsoft.aad.msal4j.ConfidentialClientApplication$Builder
 build
 access$000
 com.microsoft.aad.msal4j.ConfidentialClientApplication$Builder
 build
 clientCredential
 self
 sendX5c
 self
 access$100
 sendX5c)

orestis15:01:32

This is what I found confusing, I tried the reflection at first but this is the names of the members…

alexmiller15:01:44

members are fields I think here

alexmiller15:01:08

oh, I guess it's methods and fields

orestis15:01:16

Yeah… well actually going to the ancestor (the base class) yields these members:

(aadInstanceDiscoveryResponse
 aadInstanceDiscoveryResponse
 access$000
 access$100
 access$1000
 access$1100
 access$1200
 access$1300
 access$1400
 access$1500
 access$1600
 access$1700
 access$1800
 access$200
 access$300
 access$400
 access$500
 access$600
 access$700
 access$800
 access$900
 applicationName
 applicationName
 applicationVersion
 applicationVersion
 authenticationAuthority
 authority
 authority
 b2cAuthority
 build
 clientCapabilities
 clientCapabilities
 clientId
 com.microsoft.aad.msal4j.AbstractClientApplicationBase$Builder
 connectTimeoutForDefaultHttpClient
 connectTimeoutForDefaultHttpClient
 correlationId
 correlationId
 createDefaultAADAuthority
 executorService
 executorService
 httpClient
 httpClient
 logPii
 logPii
 onlySendFailureTelemetry
 onlySendFailureTelemetry
 proxy
 proxy
 readTimeoutForDefaultHttpClient
 readTimeoutForDefaultHttpClient
 self
 setTokenCacheAccessAspect
 sslSocketFactory
 sslSocketFactory
 telemetryConsumer
 telemetryConsumer
 tokenCacheAccessAspect
 validateAuthority
 validateAuthority)

orestis15:01:12

OK, I think I’ve found it:

{:name authority,
  :type java.lang.String,
  :declaring-class
  com.microsoft.aad.msal4j.AbstractClientApplicationBase$Builder,
  :flags #{:private}}
 {:name authority,
  :return-type
  com.microsoft.aad.msal4j.AbstractClientApplicationBase$Builder,
  :declaring-class
  com.microsoft.aad.msal4j.AbstractClientApplicationBase$Builder,
  :parameter-types [java.lang.String],
  :exception-types [java.net.MalformedURLException],
  :flags #{:public}}

orestis15:01:44

so there is a both a private field named authority and a public method, but they’re both on the parent abstract class

alexmiller15:01:03

that should be fine

alexmiller15:01:16

. prefers method if both exist

alexmiller15:01:26

(.- is always field)

orestis15:01:43

Still doesn’t work though 😞

alexmiller15:01:46

did you try type-hinting the arg to ^String? I doubt that would help since it's reporting it as String already, but I dunno

orestis15:01:55

I’ve hinted yeah

orestis15:01:17

I should be able to do (.-authority builder) right? but that throws the same exception

alexmiller15:01:37

without really diving into guts of the reflection code, I can't really tell what's wrong

alexmiller15:01:57

if you can file a repro at http://ask.clojure.org I will eventually look at it but can't atm

orestis15:01:22

Is there any workaround you could think of? I could perhaps use reflection to make the field private and set it manually?

orestis15:01:50

I’ll file a repro. Does a git repo work for you or perhaps a deps.edn with a single .clj file?

alexmiller15:01:30

seems different than that though

alexmiller15:01:05

ideally repro would be a clj -Sdeps ... and some code I can run with that

orestis15:01:05

Hm, the javadoc shows T as the return argument for those. So perhaps they are generic.

orestis15:01:54

I need to run, thanks @alexmiller for helping me figuring out some parts.

orestis15:01:07

I’ll file a repro tomorrow. Have a great day!