4 Replies Latest reply on Mar 14, 2019 2:04 PM by rdasilvacuriel

    Elytron + JDBCRealm + SHA-256 cannot connect to EJB

    rdasilvacuriel

      Hi, I'm trying to upgrade a personal system from JBossEAP6.4 to Wildfly 15. In EAP6.4 I could connect remotely to my secured EJB's after authenticating via client code. With Wildfly 15 I have the server set up correctly because I can connect to the secured EJB if I store the plain password in the database, and if I use DIGEST-MD5 in my client to connect, also using the clear password. But when I change to SHA-256 in the 'standalone.xml' as follows:

       

                          <mechanism-configuration>

      <!-- for plain password

                              <mechanism mechanism-name="DIGEST-MD5">

      -->

                              <mechanism mechanism-name="DIGEST-SHA-256">

                                  <mechanism-realm realm-name="jdbcRealm"/>

                              </mechanism>

                          </mechanism-configuration>

       

      I cannot connect using this configuration:

       

      final AuthenticationConfiguration config = AuthenticationConfiguration

        .empty()

        .useRealm("jdbcRealm")

      // .setSaslMechanismSelector(SaslMechanismSelector.NONE.addMechanism("DIGEST-MD5"))
         .setSaslMechanismSelector(SaslMechanismSelector.NONE.addMechanism("DIGEST-SHA-256"))

        .useName("raoul")

         .usePassword("password")

         .useProviders(() -> new Provider[]{wildFlyElytronProvider})

       

      In my database I used to store a Base-64 encoded SHA-256 string for "password", namely "5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8". I also tried "XohImNooBHFR0OVvjcYpJ3NgPQ1qq73WKhHvch0VQtg=" and "XohImNooBHFR0OVvjcYpJ3NgPQ1qq73WKhHvch0VQtg", but each time I get refused if I try to connect with DIGEST-SHA-256.

       

      16:03:21,305 TRACE [org.wildfly.security] (default I/O-3) Handling MechanismInformationCallback type='SASL' name='DIGEST-SHA-256' host-name='localhost' protocol='remote'

      16:03:21,307 TRACE [org.wildfly.security] (default I/O-3) Handling MechanismInformationCallback type='SASL' name='DIGEST-SHA-256' host-name='localhost' protocol='remote'

      16:03:21,308 TRACE [org.wildfly.security] (default I/O-3) Handling AvailableRealmsCallback: realms = [jdbcRealm]

      16:03:21,358 TRACE [org.wildfly.security] (default I/O-3) Creating SaslServer [org.wildfly.security.sasl.digest.DigestSaslServer@7fef79f2] for mechanism [DIGEST-SHA-256] and protocol [remote]

      16:03:21,361 TRACE [org.wildfly.security] (default I/O-3) Created SaslServer [org.wildfly.security.sasl.util.SecurityIdentitySaslServerFactory$1@6d8b87c0->org.wildfly.security.sasl.util.AuthenticationTimeoutSaslServerFactory$DelegatingTimeoutSaslServer@4975f757->org.wildfly.security.sasl.util.AuthenticationCompleteCallbackSaslServerFactory$1@38d22e8f->org.wildfly.security.sasl.digest.DigestSaslServer@7fef79f2] for mechanism [DIGEST-SHA-256]

      16:03:21,395 TRACE [org.wildfly.security] (default task-1) Handling RealmCallback: selected = [jdbcRealm]

      16:03:21,396 TRACE [org.wildfly.security] (default task-1) Handling NameCallback: authenticationName = raoul

      16:03:21,396 TRACE [org.wildfly.security] (default task-1) Principal assigning: [raoul], pre-realm rewritten: [raoul], realm name: [jdbcRealm], post-realm rewritten: [raoul], realm rewritten: [raoul]

      16:03:21,400 TRACE [org.wildfly.security] (default task-1) Executing principalQuery SELECT password FROM wrn.user WHERE name = ? with value raoul

      16:03:21,430 TRACE [org.wildfly.security] (default task-1) Key Mapper: Password credential created using algorithm column value [simple-digest-sha-256]

      16:03:21,431 TRACE [org.wildfly.security] (default task-1) Executing principalQuery SELECT r.name FROM wrn.role r JOIN wrn.User_Roles ur ON ur.role_id=r.id JOIN wrn.user u ON u.id = ur.user_id WHERE u.name=? with value raoul

      16:03:21,433 TRACE [org.wildfly.security] (default task-1) Handling CredentialCallback: failed to obtain credential

      16:03:21,433 TRACE [org.wildfly.security] (default task-1) Handling RealmCallback: selected = [jdbcRealm]

      16:03:21,433 TRACE [org.wildfly.security] (default task-1) Handling NameCallback: authenticationName = raoul

      16:03:21,433 TRACE [org.wildfly.security] (default task-1) Handling CredentialCallback: failed to obtain credential

      16:03:21,433 TRACE [org.wildfly.security] (default task-1) Handling RealmCallback: selected = [jdbcRealm]

      16:03:21,433 TRACE [org.wildfly.security] (default task-1) Handling NameCallback: authenticationName = raoul

      16:03:21,434 TRACE [org.wildfly.security] (default task-1) Handling PasswordCallback: failed to obtain PasswordCredential

      16:03:21,434 TRACE [org.wildfly.security] (default task-1) Handling AuthenticationCompleteCallback: fail

       

      The jdbcRealm is configured as follows:

       

                      <jdbc-realm name="jdbcRealm">

                          <principal-query sql="SELECT password FROM wrn.user WHERE name = ?" data-source="MySQLDS">

      <!-- for plain password

                              <clear-password-mapper password-index="1"/>

      -->

                              <simple-digest-mapper algorithm="simple-digest-sha-256" password-index="1"/>

                          </principal-query>

                          <principal-query sql="SELECT r.name FROM wrn.role r JOIN wrn.User_Roles ur ON ur.role_id=r.id JOIN wrn.user u ON u.id = ur.user_id WHERE u.name=?" data-source="MySQLDS">

                              <attribute-mapping>

                                  <attribute to="roles" index="1"/>

                              </attribute-mapping>

                          </principal-query>

                      </jdbc-realm>

       

      In "plain password" mode I can connect to the secured EJB successfully, see logging below, so I assume that my EJB and "standalone.xml" configuration is fine. So it must have to do with the SHA-256 configuration, encoding, how I store the password in the database, or how I send the password (encoded, hashed, or whatever) in the client code.

       

      16:08:23,311 TRACE [org.wildfly.security] (default I/O-2) Handling MechanismInformationCallback type='SASL' name='DIGEST-MD5' host-name='localhost' protocol='remote'

      16:08:23,312 TRACE [org.wildfly.security] (default I/O-2) Handling MechanismInformationCallback type='SASL' name='DIGEST-MD5' host-name='localhost' protocol='remote'

      16:08:23,313 TRACE [org.wildfly.security] (default I/O-2) Handling AvailableRealmsCallback: realms = [jdbcRealm]

      16:08:23,369 TRACE [org.wildfly.security] (default I/O-2) Creating SaslServer [org.wildfly.security.sasl.digest.DigestSaslServer@2e544fac] for mechanism [DIGEST-MD5] and protocol [remote]

      16:08:23,372 TRACE [org.wildfly.security] (default I/O-2) Created SaslServer [org.wildfly.security.sasl.util.SecurityIdentitySaslServerFactory$1@762cde8b->org.wildfly.security.sasl.util.AuthenticationTimeoutSaslServerFactory$DelegatingTimeoutSaslServer@1d6683e4->org.wildfly.security.sasl.util.AuthenticationCompleteCallbackSaslServerFactory$1@59c6de3->org.wildfly.security.sasl.digest.DigestSaslServer@2e544fac] for mechanism [DIGEST-MD5]

      16:08:23,415 TRACE [org.wildfly.security] (default task-1) Handling RealmCallback: selected = [jdbcRealm]

      16:08:23,416 TRACE [org.wildfly.security] (default task-1) Handling NameCallback: authenticationName = raoul

      16:08:23,417 TRACE [org.wildfly.security] (default task-1) Principal assigning: [raoul], pre-realm rewritten: [raoul], realm name: [jdbcRealm], post-realm rewritten: [raoul], realm rewritten: [raoul]

      16:08:23,421 TRACE [org.wildfly.security] (default task-1) Executing principalQuery SELECT password FROM wrn.user WHERE name = ? with value raoul

      16:08:23,478 TRACE [org.wildfly.security] (default task-1) Key Mapper: Password credential created using algorithm column value [clear]

      16:08:23,480 TRACE [org.wildfly.security] (default task-1) Executing principalQuery SELECT r.name FROM wrn.role r JOIN wrn.User_Roles ur ON ur.role_id=r.id JOIN wrn.user u ON u.id = ur.user_id WHERE u.name=? with value raoul

      16:08:23,482 TRACE [org.wildfly.security] (default task-1) Handling CredentialCallback: failed to obtain credential

      16:08:23,482 TRACE [org.wildfly.security] (default task-1) Handling RealmCallback: selected = [jdbcRealm]

      16:08:23,482 TRACE [org.wildfly.security] (default task-1) Handling NameCallback: authenticationName = raoul

      16:08:23,482 TRACE [org.wildfly.security] (default task-1) Handling CredentialCallback: obtained credential: org.wildfly.security.credential.PasswordCredential@dcce299c

      16:08:23,487 TRACE [org.wildfly.security] (default task-1) Role mapping: principal [raoul] -> decoded roles [Administrator] -> realm mapped roles [Administrator] -> domain mapped roles [Administrator]

      16:08:23,487 TRACE [org.wildfly.security] (default task-1) Authorizing principal raoul.

      16:08:23,488 TRACE [org.wildfly.security] (default task-1) Authorizing against the following attributes: [roles] => [Administrator]

      16:08:23,490 TRACE [org.wildfly.security] (default task-1) Permission mapping: identity [raoul] with roles [Administrator] implies ("org.wildfly.security.auth.permission.LoginPermission" "") = true

      16:08:23,490 TRACE [org.wildfly.security] (default task-1) Authorization succeed

      16:08:23,492 TRACE [org.wildfly.security] (default task-1) RunAs authorization succeed - the same identity

      16:08:23,492 TRACE [org.wildfly.security] (default task-1) Handling AuthorizeCallback: authenticationID = raoul  authorizationID = raoul  authorized = true

      16:08:23,493 TRACE [org.wildfly.security] (default task-1) Handling AuthenticationCompleteCallback: succeed

      16:08:23,493 TRACE [org.wildfly.security] (default task-1) Handling SecurityIdentityCallback: identity = SecurityIdentity{principal=raoul, securityDomain=org.wildfly.security.auth.server.SecurityDomain@15c430d0, authorizationIdentity=EMPTY, realmInfo=RealmInfo{name='jdbcRealm', securityRealm=org.wildfly.security.auth.realm.jdbc.JdbcSecurityRealm@251985a3}, creationTime=2019-03-09T15:08:23.486Z}

      16:08:23,759 TRACE [org.wildfly.security] (default task-2) Role mapping: principal [raoul] -> decoded roles [Administrator] -> realm mapped roles [Administrator] -> domain mapped roles [Administrator]

       

      If anyone has any idea how to get this working I would be extremely grateful. I have tried everything, storing different things in the DB, sending hash, hex-encoded passwords, but nothing seems to work. I've also tried different CallbackHandlers but I've wasted a huge number of hours without getting anywhere. Many thanks for any ideas!

        • 1. Re: Elytron + JDBCRealm + SHA-256 cannot connect to EJB
          mchoma

          What happend when you go from you working example where clear password is stored in DB + sasl DIGEST-MD5 is used. And just switch SASL DIGEST-MD5 to DIGEST-SHA-256 ?

          • 2. Re: Elytron + JDBCRealm + SHA-256 cannot connect to EJB
            rdasilvacuriel

            Hi Martin, thanks for your time. Well, the configuration I changed between the "clear password" situation and the SHA-256 situation is shown above. The "clear password" configuration is commented out, and the SHA-256 configuration is added and shown above. In short, I added the "simple-digest-mapper" and changed the mechanism to: "<mechanism mechanism-name="DIGEST-SHA-256">". I also encoded the password in the three ways I quote above, but I get the same logging (also above) when I try to run the client with the DIGEST-SHA-256 mechanism. For the password I just use "password" (and the encoded variants as described above) for now to try and get it to work and keep it simple. I read in places that the client should configure the "clear password" with the "usePassword(...)" method (I think I did this for EAP6.4), but I also saw your comment on another post where the client should pass it encoded. But I tried all combinations, and none seem to validate. Should be client pass the "hex" or the "hash" version of "password", or just "password" in clear format. Should be database store the "hex" or "hash" version? Unfortunately all the examples on the internet and in the documentation only show a working example with the clear password, and I have that working. But I'd like to get it to work with a hashed password, and then enable SSL when that works.

            • 3. Re: Elytron + JDBCRealm + SHA-256 cannot connect to EJB
              mchoma

              So you have working this

              sasl mechanism DIGEST-MD5  + clear-password-mapper  + clear password stored in db ?

               

              What happens when you try

              sasl mechanism DIGEST-SHA-256 + clear-password-mapper  + clear password stored in db ?

               

              Currently there is work on improve this exactly aspect of documentation [1]

               

              [1] [WFLY-11820] Enhance Elytron JDBC Realm documentation - JBoss Issue Tracker

              • 4. Re: Elytron + JDBCRealm + SHA-256 cannot connect to EJB
                rdasilvacuriel

                Hi Martin, thanks again.

                 

                When I use the clear-password-mapper + clear password stored in db with sasl mechanism DIGEST-SHA-256 I can access the secured EJB successfully. Logging:

                 

                18:54:15,479 TRACE [org.wildfly.security] (default I/O-12) Handling MechanismInformationCallback type='SASL' name='DIGEST-SHA-256' host-name='localhost' protocol='remote'

                18:54:15,481 TRACE [org.wildfly.security] (default I/O-12) Handling MechanismInformationCallback type='SASL' name='DIGEST-SHA-256' host-name='localhost' protocol='remote'

                18:54:15,482 TRACE [org.wildfly.security] (default I/O-12) Handling AvailableRealmsCallback: realms = [jdbcRealm]

                18:54:15,540 TRACE [org.wildfly.security] (default I/O-12) Creating SaslServer [org.wildfly.security.sasl.digest.DigestSaslServer@6dca109a] for mechanism [DIGEST-SHA-256] and protocol [remote]

                18:54:15,543 TRACE [org.wildfly.security] (default I/O-12) Created SaslServer [org.wildfly.security.sasl.util.SecurityIdentitySaslServerFactory$1@619deb48->org.wildfly.security.sasl.util.AuthenticationTimeoutSaslServerFactory$DelegatingTimeoutSaslServer@4140def1->org.wildfly.security.sasl.util.AuthenticationCompleteCallbackSaslServerFactory$1@3f96ec67->org.wildfly.security.sasl.digest.DigestSaslServer@6dca109a] for mechanism [DIGEST-SHA-256]

                18:54:15,587 TRACE [org.wildfly.security] (default task-1) Handling RealmCallback: selected = [jdbcRealm]

                18:54:15,588 TRACE [org.wildfly.security] (default task-1) Handling NameCallback: authenticationName = raoul

                18:54:15,589 TRACE [org.wildfly.security] (default task-1) Principal assigning: [raoul], pre-realm rewritten: [raoul], realm name: [jdbcRealm], post-realm rewritten: [raoul], realm rewritten: [raoul]

                18:54:15,593 TRACE [org.wildfly.security] (default task-1) Executing principalQuery SELECT password FROM wrn.user WHERE name = ? with value raoul

                18:54:15,624 TRACE [org.wildfly.security] (default task-1) Key Mapper: Password credential created using algorithm column value [clear]

                18:54:15,625 TRACE [org.wildfly.security] (default task-1) Executing principalQuery SELECT r.name FROM wrn.role r JOIN wrn.User_Roles ur ON ur.role_id=r.id JOIN wrn.user u ON u.id = ur.user_id WHERE u.name=? with value raoul

                18:54:15,628 TRACE [org.wildfly.security] (default task-1) Handling CredentialCallback: failed to obtain credential

                18:54:15,628 TRACE [org.wildfly.security] (default task-1) Handling RealmCallback: selected = [jdbcRealm]

                18:54:15,628 TRACE [org.wildfly.security] (default task-1) Handling NameCallback: authenticationName = raoul

                18:54:15,628 TRACE [org.wildfly.security] (default task-1) Handling CredentialCallback: obtained credential: org.wildfly.security.credential.PasswordCredential@dcce299c

                18:54:15,630 TRACE [org.wildfly.security] (default task-1) Role mapping: principal [raoul] -> decoded roles [Administrator] -> realm mapped roles [Administrator] -> domain mapped roles [Administrator]

                18:54:15,631 TRACE [org.wildfly.security] (default task-1) Authorizing principal raoul.

                18:54:15,631 TRACE [org.wildfly.security] (default task-1) Authorizing against the following attributes: [roles] => [Administrator]

                18:54:15,633 TRACE [org.wildfly.security] (default task-1) Permission mapping: identity [raoul] with roles [Administrator] implies ("org.wildfly.security.auth.permission.LoginPermission" "") = true

                18:54:15,633 TRACE [org.wildfly.security] (default task-1) Authorization succeed

                18:54:15,634 TRACE [org.wildfly.security] (default task-1) RunAs authorization succeed - the same identity

                18:54:15,635 TRACE [org.wildfly.security] (default task-1) Handling AuthorizeCallback: authenticationID = raoul  authorizationID = raoul  authorized = true

                18:54:15,635 TRACE [org.wildfly.security] (default task-1) Handling AuthenticationCompleteCallback: succeed

                18:54:15,636 TRACE [org.wildfly.security] (default task-1) Handling SecurityIdentityCallback: identity = SecurityIdentity{principal=raoul, securityDomain=org.wildfly.security.auth.server.SecurityDomain@58333a09, authorizationIdentity=EMPTY, realmInfo=RealmInfo{name='jdbcRealm', securityRealm=org.wildfly.security.auth.realm.jdbc.JdbcSecurityRealm@61000df}, creationTime=2019-03-14T17:54:15.630Z}

                18:54:15,857 TRACE [org.wildfly.security] (default task-2) Role mapping: principal [raoul] -> decoded roles [Administrator] -> realm mapped roles [Administrator] -> domain mapped roles [Administrator]

                 

                I'm not sure what this proves though, but it's great that there's an issue for improving the documentation for this. It is indeed quite complex and not immediately obvious how to configure everything. I think it is also unlikely that anyone will use the clear password solution for anything other than trying to get the configuration right before securing it for production. I don't think there needs to be an example for every possible encryption type, but at least the concepts should be clear, like what should be stored in the database, what to send from the client and in which format, etc.