Just a second...

Developing a control authentication handler

Implement the ControlAuthenticator interface to create a control authentication handler.

This example demonstrates how to implement a control authentication handler in Java™ .

  1. Edit the etc/Server.xml configuration file to include a name that the control authentication handler can register with.
    Include the control-authentication-handler element in the list of authentication handlers. The order of the list defines the order in which the authentication handlers are called. The value of the handler-name attribute is the name that your control authentication handler registers as. For example:
    <security>
      <authentication-handlers>
        <-- Include a local authentication handler that can authenticate the control client -->
        <authentication-handler class="com.example.LocalHandler" />
                   
        <-- Register your control authentication handler -->
        <control-authentication-handler handler-name="before-system-handler" />
    
      </authentication-handlers>
    </security>

    The client that registers your control authentication handler must first authenticate with the Diffusion™ server . Configure a local authentication handler that allows the client to connect.

  2. Start the Diffusion server.
    • On UNIX® -based systems, run the diffusion.sh command in the diffusion_installation_dir/bin directory.
    • On Windows™ systems, run the diffusion.bat command in the diffusion_installation_dir\bin directory.
  3. Create a simple client that registers a control authentication handler with the Diffusion server . You will need to create a Java class that implements ControlAuthenticator.
    package com.pushtechnology.diffusion.examples;
    
    import java.nio.charset.Charset;
    import java.util.Arrays;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Set;
    import java.util.concurrent.TimeUnit;
    
    import com.pushtechnology.diffusion.client.Diffusion;
    import com.pushtechnology.diffusion.client.callbacks.Stream;
    import com.pushtechnology.diffusion.client.features.control.clients.AuthenticationControl;
    import com.pushtechnology.diffusion.client.features.control.clients.AuthenticationControl.ControlAuthenticator;
    import com.pushtechnology.diffusion.client.session.Session;
    import com.pushtechnology.diffusion.client.types.Credentials;
    
    public final class ControlAuthenticationClient {
    
        private ControlAuthenticationClient() {
        }
    
        /**
         * Main entry point for the control client.
         */
        // CHECKSTYLE.OFF: UncommentedMain
        public static void main(final String[] args) throws Exception {
    
            // The control client connects to the server using the principal 'admin'
            // which is authenticated by the system authentication handler (see
            // etc/SystemAuthentication.store).
            // The principal must have REGISTER_HANDLER and AUTHENTICATE permissions.
            final Session session =
                Diffusion.sessions()
                    .principal("admin")
                    .password("password")
                    .open("ws://diffusion.example.com:80");
    
            session.feature(AuthenticationControl.class).setAuthenticationHandler(
                "after-system-handler",
                new ExampleControlAuthenticationHandler()).get(10, TimeUnit.SECONDS);
    
            while (true) {
                Thread.sleep(60000);
            }
        }
       
    
        /**
         * An example of a control authentication handler.
         * <p>
         * This shows a simple example using a table of permitted principals with
         * their passwords. It also demonstrates how the handler can change the
         * properties of the client being authenticated.
         */
        private static class ExampleControlAuthenticationHandler
            extends Stream.Default
            implements ControlAuthenticator {
    
            private static final Map<String, byte[]> PASSWORDS = new HashMap<>();
            static {
                PASSWORDS.put("manager", "password".getBytes(Charset.forName("UTF-8")));
                PASSWORDS.put("guest", "asecret".getBytes(Charset.forName("UTF-8")));
                PASSWORDS.put("brian", "boru".getBytes(Charset.forName("UTF-8")));
                PASSWORDS.put("another", "apassword".getBytes(Charset.forName("UTF-8")));
            }
    
            @Override
            public void authenticate(
                String principal,
                Credentials credentials,
                Map<String, String> sessionProperties,
                Map<String, String> proposedProperties,
                Callback callback) {
    
                final byte[] passwordBytes = PASSWORDS.get(principal);
    
                if (passwordBytes != null &&
                    credentials.getType() == Credentials.Type.PLAIN_PASSWORD &&
                    Arrays.equals(credentials.toBytes(), passwordBytes)) {
                    if ("manager".equals(principal)) {
                        // manager allows all proposed properties
                        callback.allow(proposedProperties);
                    }
                    else if ("brian".equals(principal)) {
                        // brian is allowed all proposed properties and also gets
                        // the 'super' role added
                        final Map<String, String> result =
                            new HashMap<>(proposedProperties);
                        final Set<String> roles =
                            Diffusion.stringToRoles(
                                sessionProperties.get(Session.ROLES));
                        roles.add("super");
                        result.put(Session.ROLES, Diffusion.rolesToString(roles));
                        callback.allow(result);
                    }
                    else {
                        // all others authenticated but ignoring proposed properties
                        callback.allow();
                    }
                }
                else {
                    // Any principal not in the table is denied.
                    callback.deny();
                }
            }
        }
    }
  4. Start your client.
    It connects to the Diffusion server and registers the control authentication handler with the name after-system-handler.
When a client authenticates, the Diffusion server forwards the authentication request to the authentication handler you have registered. Your authentication handler can ALLOW, DENY, or ABSTAIN from the authentication decision. If your authentication handler returns an ALLOW or DENY decision, this decision is used as the response to the authenticating client. If your authentication handler returns an ABSTAIN decision, the Diffusion server forwards the authentication request to the next authentication handler. For more information, see Authentication.