8 Replies Latest reply on Apr 23, 2018 2:23 PM by Craig Giordano

    user name does not propagate with programmatic authentication

    Craig Giordano Newbie

      I am migrating my ejb application to Wildfly 11 from Wildfly 9, attempting to use elytron.  I find that when I use the wildfly-config.xml file for my ejb client all works as expected.  When I try to do the same programmatically (without wildfly-config.xml) I find that the user name does not appear in the security context.  I need the user name in the security context because we use spring security for method parameter authorization.  The wildfly-config.xml that is used successfully is:

       

      <configuration>

          <authentication-client xmlns="urn:elytron:1.0">

              <authentication-rules>

                  <rule use-configuration="default-config"/>

              </authentication-rules>

              <authentication-configurations>

                  <configuration name="default-config">

                      <set-user-name name="aeinstein"/>

                      <credentials>

                          <clear-password password="e=mc2"/>

                      </credentials>

                      <sasl-mechanism-selector selector="DIGEST-MD5"/>

                      <providers>

                          <use-service-loader />

                      </providers>

                  </configuration>

              </authentication-configurations>

          </authentication-client>

      </configuration>

       

      The code snippet I use to invoke a remote ejb that does not propagate the user name to the security context is as follows:

       

      private <T> T locate(Class<T> clz) {

              String userName = "aeinstein";

              String password = "e=mc2";

       

              AuthenticationConfiguration common = AuthenticationConfiguration

                      .empty()

                      .setSaslMechanismSelector(SaslMechanismSelector.NONE.addMechanism("DIGEST-MD5"))

                      .useName(userName)

                      .usePassword(password);

       

              final AuthenticationContext authCtx = AuthenticationContext.empty().with(MatchRule.ALL.matchHost("localhost"), common);

       

              Callable<T> vCallable = () -> {

                  final Properties jndiProperties = new Properties();

                  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);

                  String beanName = clz.getSimpleName() + "Bean";

                  String url = "ejb:paragon2/paragon2-server-side/" + beanName + "!" + clz.getName();

                  return (T)context.lookup(url);

              };

              try {

                  return authCtx.runCallable(vCallable);

              } catch (Exception e) {

                  e.printStackTrace();

                  return null;

              }

          }

       

      The server.log entries:

       

      2018-02-28 12:42:18,664 TRACE [org.wildfly.security] (default I/O-8) Handling MechanismInformationCallback type='SASL' name='JBOSS-LOCAL-USER' host-name='127.0.0.1' protocol='remote'

      2018-02-28 12:42:18,664 TRACE [org.wildfly.security] (default I/O-8) Handling MechanismInformationCallback type='SASL' name='JBOSS-LOCAL-USER' host-name='127.0.0.1' protocol='remote'

      2018-02-28 12:42:18,665 TRACE [org.wildfly.security] (default I/O-8) Creating SaslServer [org.wildfly.security.sasl.localuser.LocalUserServer@34c3a4d3] for mechanism [JBOSS-LOCAL-USER] and protocol [remote]

      2018-02-28 12:42:18,665 TRACE [org.wildfly.security] (default I/O-8) Created SaslServer [org.wildfly.security.sasl.util.SecurityIdentitySaslServerFactory$1@258d3e6->org.wildfly.security.sasl.util.AuthenticationTimeoutSaslServerFactory$DelegatingTimeoutSaslServer@65a3bd5b->org.wildfly.security.sasl.util.AuthenticationCompleteCallbackSaslServerFactory$1@7493f38f->org.wildfly.security.sasl.localuser.LocalUserServer@34c3a4d3] for mechanism [JBOSS-LOCAL-USER]

      2018-02-28 12:42:18,677 TRACE [org.wildfly.security] (default task-100) Handling NameCallback: authenticationName = $local

      2018-02-28 12:42:18,677 TRACE [org.wildfly.security] (default task-100) Principal assigning: [$local], pre-realm rewritten: [$local], realm name: [local], post-realm rewritten: [$local], realm rewritten: [$local]

      2018-02-28 12:42:18,677 TRACE [org.wildfly.security] (default task-100) Role mapping: principal [$local] -> decoded roles [] -> realm mapped roles [SuperUser] -> domain mapped roles [SuperUser]

      2018-02-28 12:42:18,677 TRACE [org.wildfly.security] (default task-100) Authorizing principal $local.

      2018-02-28 12:42:18,677 TRACE [org.wildfly.security] (default task-100) Authorizing against the following attributes: [] => []

      2018-02-28 12:42:18,677 TRACE [org.wildfly.security] (default task-100) Permission mapping: identity [$local] with roles [SuperUser] implies ("org.wildfly.security.auth.permission.LoginPermission" "") = true

      2018-02-28 12:42:18,677 TRACE [org.wildfly.security] (default task-100) Authorization succeed

      2018-02-28 12:42:18,677 TRACE [org.wildfly.security] (default task-100) RunAs authorization succeed - the same identity

      2018-02-28 12:42:18,677 TRACE [org.wildfly.security] (default task-100) Handling AuthorizeCallback: authenticationID = $local  authorizationID = $local  authorized = true

      2018-02-28 12:42:18,677 TRACE [org.wildfly.security] (default task-100) Handling AuthenticationCompleteCallback: succeed

      2018-02-28 12:42:18,677 TRACE [org.wildfly.security] (default task-100) Handling SecurityIdentityCallback: identity = SecurityIdentity{principal=$local, securityDomain=org.wildfly.security.auth.server.SecurityDomain@1d6152a7, authorizationIdentity=EMPTY, realmInfo=RealmInfo{name='local', securityRealm=org.wildfly.security.auth.realm.SimpleMapBackedSecurityRealm@3e3dff44}, creationTime=2018-02-28T17:42:18.677Z}

       

      Here the user name appears as $local.  If I use wildfly-config.xml, the user name is aeinstein.  Where have I gone wrong?

       

      Below are the server.log entries for a successful remote ejb call using wildfly-config.xml (The code path appears very different.)

       

      2018-02-28 13:01:05,264 TRACE [org.wildfly.security] (default I/O-12) Handling MechanismInformationCallback type='SASL' name='DIGEST-MD5' host-name='127.0.0.1' protocol='remote'

      2018-02-28 13:01:05,265 TRACE [org.wildfly.security] (default I/O-12) Handling MechanismInformationCallback type='SASL' name='DIGEST-MD5' host-name='127.0.0.1' protocol='remote'

      2018-02-28 13:01:05,265 TRACE [org.wildfly.security] (default I/O-12) Handling AvailableRealmsCallback: realms = [ApplicationRealm]

      2018-02-28 13:01:05,265 TRACE [org.wildfly.security] (default I/O-12) Creating SaslServer [org.wildfly.security.sasl.digest.DigestSaslServer@52c9104d] for mechanism [DIGEST-MD5] and protocol [remote]

      2018-02-28 13:01:05,265 TRACE [org.wildfly.security] (default I/O-12) Created SaslServer [org.wildfly.security.sasl.util.SecurityIdentitySaslServerFactory$1@50456343->org.wildfly.security.sasl.util.AuthenticationTimeoutSaslServerFactory$DelegatingTimeoutSaslServer@63d1e497->org.wildfly.security.sasl.util.AuthenticationCompleteCallbackSaslServerFactory$1@28b7c921->org.wildfly.security.sasl.digest.DigestSaslServer@52c9104d] for mechanism [DIGEST-MD5]

      2018-02-28 13:01:05,286 TRACE [org.wildfly.security] (default task-108) Handling RealmCallback: selected = [ApplicationRealm]

      2018-02-28 13:01:05,286 TRACE [org.wildfly.security] (default task-108) Handling NameCallback: authenticationName = aeinstein

      2018-02-28 13:01:05,286 TRACE [org.wildfly.security] (default task-108) Principal assigning: [aeinstein], pre-realm rewritten: [aeinstein], realm name: [ApplicationRealm], post-realm rewritten: [aeinstein], realm rewritten: [aeinstein]

      2018-02-28 13:01:05,286 TRACE [org.wildfly.security] (default task-108) Executing principalQuery select PASSWORD, 'guest' from PARAGON2_USER where USER_NAME = ? with value aeinstein

      2018-02-28 13:01:05,287 TRACE [org.wildfly.security] (default task-108) Handling CredentialCallback: failed to obtain credential

      2018-02-28 13:01:05,288 TRACE [org.wildfly.security] (default task-108) Handling RealmCallback: selected = [ApplicationRealm]

      2018-02-28 13:01:05,288 TRACE [org.wildfly.security] (default task-108) Handling NameCallback: authenticationName = aeinstein

      2018-02-28 13:01:05,288 TRACE [org.wildfly.security] (default task-108) Executing principalQuery select PASSWORD, 'guest' from PARAGON2_USER where USER_NAME = ? with value aeinstein

      2018-02-28 13:01:05,288 TRACE [org.wildfly.security] (default task-108) Handling CredentialCallback: obtained credential: org.wildfly.security.credential.PasswordCredential@a30e3c5

      2018-02-28 13:01:05,289 TRACE [org.wildfly.security] (default task-108) Executing principalQuery select PASSWORD, 'guest' from PARAGON2_USER where USER_NAME = ? with value aeinstein

      2018-02-28 13:01:05,289 TRACE [org.wildfly.security] (default task-108) Executing principalQuery select PASSWORD, 'guest' from PARAGON2_USER where USER_NAME = ? with value aeinstein

      2018-02-28 13:01:05,290 TRACE [org.wildfly.security] (default task-108) Role mapping: principal [aeinstein] -> decoded roles [] -> realm mapped roles [] -> domain mapped roles []

      2018-02-28 13:01:05,290 TRACE [org.wildfly.security] (default task-108) Authorizing principal aeinstein.

      2018-02-28 13:01:05,290 TRACE [org.wildfly.security] (default task-108) Authorizing against the following attributes: [Roles] => [guest]

      2018-02-28 13:01:05,290 TRACE [org.wildfly.security] (default task-108) Permission mapping: identity [aeinstein] with roles [] implies ("org.wildfly.security.auth.permission.LoginPermission" "") = true

      2018-02-28 13:01:05,290 TRACE [org.wildfly.security] (default task-108) Authorization succeed

      2018-02-28 13:01:05,290 TRACE [org.wildfly.security] (default task-108) RunAs authorization succeed - the same identity

      2018-02-28 13:01:05,290 TRACE [org.wildfly.security] (default task-108) Handling AuthorizeCallback: authenticationID = aeinstein  authorizationID = aeinstein  authorized = true

      2018-02-28 13:01:05,290 TRACE [org.wildfly.security] (default task-108) Handling AuthenticationCompleteCallback: succeed

      2018-02-28 13:01:05,291 TRACE [org.wildfly.security] (default task-108) Handling SecurityIdentityCallback: identity = SecurityIdentity{principal=aeinstein, securityDomain=org.wildfly.security.auth.server.SecurityDomain@1d6152a7, authorizationIdentity=EMPTY, realmInfo=RealmInfo{name='ApplicationRealm', securityRealm=org.wildfly.security.auth.realm.jdbc.JdbcSecurityRealm@4f0b78f5}, creationTime=2018-02-28T18:01:05.290Z}

       

      For this exercise I relied upon https://docs.jboss.org/author/display/WFLY/Migrate+Legacy+Security+to+Elytron+Security#MigrateLegacySecuritytoElytronSecurity-ApplicationClientMigration

        • 1. Re: user name does not propagate with programmatic authentication
          jaikiran pai Master

          Can you try changing this:

           

          .setSaslMechanismSelector(SaslMechanismSelector.NONE.addMechanism("DIGEST-MD5"))

           

          to this:

           

          .setSaslMechanismSelector(SaslMechanismSelector.NONE.addMechanism("DIGEST-MD5").forbidMechanism("JBOSS-LOCAL-USER"))

           

          It looks like the "local auth" mechanism is being selected when you do this programatically. So forbidding that mechanism might help.

           

          Having said that, I'm not sure if it's the right behaviour that when you are using a NONE mechanism selector to start off with and then just adding one specific mechanism of your choice, it's ending up picking a different mechanism. Try out the above workaround and see if it helps.

          • 2. Re: user name does not propagate with programmatic authentication
            Craig Giordano Newbie

            Thanks for your response.  I added the forbidMechanism as you suggested but it had zero impact.  Logging below:

             

            2018-03-01 08:46:30,027 TRACE [org.wildfly.security] (default I/O-10) Handling MechanismInformationCallback type='SASL' name='JBOSS-LOCAL-USER' host-name='127.0.0.1' protocol='remote'

            2018-03-01 08:46:30,028 TRACE [org.wildfly.security] (default I/O-10) Handling MechanismInformationCallback type='SASL' name='JBOSS-LOCAL-USER' host-name='127.0.0.1' protocol='remote'

            2018-03-01 08:46:30,028 TRACE [org.wildfly.security] (default I/O-10) Creating SaslServer [org.wildfly.security.sasl.localuser.LocalUserServer@41ff7649] for mechanism [JBOSS-LOCAL-USER] and protocol [remote]

            2018-03-01 08:46:30,029 TRACE [org.wildfly.security] (default I/O-10) Created SaslServer [org.wildfly.security.sasl.util.SecurityIdentitySaslServerFactory$1@31825e8f->org.wildfly.security.sasl.util.AuthenticationTimeoutSaslServerFactory$DelegatingTimeoutSaslServer@528a0628->org.wildfly.security.sasl.util.AuthenticationCompleteCallbackSaslServerFactory$1@2746b9ba->org.wildfly.security.sasl.localuser.LocalUserServer@41ff7649] for mechanism [JBOSS-LOCAL-USER]

            2018-03-01 08:46:30,042 TRACE [org.wildfly.security] (default task-2) Handling NameCallback: authenticationName = $local

            2018-03-01 08:46:30,043 TRACE [org.wildfly.security] (default task-2) Principal assigning: [$local], pre-realm rewritten: [$local], realm name: [local], post-realm rewritten: [$local], realm rewritten: [$local]

            2018-03-01 08:46:30,044 TRACE [org.wildfly.security] (default task-2) Role mapping: principal [$local] -> decoded roles [] -> realm mapped roles [SuperUser] -> domain mapped roles [SuperUser]

            2018-03-01 08:46:30,044 TRACE [org.wildfly.security] (default task-2) Authorizing principal $local.

            2018-03-01 08:46:30,044 TRACE [org.wildfly.security] (default task-2) Authorizing against the following attributes: [] => []

            2018-03-01 08:46:30,045 TRACE [org.wildfly.security] (default task-2) Permission mapping: identity [$local] with roles [SuperUser] implies ("org.wildfly.security.auth.permission.LoginPermission" "") = true

            2018-03-01 08:46:30,045 TRACE [org.wildfly.security] (default task-2) Authorization succeed

            2018-03-01 08:46:30,045 TRACE [org.wildfly.security] (default task-2) RunAs authorization succeed - the same identity

            2018-03-01 08:46:30,045 TRACE [org.wildfly.security] (default task-2) Handling AuthorizeCallback: authenticationID = $local  authorizationID = $local  authorized = true

            2018-03-01 08:46:30,045 TRACE [org.wildfly.security] (default task-2) Handling AuthenticationCompleteCallback: succeed

            2018-03-01 08:46:30,045 TRACE [org.wildfly.security] (default task-2) Handling SecurityIdentityCallback: identity = SecurityIdentity{principal=$local, securityDomain=org.wildfly.security.auth.server.SecurityDomain@4774f55d, authorizationIdentity=EMPTY, realmInfo=RealmInfo{name='local', securityRealm=org.wildfly.security.auth.realm.SimpleMapBackedSecurityRealm@69366b48}, creationTime=2018-03-01T13:46:30.043Z}

             

            Are there any other ways to get the behavior of wildfly-config.xml?

            • 3. Re: user name does not propagate with programmatic authentication
              jaikiran pai Master

              2018-03-01 08:46:30,027 TRACE [org.wildfly.security] (default I/O-10) Handling MechanismInformationCallback type='SASL' name='JBOSS-LOCAL-USER' host-name='127.0.0.1' protocol='remote'

               

              Can you try changing this:

               

              AuthenticationContext.empty().with(MatchRule.ALL.matchHost("localhost"), common);

               

              to

               

              AuthenticationContext.empty().with(MatchRule.ALL.matchHost("127.0.0.1"), common);

               

              P.S: I haven't looked into Elytron code in detail, so my suggestions here are just guesses based on these logs and brief check of the code.

              • 4. Re: user name does not propagate with programmatic authentication
                Craig Giordano Newbie

                I tried  "127.0.0.1".  No impact .

                 

                2018-03-01 10:25:41,737 TRACE [org.wildfly.security] (default I/O-10) Handling MechanismInformationCallback type='SASL' name='JBOSS-LOCAL-USER' host-name='127.0.0.1' protocol='remote'

                2018-03-01 10:25:41,738 TRACE [org.wildfly.security] (default I/O-10) Handling MechanismInformationCallback type='SASL' name='JBOSS-LOCAL-USER' host-name='127.0.0.1' protocol='remote'

                2018-03-01 10:25:41,738 TRACE [org.wildfly.security] (default I/O-10) Creating SaslServer [org.wildfly.security.sasl.localuser.LocalUserServer@4829ac4c] for mechanism [JBOSS-LOCAL-USER] and protocol [remote]

                2018-03-01 10:25:41,739 TRACE [org.wildfly.security] (default I/O-10) Created SaslServer [org.wildfly.security.sasl.util.SecurityIdentitySaslServerFactory$1@9d23740->org.wildfly.security.sasl.util.AuthenticationTimeoutSaslServerFactory$DelegatingTimeoutSaslServer@38597f87->org.wildfly.security.sasl.util.AuthenticationCompleteCallbackSaslServerFactory$1@57f25963->org.wildfly.security.sasl.localuser.LocalUserServer@4829ac4c] for mechanism [JBOSS-LOCAL-USER]

                2018-03-01 10:25:41,754 TRACE [org.wildfly.security] (default task-10) Handling NameCallback: authenticationName = $local

                2018-03-01 10:25:41,755 TRACE [org.wildfly.security] (default task-10) Principal assigning: [$local], pre-realm rewritten: [$local], realm name: [local], post-realm rewritten: [$local], realm rewritten: [$local]

                2018-03-01 10:25:41,755 TRACE [org.wildfly.security] (default task-10) Role mapping: principal [$local] -> decoded roles [] -> realm mapped roles [SuperUser] -> domain mapped roles [SuperUser]

                2018-03-01 10:25:41,755 TRACE [org.wildfly.security] (default task-10) Authorizing principal $local.

                2018-03-01 10:25:41,755 TRACE [org.wildfly.security] (default task-10) Authorizing against the following attributes: [] => []

                2018-03-01 10:25:41,755 TRACE [org.wildfly.security] (default task-10) Permission mapping: identity [$local] with roles [SuperUser] implies ("org.wildfly.security.auth.permission.LoginPermission" "") = true

                2018-03-01 10:25:41,755 TRACE [org.wildfly.security] (default task-10) Authorization succeed

                2018-03-01 10:25:41,755 TRACE [org.wildfly.security] (default task-10) RunAs authorization succeed - the same identity

                2018-03-01 10:25:41,756 TRACE [org.wildfly.security] (default task-10) Handling AuthorizeCallback: authenticationID = $local  authorizationID = $local  authorized = true

                2018-03-01 10:25:41,756 TRACE [org.wildfly.security] (default task-10) Handling AuthenticationCompleteCallback: succeed

                2018-03-01 10:25:41,756 TRACE [org.wildfly.security] (default task-10) Handling SecurityIdentityCallback: identity = SecurityIdentity{principal=$local, securityDomain=org.wildfly.security.auth.server.SecurityDomain@4774f55d, authorizationIdentity=EMPTY, realmInfo=RealmInfo{name='local', securityRealm=org.wildfly.security.auth.realm.SimpleMapBackedSecurityRealm@69366b48}, creationTime=2018-03-01T15:25:41.755Z}

                • 5. Re: user name does not propagate with programmatic authentication
                  Craig Giordano Newbie

                  The magic method call is . . ..  . .useDefaultProviders()NOT.  I was mistaken and had wildfly-config.xml in my path.  When I removed it, the code below did not work.  Still doing local auth.  Arghhhhhhh!

                   

                  This now works for me:

                   

                      private  T locate(Class clz) {
                          String userName = "aeinstein";
                          String password = "e=mc2";
                  
                          AuthenticationConfiguration common = AuthenticationConfiguration
                                  .empty()
                                  .setSaslMechanismSelector(SaslMechanismSelector.NONE.addMechanism("DIGEST-MD5"))
                                  .useName(userName)
                                  .usePassword(password)
                                  .useDefaultProviders();
                  
                  
                          final AuthenticationContext authCtx = AuthenticationContext.empty().with(MatchRule.ALL.matchHost("localhost"), common);
                  
                  
                          Callable vCallable = () -> {
                              final Properties jndiProperties = new Properties();
                              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);
                              String beanName = clz.getSimpleName() + "Bean";
                              String url = "ejb:paragon2/paragon2-server-side/" + beanName + "!" + clz.getName();
                              return (T)context.lookup(url);
                          };
                          try {
                              return authCtx.runCallable(vCallable);
                          } catch (Exception e) {
                              e.printStackTrace();
                              return null;
                          }
                      }
                  • 6. Re: user name does not propagate with programmatic authentication
                    Martin Choma Master

                    Interesting here would be client log with org.wildfly.security to TRACE. Apparently DIGEST-MD5 sasl mechanism was taken from other the WildflyElytronProvider. You have 3 options to specify which provider to use:

                     

                    useDefaultProviders()                                   // Load providers using Service Loader + System JDK providers 
                    useProvidersFromClassLoader(YourClass.class.getClassLoader())          // Load providers using Service Loader 
                    useProviders(() -> new Provider[] { new WildFlyElytronProvider() })     // Explicitely specify providers to use
                    • 7. Re: user name does not propagate with programmatic authentication
                      jaikiran pai Master

                      Looking at the logs and what you explain, I'm starting to have a feeling that it isn't even using the authtentication context on which you are invoking and instead is using some other context which starts using the local auth mechanism. I'll have to look at the Elytron code and EJB client library in more detail to understand what/how the context manager picks up.

                      • 8. Re: user name does not propagate with programmatic authentication
                        Craig Giordano Newbie

                        I am still stuck on this one.  From the debug log statements the principal is always 'anonymous' when NOT using wildfly-config.xml.

                         

                        2018-04-23 09:53:23,682 [main] TRACE org.wildfly.security - getAuthenticationConfiguration uri=remote+http://localhost:8080, protocolDefaultPort=-1, abstractType=ejb, abstractTypeAuthority=jboss, MatchRule=[null], AuthenticationConfiguration=[AuthenticationConfiguration:principal=anonymous,set-host=localhost,set-protocol=remote+http,set-port=8080,providers-supplier=org.wildfly.security.util.ProviderUtil$1@5082d622,mechanism-properties={wildfly.sasl.local-user.quiet-auth=true}]

                         

                        And aeinstein when using wildfly-config.xml.

                         

                        2018-04-23 09:43:41,360 [main] TRACE org.wildfly.security - getAuthenticationConfiguration uri=remote+http://localhost:8080, protocolDefaultPort=-1, abstractType=ejb, abstractTypeAuthority=jboss, MatchRule=[], AuthenticationConfiguration=[AuthenticationConfiguration:principal=aeinstein,set-host=localhost,set-protocol=remote+http,set-port=8080,credentials-present,providers-supplier=org.wildfly.security.auth.client.ElytronXmlParser$DeferredSupplier@6af9fcb2,sasl-mechanism-selector=DIGEST-MD5,mechanism-properties={wildfly.sasl.local-user.quiet-auth=true}]

                         

                        Here is how I am attempting (one of many attempts) to make the remote call.

                        AuthenticationConfiguration common = AuthenticationConfiguration
                          .empty()
                          .setSaslMechanismSelector(SaslMechanismSelector.NONE.addMechanism("DIGEST-MD5").forbidMechanism("JBOSS-LOCAL-USER"))
                          .useName(userName)
                          .usePassword(password)
                          .useRealm("ApplicationRealm")
                          .useProviders( () -> new Provider[] { new WildFlyElytronProvider() })
                          .useDefaultProviders().usePort(8080).useHost("localhost").useProtocol("remote+http");
                        final AuthenticationContext authCtx = AuthenticationContext.empty().with(MatchRule.ALL, common);