Example: Update the security store
The following examples use the SecurityControl feature in the Unified API to update the security store.
JavaScript
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 diffusion.connect({ 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']) .build(); // 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']) .build(); // 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 java.util.Collections; import java.util.Map; import java.util.Set; import java.util.TreeSet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.pushtechnology.diffusion.client.Diffusion; import com.pushtechnology.diffusion.client.callbacks.ErrorReason; import com.pushtechnology.diffusion.client.features.control.clients.SecurityControl; import com.pushtechnology.diffusion.client.features.control.clients.SecurityControl.ConfigurationCallback; 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.features.control.clients.SecurityStoreFeature.UpdateStoreCallback; import com.pushtechnology.diffusion.client.session.Session; import com.pushtechnology.diffusion.client.types.GlobalPermission; import com.pushtechnology.diffusion.client.types.TopicPermission; /** * 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 = LoggerFactory.getLogger( ControlClientChangingSecurity.class); private final SecurityControl securityControl; /** * Constructor. */ public ControlClientChangingSecurity() { final Session session = Diffusion.sessions() // Authenticate with a user that has the VIEW_SECURITY and // MODIFY_SECURITY permissions. .principal("admin").password("password") // Use a secure channel because we're transferring sensitive // information. .open("wss://diffusion.example.com:80"); securityControl = session.feature(SecurityControl.class); } /** * 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). * * @param callback result callback */ public void capitalizeRoles(UpdateStoreCallback callback) { securityControl.getSecurity(new CapitalizeRoles(callback)); } private final class CapitalizeRoles implements ConfigurationCallback { private final UpdateStoreCallback callback; CapitalizeRoles(UpdateStoreCallback callback) { this.callback = callback; } @Override public void onReply(SecurityConfiguration configuration) { ScriptBuilder builder = securityControl.scriptBuilder(); builder = builder.setRolesForAnonymousSessions( capitalize(configuration.getRolesForAnonymousSessions())); builder = builder.setRolesForNamedSessions( capitalize(configuration.getRolesForNamedSessions())); for (Role role : configuration.getRoles()) { final String oldName = role.getName(); final String newName = capitalize(oldName); // Only if new name is different if (!oldName.equals(newName)) { // Global Permissions final Set<GlobalPermission> globalPermissions = role.getGlobalPermissions(); if (!globalPermissions.isEmpty()) { // Remove global permissions for old role builder = builder.setGlobalPermissions( oldName, Collections.<GlobalPermission>emptySet()); // Set global permissions for new role builder = builder.setGlobalPermissions( newName, role.getGlobalPermissions()); } final Set<TopicPermission> defaultTopicPermissions = role.getDefaultTopicPermissions(); if (!defaultTopicPermissions.isEmpty()) { // Remove default topic permissions for old role builder = builder.setDefaultTopicPermissions( oldName, Collections.<TopicPermission>emptySet()); // Set default topic permissions for new role builder = builder.setDefaultTopicPermissions( newName, role.getDefaultTopicPermissions()); } final Map<String, Set<TopicPermission>> topicPermissions = role.getTopicPermissions(); if (!topicPermissions.isEmpty()) { for (Map.Entry<String, Set<TopicPermission>> entry : topicPermissions .entrySet()) { final String topicPath = entry.getKey(); // Remove old topic permissions builder = builder.removeTopicPermissions( oldName, topicPath); // Set new topic permissions builder = builder.setTopicPermissions( newName, topicPath, entry.getValue()); } } } final Set<String> oldIncludedRoles = role.getIncludedRoles(); if (!oldIncludedRoles.isEmpty()) { if (!oldName.equals(newName)) { // Remove old included roles builder = builder.setRoleIncludes( oldName, Collections.<String>emptySet()); } // This is done even if role name did not change as it is // possible that roles included may have final Set<String> newIncludedRoles = capitalize(oldIncludedRoles); builder = builder.setRoleIncludes( newName, newIncludedRoles); } } final String script = builder.script(); LOG.info( "Sending the following script to the server:\n{}", script); securityControl.updateStore( script, callback); } private Set<String> capitalize(Set<String> roles) { final Set<String> newSet = new TreeSet<>(); for (String role : roles) { newSet.add(capitalize(role)); } return newSet; } private String capitalize(String role) { return Character.toUpperCase(role.charAt(0)) + role.substring(1); } @Override public void onError(ErrorReason errorReason) { // This might fail if the session lacks the required permissions. callback.onError(errorReason); } } /** * Close the session. */ public void close() { securityControl.getSession().close(); } }
.NET
using System.Collections.Generic; using System.Linq; using PushTechnology.ClientInterface.Client.Callbacks; using PushTechnology.ClientInterface.Client.Factories; using PushTechnology.ClientInterface.Client.Features.Control.Clients.SecurityControl; using PushTechnology.ClientInterface.Client.Types; namespace Examples { /// <summary> /// An example of using a control client to alter the security configuration. /// /// This uses the <see cref="ISecurityControl"/> feature only. /// </summary> public class ControlClientChangingSecurity { private readonly ISecurityControl securityControl; public ControlClientChangingSecurity() { // Authenticate with a user that has the VIEW_SECURITY and MODIFY_SECURITY permissions. var session = Diffusion.Sessions.Principal( "admin" ).Password( "password" ) // Use a secure channel because we're transferring sensitive information. .Open( "wss://diffusion.example.com:8443" ); securityControl = session.GetSecurityControlFeature(); } public void DoCapitalizeRoles( IUpdateStoreCallback callback ) { securityControl.GetSecurity( new CapitalizeRoles( securityControl, callback ) ); } private class CapitalizeRoles : IConfigurationCallback { private readonly ISecurityControl theSecurityControl; private readonly IUpdateStoreCallback theCallback; /// <summary> /// Constructor. /// </summary> /// <param name="securityControl">The security control object.</param> /// <param name="callback">The callback object.</param> public CapitalizeRoles( ISecurityControl securityControl, IUpdateStoreCallback callback ) { theSecurityControl = securityControl; theCallback = callback; } /// <summary> /// Notification of a contextual error related to this callback. This is analogous to an exception being /// raised. Situations in which <code>OnError</code> is called include the session being closed, a /// communication timeout, or a problem with the provided parameters. No further calls will be made to this /// callback. /// </summary> /// <param name="errorReason">errorReason a value representing the error; this can be one of constants /// defined in <see cref="ErrorReason" />, or a feature-specific reason.</param> public void OnError( ErrorReason errorReason ) { // This might fail if the session lacks the required permissions. theCallback.OnError( errorReason ); } /// <summary> /// This is called to return the requested security configuration. /// </summary> /// <param name="configuration">The snapshot of information from the security store.</param> public void OnReply( ISecurityConfiguration configuration ) { var builder = theSecurityControl.ScriptBuilder(); builder = builder.SetRolesForAnonymousSessions( Capitalize( configuration.RolesForAnonymousSessions ) ); builder = builder.SetRolesForNamedSessions( Capitalize( configuration.RolesForNamedSessions ) ); foreach ( var role in configuration.Roles ) { var oldName = role.Name; var newName = Capitalize( oldName ); // Only if new name is different if ( !oldName.Equals( newName ) ) { // Global permissions var globalPermissions = role.GlobalPermissions; if ( globalPermissions.Count > 0 ) { // Remove global permissions for old role builder = builder.SetGlobalPermissions( oldName, new List<GlobalPermission>() ); // Set global permissions for new role builder = builder.SetGlobalPermissions( newName, new List<GlobalPermission>( role.GlobalPermissions ) ); } var defaultTopicPermissions = role.DefaultTopicPermissions; if ( defaultTopicPermissions.Count > 0 ) { // Remove default topic permissions for old role builder = builder.SetDefaultTopicPermissions( oldName, new List<TopicPermission>() ); // Set default topic permissions for new role builder = builder.SetDefaultTopicPermissions( newName, new List<TopicPermission>( role.DefaultTopicPermissions ) ); } var topicPermissions = role.TopicPermissions; if ( topicPermissions.Count > 0 ) { foreach ( var entry in topicPermissions ) { var topicPath = entry.Key; // Remove old topic permissions builder = builder.RemoveTopicPermissions( oldName, topicPath ); // Set new topic permissions builder = builder.SetTopicPermissions( newName, topicPath, entry.Value ); } } } var oldIncludedRoles = role.IncludedRoles; if ( oldIncludedRoles.Count > 0 ) { // Remove old included roles builder = builder.SetRoleIncludes( oldName, new List<string>() ); } // This is done even if role name did not change as it is possible that roles included may have var newIncludedRoles = Capitalize( oldIncludedRoles ); builder = builder.SetRoleIncludes( newName, newIncludedRoles ); } } private static List<string> Capitalize( IEnumerable<string> roles ) { return roles.Select( Capitalize ).ToList(); } private static string Capitalize( string role ) { return char.ToUpper( role[ 0 ] ) + role.Substring( 1 ); } } } }
Change the URL from that provided in the example to the URL of the Diffusion™ server.
This page last modified: 2017/06/29