Pick the Path Before Touching Config
Perspective always authenticates through an identity provider (IdP). The open question is where group membership comes from. The working pattern is an Active Directory user source, bound to Ignition's internal IdP, with AD groups mapped to roles and then to security levels.
These quick fixes come up first and don't hold:
- Hand-building Ignition roles per user. It works for a week. Then AD group changes stop propagating and nobody knows who has access.
- Checking role names directly in every view and script. Every project ends up hard-coding AD group strings. A rename in AD breaks all of them silently.
- Leaving the Azure app registration as-is and hoping groups show up. Group claims are not emitted by default. When they are, they often arrive as object IDs rather than readable names.
| Option | Group source | Needs | Watch for |
|---|---|---|---|
| AD user source + internal Ignition IdP | LDAP memberOf on the domain controller |
Gateway network path to a DC and a bind account | Nested groups; cloud-only groups do not exist in on-prem AD |
| Existing Azure/OIDC IdP with group claims | Token claims from the app registration | Group claims enabled in the app registration | Claims arriving as IDs; token size limits with many groups |
Check before continuing: from the gateway host, confirm you can reach a domain controller on the LDAP port you plan to use. Also confirm the target groups (for example Ignition_Administrators, Ignition_Read) exist in on-prem AD and are not cloud-only. If either check fails, stay on the OIDC path and do the claim mapping there. The security level steps below still apply.
Build the Active Directory User Source
- Under the gateway security config, add a new user source of type Active Directory.
- Enter the domain, the domain controller host(s), and a service account with read access to users and groups.
- Set the user role attribute. The default is
memberOf. Leave it there unless your directory stores group membership elsewhere. - If you want only a subset of groups to act as roles, create them under a dedicated OU with a consistent prefix, such as
Ignition_. That keeps the role list readable.
The memberOf attribute on a user lists direct memberships only. A user who is in Ignition_Read only through a nested group will not carry that role. Flatten the nesting for Ignition groups, or add users directly.
Check: use the user source's user and role listing or its test function. Confirm a known test account resolves and shows the expected group names as roles. Stop here if roles come back empty. That is a bind-account permission or search-base problem, and nothing downstream will fix it.
Bind the Internal IdP and Map the Roles Attribute
- Create an identity provider of type Ignition (the internal IdP). Point it at the new AD user source.
- Open its user attribute mapping. For Roles, set Type =
Direct, Source =ID Token Claims, and path =Roles. - Save the IdP. Leave your current Azure IdP in place for now. Do not swap anything over yet.
The mapping copies the user source roles into the IdP's attribute set. That set is what security level rules evaluate against. If the path is wrong, the login succeeds but the user gets no roles. The symptom is a user who can sign in and sees nothing.
Check: run the IdP's test login with a test account. The returned attributes must include a roles list containing the AD group names. Get this right before writing any rules.
Create Security Levels 1:1 With AD Groups
Put a security level layer between AD groups and project permissions. It adds one management step and pays for it in several ways:
- Multiple IdPs and user sources can grant the same levels. The Azure IdP and the AD-backed IdP can both drive
Area1/Facility1/View. - Projects reference levels, not raw group strings.
- Filtering and displaying what a user has been granted inside Ignition becomes simple.
- Build a security level tree that follows your plant structure. For example,
Area1/Facility1/View,Area1/Facility1/Control, and a gateway admin level. - In the IdP's security level rules, give each level an expression that matches its AD group:
containsAny({idp-attributes:roles}, 'Ignition_Area1_Site1_View') - Keep one AD group per level. If a level needs several groups, list them in the same
containsAnycall instead of stacking rules. - Match the case exactly. Group strings in rules must match what the test login returned.
Check: test login again. The result must now show the granted security levels, not just the raw roles. A missing level with the role present means the expression string doesn't match the group name.
Apply Levels to Gateway and Projects
- Protect your way back in. Before changing the gateway's own IdP or config permissions, confirm a working admin login through the new IdP. Keep a known-good fallback until then.
- Set the Perspective project's identity provider to the new internal IdP.
- Assign project, view, and component permissions by security level. Read-only groups get view levels. Write actions and navigation to control screens require the control levels.
- Set gateway config permissions to the admin level only. Users in
Ignition_Readmust not reach gateway configuration. - Only after steps 1 to 4 pass, switch the gateway login IdP if you want AD to govern it too.
Get it running on one project first, then fix the rest properly.
Check: open the project with an admin test account and then a read-only test account. Confirm the read-only session cannot write or open restricted views.
Verify End to End
Keep one test account per AD group, and hold each account in only one group. Run the matrix below after every change to groups, rules, or permissions.
| Test account group | Expected roles | Expected levels | Expected behavior |
|---|---|---|---|
Ignition_Administrators |
Admin group | Admin level plus all area levels | Gateway config and all projects writable |
Ignition_Read |
Read group | View levels only | Views load, writes blocked, gateway config denied |
Ignition_Area1_Site1_View |
Area group | Area1/Facility1/View |
Only Area1 screens visible |
| No Ignition group | None | None beyond authenticated | Login denied or landing page only |
After moving a test account between groups in AD, log out fully and log back in. The session must pick up the new membership. If it doesn't, check how long the user source caches data and whether AD replication has reached the DC the gateway queries.
FAQ
What happens if a user is in the AD group only through a nested group?
memberOf returns direct memberships, so the role will not appear and the security level rule will not fire. Add the user directly to the Ignition group, or flatten the nesting.
What happens if the test login shows roles but no security levels?
The attribute mapping works, but the rule expressions don't match. Compare the exact group string in containsAny({idp-attributes:roles}, '...') against the returned roles, including case and prefix.
What happens if I keep the Azure app registration instead of an AD user source?
It can work, provided the app registration emits group claims. Map those claims to the Roles attribute and reuse the same security level tree. Check the decoded token first, because groups often arrive as object IDs and the rules must match whatever is actually sent.
When should I stop and call Inductive Automation support?
Stop if the AD user source cannot list roles for a known account after you have verified bind-account permissions and the search base. Also stop if a gateway IdP change has locked you out of configuration. Collect the gateway logs and the test login output, then open a case through Inductive Automation's official support channel rather than editing security settings blind.