Get Roles Via Scripting from an SAML 2.0 IDP

Hi Everyone,

I'm running Perspective on 8.1.33.

I have an SAML 2.0 IdP that I'm using to authenticate my project, and I'm attempting to access the users' roles via scripting. My method for traditional IdPs was to use system.user.getUserRoles(), but that call requires that I pass in a User Source. But a SAML 2.0 IdP has no User Source...

I can see that roles are being returned for the logged in user, by looking at the session variables. But I'm unable to access those variables via scripting. Is there a scripting call that allows me to access the user's roles?

Thanks in advance.
Matt

But I'm unable to access those variables via scripting.

You should be able to. Something like self.session.props.auth.user.roles should work but we need more information about what context you're scripting in. Post your script and where / how you are trying to run it.

1 Like

Thanks for the quick reply.

I'm trying to write the script in a view.onStartup script, but I'd be fine running from any location where session variable or system.xxx function calls could be made.

So far, I've tried using system.user.getRoles() in this startup script, which throws error
image

presumably because this call returns the roles of the default user source, and I don't have a user source set up in my arrangement.

I can also see the session variable with the role data:
image
image

but I can't path to it successfully in the script:

system.perspective.print(self.session.props.auth.securityLevels[1].children[0].children[0].name)

only returns a blank string.

Thanks.

Ultimately you just want a list of all possible roles available, not the roles of the current user?

I'd like the roles of just the current user. In hindsight, system.user.getRoles() would return all the roles, which was a confusing piece of code to put out there!

That code works for vision but not perspective. I think you want this prop off the session - returns a list of roles of the current user.

image

session.props.auth.user.roles - just select it from the session property selector in whatever extension function you're doing it. I think you can copy and paste what I put there if it is onSessionStartup as session is the given param.

A session starts up before authentication happens, so you'll have to check this value at some later point.

1 Like

Thought that may be an issue, I am just getting back to perspective stuff. The more appropriate spot may be to do it onPageStartup of your default / page -

What exactly is it you are trying to do in general with this information? Just so we don't go potentially re-inventing the wheel.

OK @pturmel good to know about timing - I didn't know that.

Use case is to read the user's roles on project startup, and allow/disallow access to certain pages based on the user's assigned roles. This is accomplished by writing the roles to a set of globally accessible tags that are used to expose which menu items the customer sees.

I'm seeing the role where you said it should be in the designer's session variables, @bkarabinchak.psi . I put together a script on a button in the project, so I can run it WELL after everything is loaded, but I'm reading blanks for the session values.

system.perspective.print('test')
system.perspective.print(session.props.auth.user.roles[0])
system.perspective.print(self.session.props.auth.securityLevels[1].children[0].children[0].name)

I think what's going on is that the Gateway/Designer are on an internal IdP (so I can see the roles there) and the project is on the customer's SAML IdP. I'm guessing that the customer isn't sending the roles through, as expected, so the blank values are appropriate.

Thanks for the help, guys. I'll follow up here if I find anything good on my end.

I hope you mean session custom properties. Tags are shared across all users on a gateway.

Consider unconditionally setting these custom properties to "disallowed" during session startup. Then possibly update them when views access the user ID later.

Is this someone that someone like an admin can edit at run time? If not, there is this built in option to limit who can see a view based on roles - Security in Perspective - Ignition User Manual 8.1 - Ignition Documentation

I like this option, at least as a stop-gap. But I noticed something noteworthy here. In the project properties (Project/General), the Identity Provider is set to use the SAML IdP. I know this is working, because our project authenticates successfully against our Okta provider.

I also notice that in project properties (Project/General), there is a User Source set, that can't be deleted or set to blank. When I follow your suggestion and set my view permissions to use the roles, it's pulling up the roles (Administrator and Maintenance) from the User Source, not the SAML IdP (which would be Administrator, Supervisor, and Operator). Any thoughts on how to force the project to reference the SAML's roles from the Configure Permission's menu?

image

Yup, I mean custom session properties. Makes sense about disallowing them during startup.

1 Like

May I suggest an alternate approach to using scripting? Consider setting up a/many (depending on your needs) custom session properties and binding them to an expression using either the hasRole() or isAuthorized() functions. Those will evaluate after session start but before the user gets to interact with anything. From there you can bind other properties. Perhaps to a button that is used to navigate to the certain pages you may or may not want the user to access.
Keep in mind that if you take this approach, the user will still be able to access the pages via directly inputing their URL into the search bar.

3 Likes

@MSviga thanks for the input. Now that the roles are coming through (see the conclusion post below) both of those calls would be worth considering.

The customer's sysadmin found the ultimate solution, by adding the following text in the Gateway setting at Config/Identify Providers/More/User Attribute Mapping, which maps the roles to a SAML attribute.

Now the session property session.props.auth.user.roles is populated with the authenticated users' roles.

Thanks to everyone for the input!

1 Like