Remote Java Client with OAuthBearer with KeyCloak

353 views
Skip to first unread message

Mansour Al Akeel

unread,
May 16, 2024, 5:02:44 PM5/16/24
to WildFly

We are using WF-26.1 with a desktop application.

We need to authenticate swing application to remote EJBs, and hoping to migrate to an SSO solution. I am trying to get an simple client example working. Following the example Secure WildFly CLI with Keycloak


Now that I am reading about Virtual Security I am not sure if this is doable. Can anyone with more knowledge help me understanding if securing EJBs applications with JWT and accessible from desktop applications.

Thank you.

Prarthona Paul

unread,
May 22, 2024, 9:49:21 AM5/22/24
to WildFly
Hello there, 
Perhaps this guide on identity propagation and using virtual security domains to secure an EJB can be useful: https://wildfly-security.github.io/wildfly-elytron/blog/wildfly-oidc-identity-propagation/
Please feel free to follow up with any other questions you may have. 
Best, 
Prarthona

Farah Juma

unread,
May 22, 2024, 10:52:39 AM5/22/24
to WildFly
One thing to note is that virtual domains are only used when securing apps deployed to WildFly with OIDC or MP JWT. Details on how to propagate the security identity in these cases to an EJB can be found here:

Identity Propagation for MP JWT

For the OAuthBearer case, a normal Elytron security domain will be used (e.g., in Secure WildFly CLI with Keycloak, the "my-jwt-domain" security-domain is used. Some examples of propagating the security identity to an EJB when using a normal Elytron security domain can be found here:


Mansour Al Akeel

unread,
May 30, 2024, 10:01:33 AM5/30/24
to WildFly
Prarthona and Farah,

Thank you a lot for taking the time to help out, and sorry for the late reply, however I am back working on this issue.
I am using WF 26, but we are hopefully upgrading soon to the latest.

Referring to the blog post:
/subsystem=elytron/virtual-security-domain
Will not work, since I guess it is written for more recent WF version and will not work on WF 26. I will try to dig deeper into the provided example.

I think the problem, is on my side not fully understanding all the moving parts and the terminology. 

I simplified my setup a bit by taking elytron OIDC client out of the picture, and just setting up oidc-realm configured with KeyCloak client. Therefore, the only setup in place is the realm. This is working fine so far with Our Rest-API setup, but I would like to extend it to EJBs being called from remote client and over http+remote protocol.

The issue I think is with the Flow (and I just learned about Oauth2.0 Flow this week, so I can be using it wrong). I am looking for a way to retrieve the token from keyCloak. For example, the following code is working to some extent:

BearerTokenCredential token = new BearerTokenCredential(VERY_LONG_STRING_TOKEN_FROM_KEYCLOAK);


AuthenticationConfiguration authConfig = AuthenticationConfiguration.empty() //

.useCallbackHandler(new SampleCallbackHandler()) //

.setSaslMechanismSelector(SaslMechanismSelector.fromString("OAUTHBEARER")) //

.useBearerTokenCredential(token);


AuthenticationContext context = AuthenticationContext.empty() //

.with(MatchRule.ALL, authConfig);


The simplest way I am thinking/hoping to get it running is:

  1. Connect to the EJB (may be with credentials username/password, or without).
  2. Upon failing authentication, retrieve token from KeyCloak
  3. Use the token to authenticate
The current setup I have, seems to be missing at least item-2 (retrieving Oauth2 Token from KeyCloak).
I can hardcode/configure keycloak auth-url to retrieve the token, but then this is painful to maintain for
many applications/customers. Additionally, I am missing the part where the AuthenticationClient may connect to KC and obtain a token if it
is not available. At the moment I am hardcoding it "VERY_LONG_STRING_TOKEN_FROM_KEYCLOAK".
Of course callback handler is not being invoked in the above code, as it was earlier at some point. I may need to rectify this if I want to store the token
in secure storage on the client for extended period of time.

I will be trying to recreate my setup and clean prior configurations with virtual-security-domain. It is worth mentioning that at this point, all I need
is to get authentication to work, and understand what is happening. I am less concerned about authorization (to keep it simple).

My questions now, given that:
* We are using WF 26.
* I am concerned only with Authentication using OAuth2.
* A working setup is working for Rest-API.
* The above code are producing the error:

08:09:29,744 TRACE [org.wildfly.security] (default task-1) Handling SecurityIdentityCallback: identity = SecurityIdentity{principal=mansour, securityDomain=org.wildfly.security.auth.server.SecurityDomain@17615f20, authorizationIdentity=EMPTY, realmInfo=RealmInfo{name='oidc-realm', securityRealm=org.wildfly.security.auth.realm.token.TokenSecurityRealm@2d390a84}, creationTime=2024-05-30T12:09:29.734233100Z}
08:09:30,096 TRACE [org.wildfly.security] (default task-1) Principal assigning: [mansour], pre-realm rewritten: [mansour], realm name: [ApplicationRealm], post-realm rewritten: [mansour], realm rewritten: [mansour]
08:09:30,702 INFO  [com.somedomain.example.JNDIUtils] (default task-1) Remoting Address set to 'remote+http://127.0.0.1:8080'
08:09:30,709 INFO  [org.wildfly.naming] (default task-1) WildFly Naming version 1.0.15.Final
08:09:30,739 INFO  [org.jboss.ejb.client] (default task-1) JBoss EJB Client version 4.0.44.Final
08:09:30,795 TRACE [org.wildfly.security.xml] (default task-1) Fallback to parse legacy configuration.
08:09:30,795 TRACE [org.wildfly.security.xml] (default task-1) No legacy configuration available, using AuthenticationContext.empty()
08:09:30,818 TRACE [org.wildfly.security] (default task-1) getAuthenticationConfiguration uri=remote+http://127.0.0.1:8080, protocolDefaultPort=-1, abstractType=ejb, abstractTypeAuthority=jboss, MatchRule=[null], AuthenticationConfiguration=[AuthenticationConfiguration:principal=anonymous,set-host=127.0.0.1,set-protocol=remote+http,set-port=8080,providers-supplier=org.wildfly.security.provider.util.ProviderUtil$1@3693b54,mechanism-properties={wildfly.sasl.local-user.quiet-auth=true}]
08:09:30,889 TRACE [org.wildfly.security] (XNIO-1 I/O-1) Created SaslClient [null] for mechanisms [OAUTHBEARER]
08:09:30,897 TRACE [org.wildfly.security.xml] (XNIO-1 task-1) Fallback to parse legacy configuration.
08:09:30,906 TRACE [org.wildfly.security.xml] (XNIO-1 task-1) No legacy configuration available, using AuthenticationContext.empty()
08:09:30,909 ERROR [com.somedomain.example.DBLoaderTest] (default task-1) Error while trying to load db properties: org.jboss.ejb.client.RequestSendFailedException: EJBCLIENT000409: No more destinations are available
        at org.jboss....@4.0.44.Final//org.jboss.ejb.client.EJBClientInvocationContext.getResult(EJBClientInvocationContext.java:620)

Which tells me the authentication is NOT working, but the exception is generated somewhere in my code. Not sure yet what to conclude from this, but
I am studying/reviewing the flow to have deeper understanding. Does this mean I need to setup Identity Propagation properly ? If so, how to deal with
virtual security domain through CLI in WF 26 ?

Thank you a lot for your help



Mansour Al Akeel

unread,
Jun 7, 2024, 3:18:08 PM6/7/24
to WildFly
I am still hoping to get some help from the community.

I was able to get the authentication to work successfully using Token-Realm (oauth2-realm) configured with KeyCloak. Pending issues:
* We are using naming client for remote JNDI "remote+http://localhost:8080".  javax.security.auth.callback.CallbackHandler  is not invoked with this protocol.
The following code is what I am using:

BearerTokenCredential token = new BearerTokenCredential(VERY_LONG_STRING_TOKEN_FROM_KEYCLOAK);

AuthenticationConfiguration authConfig = AuthenticationConfiguration.empty()

.useBearerTokenCredential(token)
.useCallbackHandler(new SampleCallbackHandler());


The above code works fine with http-client connector "http://localhost:8080/wildfly-services", and the callbacks are invoked properly. While the authenticating

a user with the token is working fine in both cases, but NOT with the remote naming client. Based on my understanding, I think this is due to the fact that SASL is

supported only in http and not in remoting jndi. Therefore the only way to get the Callback handlers to work is to switch to "http:" and use SASL.

Is this correct ? Am I missing something here ?


* I am still looking for a client side factory where I can plugin token retrieval upon authentication failure, and hopefully to securiley store the token on the

client machine for extended period of time. I can do this step programmatically, but I feel retrieving a token from KeyCloak is a common usecase, and should use

existing tools (if exist). So my question is, is there a different Authentication factory I should use to allow retrial ?


Thank you a lot for taking the time to help.


Mansour Al Akeel

unread,
Jun 12, 2024, 11:16:46 AM6/12/24
to WildFly
For someone facing the same issue, the problem was that I was using the wrong AuthenticationConfiguration  configuration.
I was using:

AuthenticationConfiguration. useCallbackHandler (new SampleCallbackHandler());

while the correct way is:
AuthenticationConfiguration.useCredentialCallbackHandler(new SampleCallbackHandler());
Reply all
Reply to author
Forward
0 new messages