I've successfully connected to my Azure AD within Ignition Gateway by defining an OpenID Connect Identity Provider. When i test my login, i get the idTokenClaims, tokenEndpointResponse, userInfo. Of course i added GroupMember.Read.All, openid, profile within the scopes.
Within my idTokenClaims i get a "groups" section with some GUID like which correspond to my Azure AD Groups i've defined.
My question is: Since User Source defined in the gateway define the Roles, and that Ignition doesn't let me define an Azure AD as a User Source to get these roles, how do i manage to know the roles for each users? I understand that at the IDP i can right-click on User Grants, and create them One by One, but it's not really efficient since these informations can already be found in the Azure AD. There must be something i'm missing.
Your roles in your Ignition user source won't necessarily line up with what's in Azure AD. Make sure the user attribute mapping for idTokenClaims path to your "groups" is configured properly for the Roles user attribute.
The way I like to do it is to create custom security levels outside of the Roles which are the standard levels I use in all of my design, then define security level rules for the identity provider to map those user groups/roles over to my custom security levels. This way my projects can be reused between customers without having to rework everything based on how they define their group/role names.
Azure AD is not able to provide the group names unless you have a hybrid setup, so I call a script to get the group names via script in the mapping, so my mapping for roles calls the expression:
In that script, I lookup the group names from a dataset tag holding the azure groups. If a group with matching id is not found in the tag, then the script updates the tag from Azure and tries again. This way, new groups are handled (the tag is updated) when users log in.
I then have security levels defined that match the groups I am interested in providing permissions for
Sorry for the delay on this post. I had an environment which didn't reflect the reality since i had no On Prem synchronized with Azure AD.
This is exactly what i've discovered yesterday Chris. I've done the test with the customer environment which is synchronized and when i did the Test Login, i was receiving the Roles Names, not their GUID.
The only problem with this is that if new groups are added, we have to fill them within this structure that you have defined, but it's not a major issue since this doesn't change much. It's just sad that Ignition is not 100% there yet for Azure AD. I'm fairly a novice for Ignition so i thought i was missing something.
from java.util import ArrayList
def GetGroupNames(ids):
logger = system.util.getLogger("AzureAdMapping")
logger.info("Azure group mapping requested")
names = []
for id in ids:
name = GetGroupName(id)
if(name != ''):
names.append(name)
return ArrayList(names)
def GetGroupName(id, refresh=False):
#handle known bad ids
#I have found that I always get a couple of group ids that dont match
#any group in our azure instance, which causes
#a refresh of the group tags every time someone logs in.
#I have them hardcoded in a list to avoid them
known_bad = ['someGuidThatDoesntMatchAnything', 'someOtherGuidThatAlsoDoesntMatch']
if id in known_bad:
return ''
groupsTag = system.tag.read('[POS]Azure/Groups')
groups = system.dataset.toPyDataSet(groupsTag.value)
for group in groups:
if(group['id'] == id):
return group['displayName']
#if we got here, we didn't find the group, so we should refresh the groups tag and try again.
#avoid infinite loop here, if we have refreshed the groups from azure and still get here, return an empty string
if(refresh):
return ''
logger = system.util.getLogger("AzureAdMapping")
logger.info("Cannot find matching group for id: " + id)
#don't refresh the groups if they've been updated recently
#you can remove this if you don't care
timeSinceLastGroupsRefresh = system.date.minutesBetween(groupsTag.timestamp, system.date.now())
if(timeSinceLastGroupsRefresh < 60):
logger.infof("Groups were last updated %d minutes ago. Too soon to refresh", timeSinceLastGroupsRefresh)
return ''
logger.info("Requesting groups refresh...")
AzureGraph.Authorize()
AzureGraph.GetGroups()
return GetGroupName(id, True)
I'm sure you can work out how to use the graph API to get the groups. The API call returns them as a list of dictionaries, I turn it into a dataset and store it in a tag. You could store it in a document tag instead.