Connectivity Software User's Guide and Reference
OPC Wizard User Authorization
OPC Wizard > Concepts > OPC Wizard Features > OPC Wizard Access Control > OPC Wizard User Authorization
In This Topic

Introduction 

After the user is authenticated, OPC Wizard determines whether the user is authorized to log on to the server (in OPC UA terms, activate the session).

If the logon access is granted, the OPC Wizard then determines the security roles the user has. The security roles can be provided by the user manager objects, where you can simply configure the security roles for each user declaratively. Alternatively, you can write a custom code to take over the determination of user security roles, and implement whatever logic is necessary in your scenario.

OPC Wizard also takes care of automatically assigning certain implicit security roles according to the OPC UA rules.

Logon Authorization 

If the client uses a username and password user identity token and the user is successfully authenticated, OPC Wizard checks whether the user is enabled, and will not allows disabled users to logon to the server, even if they are authenticated. You can control whether the user is enabled when the user is created using the Create Method, or later using the SetEnabled Method on the name and password user manager.

When an anonymous user identity is allowed and an anonymous user token is used, the logon is automatically granted.

Security Roles

A user that accesses the server is associated with a set of security roles. The security roles are then used to determine the permissions the user has. OPC UA specifications define certain well-known security roles, and you can also add your own. Security role in OPC UA is identified by its role Id, which is an OPC UA node Id of the node that represents the security role. In OPC Wizard, the security role is represented by an instance of UASecurityRole Class, which also contains additional data, such as the role name.

OPC UA Well-Known Security Roles

The standard well-known OPC UA security roles are defined in the UASecurityRoles Class. Following well-known roles are in this class: 

Name Description
The OPC UA Anonymous well-known security role.  
The OPC UA AuthenticatedUser well-known security role.  
The OPC UA ConfigureAdmin well-known security role.  
The OPC UA Engineer well-known security role.  
The OPC UA Observer well-known security role.  
The OPC UA Operator well-known security role.  
The OPC UA SecurityAdmin well-known security role.  
The OPC UA SecurityKeyServerAccess well-known security role.  
The OPC UA SecurityKeyServerAdmin well-known security role.  
The OPC UA SecurityKeyServerPush well-known security role.  
The OPC UA Supervisor well-known security role.  
The OPC UA TrustedApplication well-known security role.  

For a discussion of well-known OPC UA security roles and their usage, see OPC UA Well-Known Security Roles.

OPC UA Custom Security Roles

You can create your own OPC UA security role using the Create Method, as illustrated in th example below.

.NET

// This example shows how to create and use custom security roles in OPC UA servers.
// You can use any OPC UA client, including our Connectivity Explorer and OpcCmd utility, to connect to the server. 
//
// Find all latest examples here: https://www.doc-that.com/files/onlinedocs/OPCLabs-ConnectivityStudio/Latest/examples.html .
// OPC client, server and subscriber examples in C# on GitHub: https://github.com/OPCLabs/Examples-ConnectivityStudio-CSharp .
// Missing some example? Ask us for it on our Online Forums, https://forum.opclabs.com/forum/index ! You do not have to own
// a commercial license in order to use Online Forums, and we reply to every post.

using OpcLabs.BaseLib.Security.User.Extensions;
using OpcLabs.EasyOpc.UA;
using OpcLabs.EasyOpc.UA.NodeSpace;
using OpcLabs.EasyOpc.UA.Security.Subject;
using System;

namespace UAServerDocExamples.AccessControl
{
    internal class _UASecurityRoles
    {
        public static void Create()
        {
            // Instantiate the server object.
            // By default, the server will run on endpoint URL "opc.tcp://localhost:48040/".
            var server = new EasyUAServer();

            // Create a custom security role with specified Node Id and name.
            UASecurityRole mySecurityRole = UASecurityRoles.Create(
                "nsu=http://my.example;s=MySecurityRole", "MySecurityRole");

            // Create users. Only the user "charlie" will be assigned the custom security role created above.
            server.UserManagers.NameAndPassword.CreateWithSecurityRoleIds("alpha", "pass",
                new string [] {UASecurityRoles.Engineer, UASecurityRoles.Operator});
            server.UserManagers.NameAndPassword.CreateWithSecurityRoleIds("charlie", "pass",
                new string[] { mySecurityRole });

            // Create a data variable providing random integers.
            var random = new Random();
            var dataVariable = new UADataVariable("MyDataVariable").ReadValueFunction(() => random.Next());

            // Assign permissions to the data variable. In this case, only users with our custom security role will be able
            // to browse, read and write the variable.
            dataVariable.PermissionAssignment = new UAPermissionAssignment
            {
                new UARolePermissions(mySecurityRole, UAPermissions.ViewBasic | UAPermissions.ModifyBasic)
            };
            // We do not want to inherit permissions from the parent nodes, as they include viewing for TrustedApplication.
            dataVariable.PermissionsInheritanceType = UAPermissionsInheritanceType.None;

            // Add the data variable to the server's address space.
            server.Add(dataVariable);

            // Start the server.
            Console.WriteLine("The server is starting...");
            server.Start();

            Console.WriteLine("The server is started.");
            Console.WriteLine();

            // Let the user decide when to stop.
            Console.WriteLine("Press Enter to stop the server...");
            Console.ReadLine();

            // Stop the server.
            Console.WriteLine("The server is stopping...");
            server.Stop();

            Console.WriteLine("The server is stopped.");
        }
    }
}

OPC UA Implicit Security Roles

In addition to explicitly defined roles for a user, OPC Wizard always adds certain implicit security roles to the security principal. The rules that govern the implicit security roles are laid out in OPC UA specifications. Briefly:

User Assignment By User Managers

In its default behavior, OPC Wizard obtains the security roles, i.e. authorizes the user, using the same user manager objects that were used for authentication.

If the client has used an anonymous user identity token, the IDs of the security roles are taken from the SecurityRoleIdSet Property of the anonymous user manager. By default, this set is empty, and anonymous users thus only get the implicit security roles as described above. You can modify this set if you want to assign additional roles to anonymous users.

If the client has used a username and password security token, the IDs of their security roles are obtained from the name and password user manager object (ReadOnlyNameAndPassword Property) using the GetSecurityRoleIdList Method. If you want to configure the security roles IDs associated with a specific user, access the NameAndPassword Property of UserManagers, and use the AddSecurityRoleId and RemoveSecurityRoleId methods.

You can also assign the security roles to the user right when creating the user, with the CreateWithSecurityRoleIds Extension Method.

The following example shows how to create a user with username and password, and assign it specific OPC UA roles.

.NET

// This example shows how to create a user with username & password and assign it specific OPC UA security roles. 
// You can use any OPC UA client, including our Connectivity Explorer and OpcCmd utility, to connect to the server. 
//
// Find all latest examples here: https://www.doc-that.com/files/onlinedocs/OPCLabs-ConnectivityStudio/Latest/examples.html .
// OPC client, server and subscriber examples in C# on GitHub: https://github.com/OPCLabs/Examples-ConnectivityStudio-CSharp .
// Missing some example? Ask us for it on our Online Forums, https://forum.opclabs.com/forum/index ! You do not have to own
// a commercial license in order to use Online Forums, and we reply to every post.

using OpcLabs.BaseLib.Security.User.Extensions;
using OpcLabs.EasyOpc.UA;
using OpcLabs.EasyOpc.UA.NodeSpace;
using OpcLabs.EasyOpc.UA.Security.Subject;
using System;

namespace UAServerDocExamples.AccessControl
{
    internal class NameAndPasswordUserManager
    {
        public static void CreateWithSecurityRoleIds()
        {
            // Instantiate the server object.
            // By default, the server will run on endpoint URL "opc.tcp://localhost:48040/".
            var server = new EasyUAServer();

            // Clear the default security roles (Operator) for the Anonymous user.
            server.UserManagers.Anonymous.SecurityRoleIdSet.Clear();

            // Create a user with username "alpha" and password "pass". The user session will be assigned the Engineer and
            // Operator security roles, in addition to the implicit Anonymous, AuthenticatedUser and possibly
            // TrustedApplication roles.
            server.UserManagers.NameAndPassword.CreateWithSecurityRoleIds("alpha", "pass",
                new string[] {UASecurityRoles.Engineer, UASecurityRoles.Operator});

            // Create a data variable providing random integers.
            var random = new Random();
            var dataVariable = new UADataVariable("MyDataVariable").ReadValueFunction(() => random.Next());

            // Assign permissions to the data variable. In this case, only users with the Engineer security role will be able
            // to browse, read and write the variable.
            dataVariable.PermissionAssignment = new UAPermissionAssignment
            {
                new UARolePermissions(UASecurityRoles.Engineer, UAPermissions.ViewBasic | UAPermissions.ModifyBasic)
            };
            // We do not want to inherit permissions from the parent nodes, as they include viewing for TrustedApplication.
            dataVariable.PermissionsInheritanceType = UAPermissionsInheritanceType.None;

            // Add the data variable to the server's address space.
            server.Add(dataVariable);

            // Start the server.
            Console.WriteLine("The server is starting...");
            server.Start();

            Console.WriteLine("The server is started.");
            Console.WriteLine();

            // Let the user decide when to stop.
            Console.WriteLine("Press Enter to stop the server...");
            Console.ReadLine();

            // Stop the server.
            Console.WriteLine("The server is stopping...");
            server.Stop();

            Console.WriteLine("The server is stopped.");
        }
    }
}

Custom User Assignment

If you have special needs, you can replace the user assignment mechanism described above by your own.

Similarly to what has been described in OPC Wizard User Authentication, you can do so by creating and using your own user manager objects.

Alternatively, you can also handle the GetIdentityContextSecurityRoleIds Event. In the event arguments, your code receives an UAIdentityContext that contains the information needed for authorization decisions. Your code will determine the security role IDs associated with the given identity context, and then call the HandleAndReturn Method to return them and indicate that the default processing should not be used.

 

See Also

Knowledge Base