Wildfly 17 elytron - bcrypt-mapper + DIGEST-MD5 cannot connect to EJB
obreckoff Aug 11, 2019 4:39 PMHi, I'm trying to use a bcrypt-mapper in a jdbc-realm configuration together with DIGEST-MD5 as a mechanism in a sasl-authentication-factory configuration. However, it seems not working, but with a clear-password-mapper instead of bcrypt-mapper and with an appropriate import.sql file it worked fine.
The jdbc-realm configuration and the import.sql file both come from the working example jdbc-security-realm-bcrypt-password at https://github.com/wildfly-security-incubator/elytron-examples/tree/master/jdbc-security-realm-bcrypt-password so the passwords should be in the right form in the database (this is why the error seems like a bug to me).
This is my jdbc-realm configuration in standalone.xml:
<jdbc-realm name="my-jdbc-realm">
<principal-query sql="SELECT PASSWORD, SALT, ITERATION_COUNT FROM USERS WHERE USERNAME = ?" data-source="ExampleDS">
<bcrypt-mapper password-index="1" salt-index="2" iteration-count-index="3"/>
</principal-query>
<principal-query sql="SELECT R.NAME, 'Roles' FROM USERS_ROLES UR INNER JOIN ROLES R ON R.ID = UR.ROLE_ID INNER JOIN USERS U ON U.ID = UR.USER_ID WHERE U.USERNAME = ?" data-source="ExampleDS">
<attribute-mapping>
<attribute to="roles" index="1"/>
</attribute-mapping>
</principal-query>
</jdbc-realm>
This is my sasl-authentication-factory configuration in standalone.xml:
<sasl-authentication-factory name="my-sasl-authentication-factory" sasl-server-factory="configured" security-domain="my-security-domain">
<mechanism-configuration>
<mechanism mechanism-name="DIGEST-MD5">
<mechanism-realm realm-name="my-jdbc-realm"/>
</mechanism>
</mechanism-configuration>
</sasl-authentication-factory>
These and the other changes I made to standalone.xml are:
/subsystem=elytron/jdbc-realm=my-jdbc-realm:add(principal-query=[{sql="SELECT PASSWORD, SALT, ITERATION_COUNT FROM USERS WHERE USERNAME = ?", data-source="ExampleDS", bcrypt-mapper={password-index=1, salt-index=2, iteration-count-index=3}},{sql="SELECT R.NAME, 'Roles' FROM USERS_ROLES UR INNER JOIN ROLES R ON R.ID = UR.ROLE_ID INNER JOIN USERS U ON U.ID = UR.USER_ID WHERE U.USERNAME = ?", data-source="ExampleDS", attribute-mapping=[{index=1, to=roles}]}])
/subsystem=elytron/simple-role-decoder=from-roles-attribute:add(attribute="roles")
/subsystem=elytron/security-domain=my-security-domain:add(default-realm=my-jdbc-realm, permission-mapper=default-permission-mapper, realms=[{realm=my-jdbc-realm, role-decoder=from-roles-attribute}])
/subsystem=ejb3/application-security-domain=my-application-security-domain:add(security-domain=my-security-domain)
/subsystem=elytron/sasl-authentication-factory=my-sasl-authentication-factory:add(sasl-server-factory=configured, security-domain=my-security-domain, mechanism-configurations=[{mechanism-name=DIGEST-MD5, mechanism-realm-configurations=[{realm-name=my-jdbc-realm}]}])
/subsystem=remoting/http-connector=http-remoting-connector:write-attribute(name=sasl-authentication-factory,value=my-sasl-authentication-factory)
My client-code looks like this:
AuthenticationConfiguration authCfg
= AuthenticationConfiguration
.empty()
.setSaslMechanismSelector(SaslMechanismSelector.NONE.addMechanism("DIGEST-MD5"))
.useName("quickstartUser")
.usePassword("quickstartPwd1!"
);
final AuthenticationContext authCtx = AuthenticationContext.empty().with(MatchRule.ALL, authCfg);
AuthenticationContext.getContextManager().setThreadDefault(authCtx);
final Hashtable<String, String> jndiProperties = new Hashtable();
jndiProperties.put(Context.INITIAL_CONTEXT_FACTORY, "org.wildfly.naming.client.WildFlyInitialContextFactory");
jndiProperties.put(Context.PROVIDER_URL, "remote+http://localhost:8080");
final Context context = new InitialContext(jndiProperties);
SecuredEJBRemote reference = (SecuredEJBRemote) context.lookup(
"ejb:/ejb-test-with-bcrypt-mapper-backend/SecuredEJB!"
+ SecuredEJBRemote.class.getName()
);
System.out.println("\n\n\n* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n\n");
System.out.println("Successfully called secured bean, caller principal " + reference.getSecurityInfo());
...
The error on the server-side is:
04:35:00,539 TRACE [org.wildfly.security] (default I/O-5) Handling MechanismInformationCallback type='SASL' name='DIGEST-MD5' host-name='localhost' protocol='remote'
04:35:00,539 TRACE [org.wildfly.security] (default I/O-5) Handling MechanismInformationCallback type='SASL' name='DIGEST-MD5' host-name='localhost' protocol='remote'
04:35:00,539 TRACE [org.wildfly.security] (default I/O-5) Handling AvailableRealmsCallback: realms = [my-jdbc-realm]
04:35:00,539 TRACE [org.wildfly.security] (default I/O-5) Creating SaslServer [org.wildfly.security.sasl.digest.DigestSaslServer@7773dca9] for mechanism [DIGEST-MD5] and protocol [remote]
04:35:00,539 TRACE [org.wildfly.security] (default I/O-5) Created SaslServer [org.wildfly.security.sasl.util.SecurityIdentitySaslServerFactory$1@32714c23->org.wildfly.security.sasl.util.AuthenticationTimeoutSaslServerFactory$
DelegatingTimeoutSaslServer@126410cb->org.wildfly.security.sasl.util.AuthenticationCompleteCallbackSaslServerFactory$1@389f819->org.wildfly.security.sasl.digest.DigestSaslServer@7773dca9] for mechanism [DIGEST-MD5]
04:35:00,578 TRACE [org.wildfly.security] (default task-1) Handling RealmCallback: selected = [my-jdbc-realm]
04:35:00,578 TRACE [org.wildfly.security] (default task-1) Handling NameCallback: authenticationName = quickstartUser
04:35:00,578 TRACE [org.wildfly.security] (default task-1) Principal assigning: [quickstartUser], pre-realm rewritten: [quickstartUser], realm name: [my-jdbc-realm], post-realm rewritten: [quickstartUser], realm rewritten: [quickstartUser]
04:35:00,578 TRACE [org.wildfly.security] (default task-1) Executing principalQuery SELECT PASSWORD, SALT, ITERATION_COUNT FROM USERS WHERE USERNAME = ? with value quickstartUser
04:35:00,579 TRACE [org.wildfly.security] (default task-1) Key Mapper: Password credential created using algorithm column value [bcrypt]
04:35:00,579 TRACE [org.wildfly.security] (default task-1) Executing principalQuery SELECT R.NAME, 'Roles' FROM USERS_ROLES UR INNER JOIN ROLES R ON R.ID = UR.ROLE_ID INNER JOIN USERS U ON U.ID = UR.USER_ID WHERE U.USERNAME = ? with value quickstartUser
04:35:00,579 TRACE [org.wildfly.security] (default task-1) Handling CredentialCallback: failed to obtain credential
04:35:00,579 TRACE [org.wildfly.security] (default task-1) Handling RealmCallback: selected = [my-jdbc-realm]
04:35:00,579 TRACE [org.wildfly.security] (default task-1) Handling NameCallback: authenticationName = quickstartUser
04:35:00,579 TRACE [org.wildfly.security] (default task-1) Handling CredentialCallback: failed to obtain credential
04:35:00,579 TRACE [org.wildfly.security] (default task-1) Handling RealmCallback: selected = [my-jdbc-realm]
04:35:00,579 TRACE [org.wildfly.security] (default task-1) Handling NameCallback: authenticationName = quickstartUser
04:35:00,579 TRACE [org.wildfly.security] (default task-1) Handling PasswordCallback: failed to obtain PasswordCredential
04:35:00,580 TRACE [org.wildfly.security] (default task-1) Handling AuthenticationCompleteCallback: fail
The error on client-side is:
Exception in thread "main" org.jboss.ejb.client.RequestSendFailedException: EJBCLIENT000409: No more destinations are available
at org.jboss.ejb.client.EJBClientInvocationContext.getResult(EJBClientInvocationContext.java:607)
at org.jboss.ejb.client.EJBClientInvocationContext.getResult(EJBClientInvocationContext.java:543)
...
Caused by: javax.security.sasl.SaslException: Authentication failed: all available authentication mechanisms failed:
DIGEST-MD5: javax.security.sasl.SaslException: DIGEST-MD5: Server rejected authentication
at org.jboss.remoting3.remote.ClientConnectionOpenListener.allMechanismsFailed(ClientConnectionOpenListener.java:109)
at org.jboss.remoting3.remote.ClientConnectionOpenListener$Capabilities.handleEvent(ClientConnectionOpenListener.java:262)
...
Can someone give me a hint, what causes this error and how I can fix it?
Below are file-attachments for the not working maven-project with the bcrypt-mapper and the last working maven-project with the clean-password-mapper each with related configure-server.cli and pre-configured standalone.xm file.
Best regards
Olrik.