Authentication / Authorization issues migrating from Wildfly 16 to 26

714 views
Skip to first unread message

Jens Kutschke

unread,
Nov 27, 2023, 2:35:16 PM11/27/23
to WildFly
Hi all,

I am migrating an open source application from Wildfly 16 to 26. In the past, I used a JDBC login module with base64'ed SHA-256 hashes of passwords. The most relevant snippet looked like this:
                        <login-module code="Database" flag="required">
                            <module-option name="dsJndiName" value="java:/jlawyerdb"/>
                            <module-option name="principalsQuery" value="select password from security_users where principalId=?"/>
                            <module-option name="rolesQuery" value="select role, 'Roles' from security_roles where principalId=?"/>
                            <module-option name="unauthenticatedIdentity" value="anonymous"/>
                            <module-option name="hashAlgorithm" value="SHA-256"/>
                            <module-option name="hashEncoding" value="base64"/>
                            <module-option name="hashUserPassword" value="true"/>
                            <module-option name="hashStorePassword" value="false"/>
                        </login-module>

I am trying really hard for the last days to get an equivalent configuration for Wildfly 26, to no avail. Here's what I have:
(note that I have change the existing ApplicationRealm and ApplicationDomain instead of adding new ones - i don't like it, but it got me further than with new ones)

A JDBC realm:

                <jdbc-realm name="ApplicationRealm">
                    <principal-query sql="select password from security_users where principalId=?" data-source="jlawyerdb">
                        <!-- clear-password-mapper password-index="1"/ -->
                        <simple-digest-mapper algorithm="simple-digest-sha-256" password-index="1"/>
                    </principal-query>
                    <principal-query sql="select role, 'Roles' from security_roles where principalId=?" data-source="jlawyerdb">
                        <attribute-mapping>
                            <attribute to="Roles" index="1"/>
                        </attribute-mapping>
                    </principal-query>
                </jdbc-realm>


SASL Authentication Factory:

                <sasl-authentication-factory name="application-sasl-authentication" sasl-server-factory="configured" security-domain="ApplicationDomain">
                    <mechanism-configuration>
                        <!-- mechanism mechanism-name="JBOSS-LOCAL-USER" realm-mapper="local"/ -->
                        <mechanism mechanism-name="DIGEST-SHA-256">
                            <mechanism-realm realm-name="ApplicationRealm"/>
                        </mechanism>
                    </mechanism-configuration>
                </sasl-authentication-factory>

As I have a remote EJB client, I updated the remoting subsystem to point to the factory:

        <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 remote EJB client looks like this:

            Properties properties = new Properties();
            properties.put("jboss.naming.client.ejb.context", true);

            // begin: for JMS only
            properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.wildfly.naming.client.WildFlyInitialContextFactory");
            properties.put(Context.PROVIDER_URL, "http-remoting://localhost:8080");
            properties.put(Context.SECURITY_PRINCIPAL, "admin");
            properties.put(Context.SECURITY_CREDENTIALS, pwString);
            properties.put("jboss.naming.client.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT", "false");
            properties.put("jboss.naming.client.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS", "false");
            properties.put("jboss.naming.client.connect.options.org.xnio.Options.SSL_ENABLED", "false");
            properties.put("jboss.naming.client.connect.options.org.xnio.Options.SSL_STARTTLS", "false");

            InitialContext ic = new InitialContext(properties);
            SecurityServiceRemote remote = (SecurityServiceRemote) ic.lookup("ejb:j-lawyer-server/j-lawyer-server-ejb//SecurityService!com.jdimension.jlawyer.services.SecurityServiceRemote");
            remote.login();

Only when passing in the base64'ed and hashed password, I successfully gets a reference to the remote interface, but calling any business logic yields:

2023-11-26 23:41:32,329 ERROR [org.jboss.as.ejb3.invocation] (default task-1) WFLYEJB0034: Jakarta Enterprise Beans Invocation failed on component SecurityService for method public abstract boolean com.jdimension.jlawyer.services.SecurityServiceRemote.login(java.lang.String,java.lang.String): javax.ejb.EJBAccessException: WFLYEJB0364: Invocation on method: public abstract boolean com.jdimension.jlawyer.services.SecurityServiceRemote.login(java.lang.String,java.lang.String) of bean: SecurityService is not allowed


Logging tells me this:

2023-11-26 23:41:32,262 TRACE [org.wildfly.security] (default I/O-5) Handling SocketAddressCallback
2023-11-26 23:41:32,263 TRACE [org.wildfly.security] (default I/O-5) Handling SocketAddressCallback
2023-11-26 23:41:32,263 TRACE [org.wildfly.security] (default I/O-5) Handling MechanismInformationCallback type='SASL' name='JBOSS-LOCAL-USER' host-name='localhost' protocol='remote'
2023-11-26 23:41:32,263 TRACE [org.wildfly.security] (default I/O-5) Handling MechanismInformationCallback type='SASL' name='JBOSS-LOCAL-USER' host-name='localhost' protocol='remote'
2023-11-26 23:41:32,263 TRACE [org.wildfly.security] (default I/O-5) Creating SaslServer [org.wildfly.security.sasl.localuser.LocalUserServer@66e25eec] for mechanism [JBOSS-LOCAL-USER] and protocol [remote]
2023-11-26 23:41:32,263 TRACE [org.wildfly.security] (default I/O-5) Created SaslServer [org.wildfly.security.sasl.util.SecurityIdentitySaslServerFactory$1@62ddd6e8->org.wildfly.security.sasl.util.AuthenticationTimeoutSaslServerFactory$DelegatingTimeoutSaslServer@27df54d7->org.wildfly.security.sasl.util.AuthenticationCompleteCallbackSaslServerFactory$1@62d3e4c9->org.wildfly.security.sasl.localuser.LocalUserServer@66e25eec] for mechanism [JBOSS-LOCAL-USER]
2023-11-26 23:41:32,271 TRACE [org.wildfly.security] (default task-1) Handling NameCallback: authenticationName = admin
2023-11-26 23:41:32,271 TRACE [org.wildfly.security] (default task-1) Principal assigning: [admin], pre-realm rewritten: [admin], realm name: [local], post-realm rewritten: [admin], realm rewritten: [admin]
2023-11-26 23:41:32,271 TRACE [org.wildfly.security] (default task-1) Authorization failed - realm identity does not exists
2023-11-26 23:41:32,271 TRACE [org.wildfly.security] (default task-1) Handling AuthorizeCallback: authenticationID = admin  authorizationID = admin  authorized = false
2023-11-26 23:41:32,272 TRACE [org.wildfly.security.sasl.local] (default task-1) SASL Negotiation Failed
2023-11-26 23:41:32,272 TRACE [org.wildfly.security] (default task-1) Handling AuthenticationCompleteCallback: fail
2023-11-26 23:41:32,276 TRACE [org.wildfly.security] (default I/O-5) Handling SocketAddressCallback
2023-11-26 23:41:32,276 TRACE [org.wildfly.security] (default I/O-5) Handling SocketAddressCallback
2023-11-26 23:41:32,276 TRACE [org.wildfly.security] (default I/O-5) Handling MechanismInformationCallback type='SASL' name='DIGEST-MD5' host-name='localhost' protocol='remote'
2023-11-26 23:41:32,276 TRACE [org.wildfly.security] (default I/O-5) Handling MechanismInformationCallback type='SASL' name='DIGEST-MD5' host-name='localhost' protocol='remote'
2023-11-26 23:41:32,276 TRACE [org.wildfly.security] (default I/O-5) Handling AvailableRealmsCallback: realms = [ApplicationRealm]
2023-11-26 23:41:32,276 TRACE [org.wildfly.security] (default I/O-5) Creating SaslServer [org.wildfly.security.sasl.digest.DigestSaslServer@16b2d341] for mechanism [DIGEST-MD5] and protocol [remote]
2023-11-26 23:41:32,276 TRACE [org.wildfly.security] (default I/O-5) Created SaslServer [org.wildfly.security.sasl.util.SecurityIdentitySaslServerFactory$1@1a543de9->org.wildfly.security.sasl.util.AuthenticationTimeoutSaslServerFactory$DelegatingTimeoutSaslServer@47f0ab98->org.wildfly.security.sasl.util.AuthenticationCompleteCallbackSaslServerFactory$1@3a78ea03->org.wildfly.security.sasl.digest.DigestSaslServer@16b2d341] for mechanism [DIGEST-MD5]
2023-11-26 23:41:32,285 TRACE [org.wildfly.security] (default task-1) Handling RealmCallback: selected = [ApplicationRealm]
2023-11-26 23:41:32,285 TRACE [org.wildfly.security] (default task-1) Handling NameCallback: authenticationName = admin
2023-11-26 23:41:32,285 TRACE [org.wildfly.security] (default task-1) Principal assigning: [admin], pre-realm rewritten: [admin], realm name: [ApplicationRealm], post-realm rewritten: [admin], realm rewritten: [admin]
2023-11-26 23:41:32,285 TRACE [org.wildfly.security] (default task-1) Executing principalQuery select password from security_users where principalId=? with value admin
2023-11-26 23:41:32,285 TRACE [org.wildfly.security] (default task-1) Key Mapper: Password credential created using algorithm column value [clear]
2023-11-26 23:41:32,285 TRACE [org.wildfly.security] (default task-1) Executing principalQuery select role, 'Roles' from security_roles where principalId=? with value admin
2023-11-26 23:41:32,286 TRACE [org.wildfly.security] (default task-1) Handling CredentialCallback: failed to obtain credential
2023-11-26 23:41:32,286 TRACE [org.wildfly.security] (default task-1) Handling RealmCallback: selected = [ApplicationRealm]
2023-11-26 23:41:32,286 TRACE [org.wildfly.security] (default task-1) Handling NameCallback: authenticationName = admin
2023-11-26 23:41:32,286 TRACE [org.wildfly.security] (default task-1) Handling CredentialCallback: obtained credential: org.wildfly.security.credential.PasswordCredential@24893dcb
2023-11-26 23:41:32,286 TRACE [org.wildfly.security] (default task-1) Role mapping: principal [admin] -> decoded roles [] -> domain decoded roles [] -> realm mapped roles [] -> domain mapped roles []
2023-11-26 23:41:32,286 TRACE [org.wildfly.security] (default task-1) Authorizing principal admin.
2023-11-26 23:41:32,286 TRACE [org.wildfly.security] (default task-1) Authorizing against the following attributes: [Roles] => [loginRole, writeAddressRole, createAddressRole, readArchiveFileRole, createOptionGroupRole, commonReportRole, createArchiveFileRole, writeOptionGroupRole, removeAddressRole, confidentialReportRole, readAddressRole, adminRole, writeArchiveFileRole, removeArchiveFileRole, deleteOptionGroupRole, importRole]
2023-11-26 23:41:32,286 TRACE [org.wildfly.security] (default task-1) Authorizing against the following runtime attributes: [Source-Address] => [127.0.0.1]
2023-11-26 23:41:32,286 TRACE [org.wildfly.security] (default task-1) Permission mapping: identity [admin] with roles [] implies ("org.wildfly.security.auth.permission.LoginPermission" "") = true
2023-11-26 23:41:32,286 TRACE [org.wildfly.security] (default task-1) Authorization succeed
2023-11-26 23:41:32,286 TRACE [org.wildfly.security] (default task-1) RunAs authorization succeed - the same identity
2023-11-26 23:41:32,286 TRACE [org.wildfly.security] (default task-1) Handling AuthorizeCallback: authenticationID = admin  authorizationID = admin  authorized = true
2023-11-26 23:41:32,286 TRACE [org.wildfly.security.sasl.digest] (default task-1) SASL Negotiation Completed
2023-11-26 23:41:32,286 TRACE [org.wildfly.security] (default task-1) Handling AuthenticationCompleteCallback: succeed
2023-11-26 23:41:32,286 TRACE [org.wildfly.security] (default task-1) Handling SecurityIdentityCallback: identity = SecurityIdentity{principal=admin, securityDomain=org.wildfly.security.auth.server.SecurityDomain@83cd397, authorizationIdentity=EMPTY, realmInfo=RealmInfo{name='ApplicationRealm', securityRealm=org.wildfly.security.auth.realm.jdbc.JdbcSecurityRealm@6ea53af9}, creationTime=2023-11-26T22:41:32.286637572Z}
2023-11-26 23:41:32,329 TRACE [org.wildfly.security] (default task-1) Role mapping: principal [admin] -> decoded roles [] -> domain decoded roles [] -> realm mapped roles [] -> domain mapped roles []

If I read the logs right, it seems to authenticate, then load the roles, even retrieves the roles, but then says "not allowed".

At this point I am totally stuck and countless hours have not yielded any progress.

Questions:

(1) Is the client really supposed to provide the hashed value? In Wildfly 16, there was no such thing needed. Also, I wonder whether that would work at all with a web module using HTTP BASIC auth - the browser cannot do the client-side hashing. Am I doing something wrong on a conceptional level?

(2) Why do the logs not indicate an issue, but the remote client receives a "not allowed" exception?

(3) Any ideas whether my configuration is wrong?

Thanks all for helping!

Cheers,
Jens

Jens Kutschke

unread,
Nov 29, 2023, 6:43:25 PM11/29/23
to WildFly
Answering my own question here, just in case anyone else runs into this issue:

I had used a password mapper which took care of the hashing, AND I had a DIGEST-SHA-256 as a mechanism at the SASL auth factory. Seems like I asked the container to do two hashings in sequence. Switching the mechanism to PLAIN did the trick.
Reply all
Reply to author
Forward
0 new messages