Identity Providers and Security Levels

Last night’s build includes the configuration pages in the Gateway Web Interface for Security Levels and Identity Providers! You will find the two new links here:

Identity Providers

In order to have Ignition 8 and Perspective be compatible with modern authentication practices, we have introduced a new concept, called Identity Providers (often shortened to IdP). An Identity Provider knows how to manage a web-based authentication strategy. Ignition 8 will include three different IdP types out of the box:

  1. Ignition IdP (Implemented)

This identity provider will authenticate against any User Source defined in Ignition. This is useful for standalone systems that do not want to integrate with an external authentication system. It also provides backwards compatibility for users who wish to continue using legacy authentication strategies such as LDAP based active directory authentication.

  1. OpenID-Connect IdP (Implemented)

This identity provider is used to integrate with an external IdP service that supports the OpenID-Connect (OIDC) 1.0 protocol, which is built on OAuth2.0. OpenID-Connect is used by many third party identity providers,

  1. SAML IdP (Not Yet Implemented as of 12/11/18)

This identity provider is used to integrate with an external IdP service that supports the SAML 2.0 protocol. SAML is also used by many third party identity providers, in particular: Microsoft Active Directory Federation Services (ADFS).

Security Levels

New in Ignition 8 is the concept of Security Levels. Security Levels are a platform-level construct aimed to make the permission modeling inside Ignition more convenient, portable. The idea is to introduce a stand-alone permission modeling system for use within Ignition, regardless of how identity was established. Put another way: security levels allow Ignition to have its own authorization system, independent of the authentication system being used.

Security Levels are defined gateway-wide so that they can be used by all projects, tags, and other systems on the Gateway. Security Levels are just strings (like roles), except that they are organized into a hierarchy. For example, you might have the following security levels defined:

  • User
  • Operator
  • LineA
  • LineB
  • Supervisor

Using security levels makes defining permissions simple. You simply pick which security levels have access to parts of your application. The hierarchy of security levels can be used to simplify the security settings, because users with more specific security levels also “inherit” the more general security levels. For example, a user granted the security level “Operator / LineB” also has the security level of “Operator”.

Special Reserved Security Levels

There are four “special” security levels built into the platform. The first is the “Public” security level. All users are always granted the Public security level, even if they are not authenticated. A session that only has the Public security level is not authenticated, put another way, they are a guest or anonymous. The Public security level is the ancestor of all other security levels in the hierarchy.

The second special security level is the “Authenticated” security level. It is a direct descendant of the Public security level. If a session has authenticated against the configured IdP successfully, they will have the “Authenticated” security level.

The third special security level is “Authenticated / Roles”. If the IdP used did provide “role” information, the roles provided will be added as child security levels underneath “Authenticated / Roles”. For example, if you authenticate against the Ignition IdP configured to delegate to the Internal user source, and your user was granted the roles “A”, and “B”, you would have (at a minimum) the following security levels granted to you:

  • Public
  • Authenticated
    • Roles
      • A
      • B

The fourth special security level is “SecurityZones”. It is a direct descendant of the Public security level. For each security zone Z that the user has, Z will be added as a direct descendant to the SecurityZones security level.

The Public security level is there to remind application designs that, unless another security level is required, guest access will be allowed. The Authenticated security level exists to provide a convenient way to mean “The user must be logged in to access/do this”. The legacy role information underneath “Authenticated / Roles” provides a way to bridge this new method of permission modeling with the role-based permission modeling from Ignition 7. Finally, the security zone information underneath “SecurityZones” provides a way to bridge this new method of permissions modeling with location-based permission modeling from Ignition 7.

Granting Security Levels

Since security levels exist outside of the scope of any identity provider, a mapping / granting mechanism is needed to actually assign authenticated users with security levels. Apart from the automatic security levels (Public, Authenticated, Authenticated / Roles, and SecurityZones), this will be done in two different ways.

Direct User Grants

The User Grants page of an Identity Provider gives the capability to directly assigned security levels to authenticated users identified with the unique ID or username.

Security Level Rules

The security levels rules for an Identity Provider allows users to set expression based rules for each security level in the tree that is not built into the system.

There are three special types of paths that the expression has access to:

  1. {idp-attributes:X} - access an attribute on the IdP response document where X = the path to the attribute on the IdP response document
  2. {security-zones} - the collection of security zones the user currently has (collection of the security zone name strings)
  3. {X} - access a tag where X is the tag path

For dealing with collections in expressions, two useful functions are available:

  1. containsAll(someCollection, element0, element1, ..., elementN) - checks if the expression someCollection contains all of the elements element0, element1, …, elementN
  2. containsAny(someCollection, element0, element1, ..., elementN) - checks if the expression someCollection contains at least one of the elements element0, element1, …, elementN

Conclusion

While Identity Providers and Security Levels are Platform-level capabilities, the Perspective module is the first and only adopter of these capabilities in 8.0.

User manual content for Identity Providers and Security Levels is in progress and will be published in the coming weeks.

6 Likes

How do you get the username now once they’re logged in?

system.security.getUsername() does not seem to work anymore. I get an error that the object has no attribute.

Are you talking about within the Expression on any of the Identity Provider stuff? Or are you referring to within a Perspective Session?

If the former, the system functions are scripting while the Identity Provider/Security Levels config is the Expression Language, and the script won’t typically work in an expression. To reference the username of a user within something like a Security Level Rule, you first need to make sure you are in a level within the Authenticated node, as those levels ensure the user has authenticated and we can obtain user information. You could then do something like Joel mentions above:
{idp-attributes:X} - access an attribute on the IdP response document where X = the path to the attribute on the IdP response document
That X could vary depending on what the IdP response document looks like.

If you are referring to the latter, you may want to check out the reference section in the user manual, as we have recently updated the scope of the functions to be more abundantly clear. https://docs.inductiveautomation.com/display/DOC80/system.security.getUsername
The function has a scope of Vision Client, which means it can’t be used in a Perspective session. As far as I know, there is a session prop that holds this information once the user actually logs in, though maybe someone else can chime in with more details on that.

To my knowledge you should reference a user’s username as a property with session.props.user.name.

To reference that same value in a script, you would want to use self.session.props.user.name.

3 Likes

Yes, thank you. That’s what I was looking for. Is there any documentation ready for those objects do you know?

Not yet, as the Auth content only made its way into the Beta this morning. The documentation should be in place in the coming days.

1 Like

We now have documentation on Identity Providers and Security Levels, feel free to check it out! Keep in mind that the manual is still very much a work in progress.
https://docs.inductiveautomation.com/display/DOC80/Identity+Providers
https://docs.inductiveautomation.com/display/DOC80/Security+Levels

5 Likes

Awesome! Checking this out over the next week or so.

Hi guys, Can the identity provider be used to authenticate the Gateway page and Designer?

Not yet, although this is something we want to support in the future (no timeline for this yet).

Thanks Joel, look forward to it. It’s working very well for us on Perspective so it would be nice to have a common user management for the platform.

2 Likes