Just a second...

Example: Update the security store

The following examples use the SecurityControl feature in the Diffusion™ API to update the security store.

Note: Only steps 2 and 3 deal with the security store.
// Session security allows you to change the principal that a session is authenticated as. It also  allows users to
// query and update server-side security and authentication stores, which control users, roles and permissions.
// This enables you to manage the capabilities that any logged in user will have access to.

// Connect to Diffusion with control client credentials
    host   : 'diffusion.example.com',
    port   : 443,
    secure : true,
    principal : 'control',
    credentials : 'password'
}).then(function(session) {

    // 1. A session change their principal by re-authenticating
    session.security.changePrincipal('admin', 'password').then(function() {
        console.log('Authenticated as admin');

    // 2. The security configuration provides details about roles and their assigned permissions
    session.security.getSecurityConfiguration().then(function(config) {
        console.log('Roles for anonymous sessions: ', config.anonymous);
        console.log('Roles for named sessions: ', config.named);
        console.log('Available roles: ', config.roles);
    }, function(error) {
        console.log('Unable to fetch security configuration', error);

    // 3. Changes to the security configuration are done with a SecurityScriptBuilder
    var securityScriptBuilder = session.security.securityScriptBuilder();

    // Set the permissions for a particular role - global and topic-scoped
    // Each method on a script builder returns a new builder
    var setPermissionScript = securityScriptBuilder.setGlobalPermissions('SUPERUSER', ['REGISTER_HANDLER'])
                                                   .setTopicPermissions('SUPERUSER', '/foo', ['UPDATE_TOPIC'])

    // Update the server-side store with the generated script
    session.security.updateSecurityStore(setPermissionScript).then(function() {
        console.log('Security configuration updated successfully');
    }, function(error) {
        console.log('Failed to update security configuration: ', error);

    // 4. The system authentication configuration lists all users & roles
    session.security.getSystemAuthenticationConfiguration().then(function(config) {
        console.log('System principals: ', config.principals);
        console.log('Anonymous sessions: ', config.anonymous);
    }, function(error) {
        console.log('Unable to fetch system authentication configuration', error);

    // 5. Changes to the system authentication config are done with a SystemAuthenticationScriptBuilder
    var authenticationScriptBuilder = session.security.authenticationScriptBuilder();

    // Add a new user and set password & roles.
    var addUserScript = authenticationScriptBuilder.addPrincipal('Superman', 'correcthorsebatterystapler')
                                                   .assignRoles('Superman', ['SUPERUSER'])

    // Update the system authentication store
    session.security.updateAuthenticationStore(addUserScript).then(function() {
        console.log('Updated system authentication config');
    }, function(error) {
        console.log('Failed to update system authentication: ', error);
Java and Android
package com.pushtechnology.diffusion.examples;

import static java.util.Collections.emptySet;
import static java.util.stream.Collectors.toCollection;

import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.pushtechnology.diffusion.client.Diffusion;
import com.pushtechnology.diffusion.client.features.control.clients.SecurityControl;
import com.pushtechnology.diffusion.client.features.control.clients.SecurityControl.Role;
import com.pushtechnology.diffusion.client.features.control.clients.SecurityControl.ScriptBuilder;
import com.pushtechnology.diffusion.client.features.control.clients.SecurityControl.SecurityConfiguration;
import com.pushtechnology.diffusion.client.session.Session;
import com.pushtechnology.diffusion.client.types.PathPermission;

 * An example of using a control client to alter the security configuration.
 * <P>
 * This uses the {@link SecurityControl} feature only.
 * @author Push Technology Limited
 * @since 5.3
public class ControlClientChangingSecurity {

    private static final Logger LOG =

    private final SecurityControl securityControl;
    private final ScriptBuilder emptyScript;

     * Constructor.
    public ControlClientChangingSecurity() {

        final Session session = Diffusion.sessions()
            // Authenticate with a user that has the VIEW_SECURITY and
            // MODIFY_SECURITY permissions.
            // Use a secure channel because we're transferring sensitive
            // information.

        securityControl = session.feature(SecurityControl.class);
        emptyScript = securityControl.scriptBuilder();

     * This will update the security store to ensure that all roles start with a
     * capital letter (note that this does not address changing the use of the
     * roles in the system authentication store).
     * @return a CompletableFuture that completes when the operation succeeds or
     *         fails.
     *         <p>
     *         If the operation was successful, the CompletableFuture will
     *         complete successfully.
     *         <p>
     *         Otherwise, the CompletableFuture will complete exceptionally with
     *         an {@link ExecutionException}. See
     *         {@link SecurityControl#getSecurity()} and
     *         {@link SecurityControl#updateStore(String)} for common failure
     *         reasons.
    public CompletableFuture<Void> capitalizeRoles() {
        return securityControl.getSecurity().thenCompose(this::capitalizeRoles);

    private CompletableFuture<Void> capitalizeRoles(
        SecurityConfiguration configuration) {

        final String script = emptyScript



                // For each role ...
                // ... build a script that capitalises that role ...
                /// .. and combine the per-role scripts into one.
                .reduce(emptyScript, (sb1, sb2) -> sb1.append(sb2)))


        LOG.info("Sending the following script to the server:\n{}", script);

        return securityControl.updateStore(script)
            // Convert CompletableFuture<?> to CompletableFuture<Void>.
            .thenAccept(ignored -> { });

    private ScriptBuilder capitalizeRole(Role role) {
        final String oldName = role.getName();
        final String newName = capitalizeString(oldName);

        ScriptBuilder builder = emptyScript;

        // Only if new name is different
        if (!oldName.equals(newName)) {
            if (!role.getGlobalPermissions().isEmpty()) {
                builder = builder
                    // Remove global permissions for old role
                    .setGlobalPermissions(oldName, emptySet())
                    // Set global permissions for new role
                        newName, role.getGlobalPermissions());

            if (!role.getDefaultPathPermissions().isEmpty()) {
                builder = builder
                    // Remove default path permissions for old role
                    .setDefaultPathPermissions(oldName, emptySet())
                    // Set default path permissions for new role
                        newName, role.getDefaultPathPermissions());

            builder = builder.append(
                    entry -> {
                        final String path = entry.getKey();
                        final Set<PathPermission> permissions = entry.getValue();

                        return emptyScript
                            // Remove path permissions for old role
                            .removePathPermissions(oldName, path)
                            // Set path permissions for new role
                            .setPathPermissions(newName, path, permissions);
                    .reduce(emptyScript, (sb1, sb2) -> sb1.append(sb2)));

        final Set<String> oldIncludedRoles = role.getIncludedRoles();

        if (oldIncludedRoles.isEmpty()) {
            return builder;

        return builder
            // Remove old included roles.
            .setRoleIncludes(oldName, emptySet())

            // Set new roles even if role name did not change as the included
            // roles may be changed.
            .setRoleIncludes(newName, capitalizeSet(oldIncludedRoles));

    private static Set<String> capitalizeSet(Set<String> roles) {
        return roles.stream()

    private static String capitalizeString(String role) {
        return Character.toUpperCase(role.charAt(0)) + role.substring(1);

     * Close the session.
    public void close() {

Change the URL from that provided in the example to the URL of Diffusion Cloud. Diffusion Cloud service URLs end in diffusion.cloud