I've set up Wildfly to use OAUTHBEARER auth mechanism for remote JNDI EJB lookups between my server and a desktop app, and it works great.
However, I also want to set up a simple .properties file based auth method to communicate with the server without a token to be able request one, or access information about the keycloak auth server as i don't want to hardcode it into my client application, and I can't seem to make it work. Whatever I do, the server rejects my auth attempts.
The sample code I was trying to reach the a pre auth bean with looks like this:
private static PreAuth lookUpPreAuthBean() throws NamingException
{
final Properties jndiProperties = new Properties();
jndiProperties.put(Context.INITIAL_CONTEXT_FACTORY, "org.wildfly.naming.client.WildFlyInitialContextFactory");
jndiProperties.put(Context.PROVIDER_URL,"http-remoting://localhost:8080");
jndiProperties.put(Context.SECURITY_PRINCIPAL, "test");
jndiProperties.put(Context.SECURITY_CREDENTIALS, "test");
final Context initialContext = new InitialContext(jndiProperties);
return (PreAuth) initialContext.lookup("ejb:server/server-ejb/PreAuthImpl!co.my.package.server.PreAuth");
}
Here is the stacktrace I get:
Suppressed: javax.security.sasl.SaslException: ELY05019: No token was given
at org.wildfly.security.mechanism.oauth2.OAuth2Client.getInitialResponse(OAuth2Client.java:66)
at org.wildfly.security.sasl.oauth2.OAuth2SaslClient.evaluateMessage(OAuth2SaslClient.java:62)
at org.wildfly.security.sasl.util.AbstractSaslParticipant.evaluateMessage(AbstractSaslParticipant.java:225)
at org.wildfly.security.sasl.util.AbstractSaslClient.evaluateChallenge(AbstractSaslClient.java:98)
at org.wildfly.security.sasl.util.AbstractDelegatingSaslClient.evaluateChallenge(AbstractDelegatingSaslClient.java:54)
at org.wildfly.security.sasl.util.PrivilegedSaslClient.lambda$evaluateChallenge$0(PrivilegedSaslClient.java:55)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at org.wildfly.security.sasl.util.PrivilegedSaslClient.evaluateChallenge(PrivilegedSaslClient.java:55)
at org.jboss.remoting3.remote.ClientConnectionOpenListener$Capabilities.lambda$handleEvent$1(ClientConnectionOpenListener.java:459)
at org.jboss.remoting3.EndpointImpl$TrackingExecutor.lambda$execute$0(EndpointImpl.java:991)
at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1990)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1348)
at org.xnio.XnioWorker$WorkerThreadFactory$1$1.run(XnioWorker.java:1280)
at java.base/java.lang.Thread.run(Thread.java:829)
Suppressed: javax.security.sasl.SaslException: DIGEST-MD5: Server rejected authentication
at org.jboss.remoting3.remote.ClientConnectionOpenListener$Authentication.handleEvent(ClientConnectionOpenListener.java:760)
at org.jboss.remoting3.remote.ClientConnectionOpenListener$Authentication.handleEvent(ClientConnectionOpenListener.java:602)
at org.xnio.ChannelListeners.invokeChannelListener(ChannelListeners.java:92)
at org.xnio.conduits.ReadReadyHandler$ChannelListenerHandler.readReady(ReadReadyHandler.java:66)
at org.xnio.nio.NioSocketConduit.handleReady(NioSocketConduit.java:89)
at org.xnio.nio.WorkerThread.run(WorkerThread.java:591)
If I was to supply a token, the bearer mechanism works, seems like for some reason the other mechanism is not authenticating
Here are the parts from the Wildfly 24 standalone.xml I've modified:
EJB subsystem:
...
<default-security-domain value="other"/>
<application-security-domains>
<application-security-domain name="other" security-domain="ApplicationDomain"/>
</application-security-domains>
...
Elytron subsystem:
- I would like to use the PreAuthRealm for the simple auth.
<security-domains>
<security-domain name="ApplicationDomain" default-realm="JWTRealm" permission-mapper="default-permission-mapper">
<realm name="JWTRealm" role-decoder="jwt-to-roles"/>
<realm name="PreAuthRealm" role-decoder="groups-to-roles"/>
</security-domain>
...
<\security-domains>
- I want to use the application-users.properties file to store the username and the password, these credentials were added to the store with the add-user.sh script
<security-realms>
<identity-realm name="local" identity="$local"/>
<properties-realm name="PreAuthRealm">
<users-properties path="application-users.properties" relative-to="jboss.server.config.dir" digest-realm-name="PreAuthRealm"/>
<groups-properties path="application-roles.properties" relative-to="jboss.server.config.dir"/>
</properties-realm>
<token-realm name="JWTRealm" principal-claim="*my claim*">
<jwt issuer="*my issuer*" audience="account">
<key kid="*my key id*" public-key="*my public key*"/>
</jwt>
</token-realm>
</security-realms>
- The sasl authentication factory setup:
<sasl-authentication-factory name="application-sasl-authentication" sasl-server-factory="configured" security-domain="ApplicationDomain">
<mechanism-configuration>
<mechanism mechanism-name="OAUTHBEARER">
<mechanism-realm realm-name="JWTRealm"/>
</mechanism>
<mechanism mechanism-name="DIGEST-MD5">
<mechanism-realm realm-name="PreAuthRealm"/>
</mechanism>
</mechanism-configuration>
</sasl-authentication-factory>
Remoting subsystem:
<subsystem xmlns="urn:jboss:domain:remoting:4.0">
<http-connector name="http-remoting-connector" connector-ref="default" sasl-authentication-factory="application-sasl-authentication"/>
</subsystem>
The strange part is, if I remove the sasl-authentication-factory="application-sasl-authentication"
from the Remoting subsystem, and put back the original security-realm="ApplicationRealm"
the above code runs and it actually authenticates me from the .properties file, but then of course the bearer token part won't work, which is the whole point.
What am I missing with my setup here? Is it even possible what i want to achieve?