Managing User Sessions in Ignition Perspective

In our ever more connected world, it can be difficult to manage access to plant SCADA systems from multiple locations. While it’s possible to utilize single sign on (SSO) to give your operators all unique sessions, this isn’t feasible for every situation.

Consider a case with a global operator login for a control room. You’ll probably have a certain type of access set up on this login. They will have enough access to run the plant, but not enough to make drastic changes to recipes, schedules, or otherwise.

In many plants, locking this operator login down to a single session is desired. But, this approach may or may not have the additional requirement of locking the login down to a particular computer. In this post, we’ll show you how to accomplish both of these approaches using Ignition Perspective.

Using Perspective Session Events

To manage sessions, we’ll add our code to the Perspective Session Events portion of our project. We’ll take a deeper dive into how session events work in another post. In this post, we will be focusing on the Page Startup event type.

This event executes when a page starts up—right AFTER the user has logged in—but before they can interact with anything on the page. Technically, you could use a session startup event, however this type of event occurs before the user has logged in. Unfortunately, this can lead to caching issues with the browser, putting a soft lock on the system and delaying the ability to log in for a few minutes!

Basically, we’re going to supply a known username that we want to lock down to a single session at a time. If the newly logged in user is using the same login, we will kick them out with a note indicating there is already an active session. From there they can login with a different username if they desire.

Page Startup: Checking a User Session

Screenshot of the page startup session event with code to check the current session's user, see if any sessions exist and log out if there are multiple sessions logged in.

In the code above, we are checking for multiple sessions opened by the “operator” user. If we wanted to check for multiple sessions from any user we could simplify this code a little. Or if we wanted to check for a session open on a particular computer, we could do that too. We could also lock down particular users to certain machines if necessary. Please note that in this code we are also writing notes to the gateway logs which will be helpful for troubleshooting or monitoring the operation of the system.

When we pass the username, we want to check in the system.perspective.getSessionInfo() function call, which will return a list of any sessions open with that username. Then by checking the length of these results to see if the value is greater than one, we’ll see if we have multiple sessions open under the operator login. If there’s only one session, we will note that there’s one session open, and that we are now logged in on the Page Startup event.

Finally, we will check the current session’s username using the relevant session property. If it is “operator”, we log the user out and display a relevant message indicating why they were logged out of the system. This allows us to keep the number of sessions limited on a per username basis and can be a very handy tool when you need it.

Going Deeper: Limiting Access to Specific Computers

If we want to apply the same concept to limiting access for a particular user to a specific computer, we can look at the current session, grab the clientAddress property and compare it to our desired value. If they don’t match up, we would simply log the user out in the same way, but providing a different message this time.

userCheck = 'operator'
sessions = system.perspective.getSessionInfo(userCheck)
currentSession = system.perspective.getSessionInfo()

if len(sessions) >1:
     if page.session.props.auth.user.userName == userCheck:
          system.perspective.logout(sessionID=page.session.props.id, message='The operator account is already in use. Your session is being terminated.')
     elif "192.168.1.112" not in currentSession[0].clientAddress:
          system.perspective.logout(sessionID=page.session.props.id, message='This computer is not authorized for this username.')

In the code above, we’re grabbing the current session info, then checking the clientAddress property against our desired IP address of 192.168.1.112. If this value is not in the current session (meaning the user logged in from a machine with an IP address other than 192.168.1.112), we will log them out and display a message indicating that access on this computer is not authorized.

Wrapping Up: Page Startup Events and User Sessions

When necessary, locking down user access based on the number of sessions or to specific computers can be a powerful tool—but, it isn’t always necessary. However, when you do need this functionality, it’s great that Inductive Automation’s Ignition and Perspective make it very easy to implement.

The trick is to place the code in the Page Startup Event. It is significantly more complicated to try to use a Session Startup Event. The tradeoff is that it will run this code every time a page is started. Given the constraints of available events, this is acceptable. But, it would be nice to have a user authentication event built into the system to decouple this task from page loads. Maybe we can get this in a future release!

Previous
Previous

Searchable Tables in Opto 22 groov View

Next
Next

Database Table Integration in Opto 22 groov View