User Attribute Mapping
The User Attribute Mapping page allows you to map information in the Identity Providers (IdP) response document to easily understandable properties. These properties are then made available as Session Properties in the Perspective Session. To work, this requires that the Gateway already has a valid IdP configuration which returns a response document when attempting to login.
Configuring a User Attribute Mappingβ
From the Gateway Webpage Config tab, click on Security > Identity Providers.
Select the Identity Provider and click on User Attribute Mapping under the More button.
The Name, Description, and Provider Type are not editable here, but are listed on the page to make clear which IdP the User Attribute Mapping is being configured on.
Under the User Attributes section of properties, you'll find settings for each of the mappable user attributes.
If you make changes to any of the mappings, be sure to click Save when finished.
User Attribute Mapping Property Reference Tableβ
Mappings can be configured on several user attributes.
Attribute | Description | Data Type |
---|---|---|
ID | The Type of mapping to apply for user IDs. | String |
Username | The Type of mapping to apply for usernames. | String |
First Name | The type of mapping to apply for first names. | String |
Last Name | The type of mapping to apply for last names. | String |
The type of mapping to apply for email addresses. | String | |
Roles | The type of mapping to apply for user roles. Note: While using an Expression type attribute mapping, you can use a runScript call to create a list of roles through scripting. However the script must return an ArrayList, as opposed to Jython collection types:
| Java ArrayList of Strings |
Each attribute mapping has similar properties, which are listed below
Property Name | Description |
---|---|
Type | The Type of mapping to apply for the attribute. Options are direct or expression. |
Source | The name of the attribute source. In cases where the identity provider has several Attribute Sources, this property allows you to specify which source the mapping should use. (for direct type only) |
Path | Path to the attribute map based on the selected source. Each node in the path is delimited by a slash character ( "/" ). (for direct type only) |
Expression | The source code for the expression used to map the targeted user attribute. See the Security Level Rules. (for expression type only) |
Direct Mappingβ
Direct mappings require that you enter in the path to an attribute in the response document for the given property. Values in the Identity Providerβs response document are dereferenced using the configured paths and are copied to the respective user properties in Ignition. The Source dropdown allows a particular mapping to target a specific object in the response document. The Path property then determines what object inside of source should be.
In the image below, the ID of the user, as represented on the Ignition Gateway, will be determined by the sub attribute, located in the ID Token Claims source in the response document.
Attribute Sourcesβ
Each Identity Provider has a different list of possible attribute sources. Below are several tables that list each possible source, as well as the expression path name for the source (used by {attribute-source:X:Y}
and {multi-attribute-source:X:Y}
expression paths. See Security Level Rules.)
IdP Type | Attribute Source(s) |
---|---|
Ignition | ID Token Claims (default) |
Ignition | Token Endpoint Response |
OIDC | ID Token Claims (default) |
OIDC | Token Endpoint Response |
OIDC | User Info Claims |
SAML | Authentication Response |
For Ignition and OIDC IdPs, the correct source to use will vary with the referenced attribute, and is included in the response document on the Test Login page.
The user info claims attribute source is present only when the user info URL is configured and Ignition receives a valid user info response from the IdP.
Expression Mappingβ
The Expression type allows you to use the expression language to derive the mapping from contextual data, such as the IdP response document or Tags. To assist with parsing the response document in an expression, there are several built-in objects.
Built-in Expression Objectsβ
In IdP contexts, it is possible to reference IdP response document elements using a three-part format:
{<Attribute Type>:<Attribute Source>:<Attribute Path>}
In this format, "<Attribute Type>"
is the attribute type we're attempting to reference, "<Attribute Source>"
is the name of the top-level attribute source, and "<Attribute Path>"
is a path to the property inside the attribute source. Here, we'll discuss the possible values for each part of this expression, and when they should be used.
Attribute Typeβ
Type | Expression Value | Description |
---|---|---|
Single-Valued Object | attribute-source | Provides the ability to reference an attribute (such as the username) returned from an IdP attribute source where the attribute's value is expected to be a single atomic value, usually a string. |
Multi-Valued Object | multi-attribute-source | Provides the ability to reference an attribute (such as the user's roles) returned from an IdP attribute source where the attribute's value is expected to be a collection of single atomic values, usually a collection of strings. |
Attribute Sourceβ
Possible values for the attribute source will vary by IdP type:
IdP Type | Attribute Source(s) | Expression Path Name |
---|---|---|
Ignition | ID Token Claims (default) | idTokensClaims |
Ignition | Token Endpoint Response | tokenEndpointResponse |
OIDC | ID Token Claims (default) | idTokenClaims |
OIDC | Token Endpoint Response | tokenEndpointResponse |
OIDC | User Info Claims | userInfo |
SAML | Authentication Response | authnResponse |
For Ignition and OIDC IdPs, the correct source to use will vary with the referenced attribute, and is included in the response document on the Test Login page.
Prior to Ignition 8.1.5, the expression path for SAML Authentication Response did not have an explicit name, so the attribute-source expression path would simply default to Authentication Response in all cases. As of 8.1.5, authnResponse must be explicitly stated when attempting to access the Authentication Response source with expression paths. See Expression Mapping.
Attribute Pathβ
The final element in an attribute reference is a path to the attribute within the attribute source. Here, the Test Login page is helpful for accessing the attribute source's structure in the response document.
If the attribute source is a JSON document (as is the case with Ignition and OIDC IdPs), then a JSON Path may be used to reference the target attribute.
If the attribute source is an XML document (as is the case with SAML IdPs), then an XPath 1.0 expression may be used to reference the target attribute. See the Multi-Valued Object Example further down.
Single-Valued Object Exampleβ
This example makes use of the Single-Valued Object on an JSON response document from an OpenID Connect IdP. The document used by this example is listed in the code block below.
Sample OIDC Response Document
{
"idTokenClaims": {
"sub": "00u4zl66kjWSxpKyH357",
"name": "Paul Person",
"email": "person@company.com",
"ver": 1,
"iss": "https://573779.okta.com",
"aud": "0oa2uqi4odPcNHRpS357",
"iat": 1617831866,
"exp": 1617835466,
"jti": "ID.itbv0TrKsyxqJpEsqwkVHaVa07xBD_haRQMnGUQ5tz4",
"amr": [
"pwd"
],
"idp": "00ob8o86nJ2kN48V4356",
"nonce": "a2Zq9QA1xL7t_apS58YIPaegbGD9w6FN60qSgP0i7fg",
"preferred_username": "person@company.com",
"auth_time": 1617831865,
"at_hash": "TEbuSUf8aMhWGYDuHsC0jQ"
},
"tokenEndpointResponse": {
"token_type": "Bearer",
"expires_in": 3600,
"access_token": "eyJraWQiOiJCVlowd3JweUdiRnB5cG5EQ05HbUpnMnhtbW5sc0h3TlBRdVp3MjQxSjdrIiwiYWxnIjoiUlMyNTYifQ.eyJ2ZXIiOjEsImp0aSI6IkFULmhmaEVRLUFiZzIyVU1Bb3NWNm9wWld1NHFGWmIzZUdLR25VVUNhX1lWWWciLCJpc3MiOiJodHRwczovL2Rldi01NzM3Nzkub2t0YS5jb20iLCJhdWQiOiJodHRwczovL2Rldi01NzM3Nzkub2t0YS5jb20iLCJzdWIiOiJwc2NvdHRAaW5kdWN0aXZlYXV0b21hdGlvbi5jb20iLCJpYXQiOjE2MTc4MzE4NjYsImV4cCI6MTYxNzgzNTQ2NiwiY2lkIjoiMG9hMnVxaTRvZFBjTkhScFMzNTciLCJ1aWQiOiIwMHU0emw2NmtqV1N4cEt5SDM1NyIsInNjcCI6WyJvcGVuaWQiLCJlbWFpbCIsInByb2ZpbGUiXX0.GR3JoTmbNtD7FDV59cuiE3wXsNJARN_zz5pmtnhLr19BGgiR7KJonYXBo7E_KPJ82RAEKsGRKFLzSDIzaB2QUCPyzJSsNg2LKvht5yoQoguoY6HqgeU73UkF6gbEhE3c_WfW1reewN8eazIOnvYJQhmVZYrhlF04XYOcB8o_1raNku3yUw76MDyAlWpaXuYQ2b9UYir3CLlb7AwpYTHdRHAk7zdFv713m4aR5IgVt0Pch8pFarX4k3o6Sg4ZghLW-4eioSzs0CrVLk3j09vQIEKn0jdlKqY0i9_9HBiEGUrVOXuiJ587ocRTjvxeNCpr_B7DBczBbtTkOFNzw3xRhw",
"scope": "openid email profile",
"id_token": "eyJraWQiOiJUNEhmZDQ0LXVVQ09sMGJpTl9fWnprQkJYWVdSSXlQYXBIZi1QeFRFTHYwIiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiIwMHU0emw2NmtqV1N4cEt5SDM1NyIsIm5hbWUiOiJQYXVsIFNjb3R0IiwiZW1haWwiOiJwc2NvdHRAaW5kdWN0aXZlYXV0b21hdGlvbi5jb20iLCJ2ZXIiOjEsImlzcyI6Imh0dHBzOi8vZGV2LTU3Mzc3OS5va3RhLmNvbSIsImF1ZCI6IjBvYTJ1cWk0b2RQY05IUnBTMzU3IiwiaWF0IjoxNjE3ODMxODY2LCJleHAiOjE2MTc4MzU0NjYsImp0aSI6IklELml0YnYwVHJLc3l4cUpwRXNxd2tWSGFWYTA3eEJEX2hhUlFNbkdVUTV0ejQiLCJhbXIiOlsicHdkIl0sImlkcCI6IjAwb2I4bzg2bkoya040OFY0MzU2Iiwibm9uY2UiOiJhMlpxOVFBMXhMN3RfYXBTNThZSVBhZWdiR0Q5dzZGTjYwcVNnUDBpN2ZnIiwicHJlZmVycmVkX3VzZXJuYW1lIjoicHNjb3R0QGluZHVjdGl2ZWF1dG9tYXRpb24uY29tIiwiYXV0aF90aW1lIjoxNjE3ODMxODY1LCJhdF9oYXNoIjoiVEVidVNVZjhhTWhXR1lEdUhzQzBqUSJ9.b5wi6CH0p1OigL6aaamZu3aVbOHRgiKdHFKqEgU0PLfbTILGtabhLktic843XaBTiQm8s3oXz153P3rdsUP4VPj1jXF8C221iEjP-55PyBX2kQ-ggyqXVrWlywmOWFNn4kSjViuzMIt2gXeW8yW-OBtxBTZr7QPDF6XKwZk6V183K0hT3ZbrzHcqZ0juIEkxrrfDU8N8Fo8bO94A2rGPp0mfSPttkrxxZBJ3bO6oY5e7NtcBnt4IsbSZfvI3_1KUoQt0SylljsescEZGxRJCfNdE3dJyOaQZuBKLN8ouxibD9Jdmn9_raeLGKOsxNHK0pNMRbptJ9UD4VemyezQvzA"
},
"userInfo": {
"sub": "00u4zl66kjWSxpKyH357",
"name": "Paul Person",
"locale": "en-US",
"email": "person@company.com",
"preferred_username": "person@company.com",
"given_name": "Paul",
"family_name": "Person",
"zoneinfo": "America/Los_Angeles",
"updated_at": 1596495564,
"email_verified": true
}
}
If, for example, we wanted to configure a mapping on the First Name, which would allow us to retrieve the name of the user provided by the response document. The given_name under userInfo appears to have the value we're looking for.
We can use the attribute-source object to directly reference the node.
{attribute-source:userInfo:given_name}
This is equivalent to using a direct mapping type with Source set to "ID Token Claims" and Path set to "name". However, since we're using the expression language, we have access to more tools, which is useful in cases where the attribute value we're looking for isn't as readily accessible.
For example, say the response document did not contain a node that represented just the users first name. However, it does contain a name under idTokenClaims (line 4) to that has the user's full name. We could access the full name, and then use the expression language's split function to split the first and last names.
split({attribute-source:idTokenClaims:name}, ' ')[0,0]
Multi-Valued Object Exampleβ
This example makes use of the Multi-Valued Object on an XML response document from a SAML IdP. Here we can use an XPath expression to examine the document and reference a specific node. We'll configure an expression type mapping that will retrieve attribute values that we want mapped to a user's Roles. Below we see the results of a test login. Our user does not appear to have any roles mapped.
If we click on the IdP Response Data tab, we see the results listed in the code block below.
Sample SAML Response Document
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:xs="http://www.w3.org/2001/XMLSchema" Destination="http://localhost:8088/data/federate/callback/saml" ID="id508417152055433477622124" InResponseTo="A-tiacipjeAZM4e4xHRRgFkV9KrOx5Mv8tHrdowuL7zi0" IssueInstant="2021-04-06T21:42:33.776Z" Version="2.0">
<saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">http://www.okta.com/exkj0b0vtttYvPzH10h7</saml2:Issuer>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<ds:Reference URI="#id508417152055433477622124">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="xs"/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue>UYW4pdcsWK19aRbSl3NlgRc+RZ1jIyCK6hsXnSu7VYs=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
</ds:Signature>
<saml2p:Status>
<saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
</saml2p:Status>
<saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="id508417152165556256586917" IssueInstant="2021-04-06T21:42:33.776Z" Version="2.0">
<saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">http://www.okta.com/exkj0b0vtttYvPzH10h7</saml2:Issuer>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<ds:Reference URI="#id508417152165556256586917">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="xs"/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue>xNlFDTmRTPXYqSLpruOZoPSq2Lz6q1rPrGiROR6MXdM=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
</ds:Signature>
<saml2:Subject>
<saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">person@company.com</saml2:NameID>
<saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml2:SubjectConfirmationData InResponseTo="A-tiacipjeAZM4e4xHRRgFkV9KrOx5Mv8tHrdowuL7zi0" NotOnOrAfter="2021-04-06T21:47:33.776Z" Recipient="http://localhost:8088/data/federate/callback/saml"/>
</saml2:SubjectConfirmation>
</saml2:Subject>
<saml2:Conditions NotBefore="2021-04-06T21:37:33.776Z" NotOnOrAfter="2021-04-06T21:47:33.776Z">
<saml2:AudienceRestriction>
<saml2:Audience>http://localhost:8088</saml2:Audience>
</saml2:AudienceRestriction>
</saml2:Conditions>
<saml2:AuthnStatement AuthnInstant="2021-04-06T21:26:07.499Z" SessionIndex="A-tiacipjeAZM4e4xHRRgFkV9KrOx5Mv8tHrdowuL7zi0">
<saml2:AuthnContext>
<saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml2:AuthnContextClassRef>
</saml2:AuthnContext>
</saml2:AuthnStatement>
<saml2:AttributeStatement>
<saml2:Attribute Name="FirstName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
<saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Paul</saml2:AttributeValue>
</saml2:Attribute>
<saml2:Attribute Name="LastName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
<saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Scott</saml2:AttributeValue>
</saml2:Attribute>
<saml2:Attribute Name="Email" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
<saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">person@company.com</saml2:AttributeValue>
</saml2:Attribute>
<saml2:Attribute Name="Role" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
<saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string"/>Operator</saml2:AttributeValue>
<saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string"/>Supervisor</saml2:AttributeValue>
</saml2:Attribute>
<saml2:Attribute Name="Groups" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
<saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string"/>
</saml2:Attribute>
</saml2:AttributeStatement>
</saml2:Assertion>
</saml2p:Response>
In the example document, lines 68 and 69 contain saml2:AttribueValue elements, which contain the roles for our user. Starting from the roles, we can work our way back towards the top of the document, but making the following observations.
We see both elements are under a
saml2:Attribute
element (line 67).The
saml2:Attribute
element is under asaml2:AttributeStatement
element (line 57).The
saml2:AttribueStatement
element is under asaml2:Assertion
element (line 23).Finally, the
saml2:Assertion
element is under thesaml2p:Response element
, which seems to be the root for the entire path (line 2).
Thus, we're looking for all text values of all saml2:AttributeValue elements that are under a specific saml2:Attribute element. We see that the saml2SAttribute element we're looking for also has name attribute set to "Role", which we can use to help focus our path. Based on our observations, the path looks like the following:
Note that we start at the root of the saml2p:Reponse element (on the left), and build the rest of the path in reverse order of our observations.
We specified that the saml2:Attribute must contain an attribute by the name of "Name", with a value of "Role", with which filters out the other saml2:Attribute elements in the document (such as the elements with FirstName and LastName).
In addition, we ended the path with text(), which access the text values of the nodes.
/saml2p:Response/saml2:Assertion/saml2:AttributeStatement/saml2:Attribute[@Name="Role"]/saml2:AttributeValue/text()
Writing the Pathβ
Now that we know what our path looks like, we can write an expression. We'll type the following into the "Expression" field for the Roles setting:
{multi-attribute-source:authnResponse:/saml2p:Response/saml2:Assertion/saml2:AttributeStatement/saml2:Attribute[@Name="Role"]/saml2:AttributeValue/text()}
If we then Save, we can attempt a test login, and check the mapped user attributes, where we see our roles from the response document now appear mapped to our user.
Tag Path Exampleβ
In addition, Tag values can be referenced by mappings. Note that the values are only checked when the user logs in. So if the value of any tags used in a mapping change after the user logs in, the result of the mapping won't retroactively change.
{[default]A_Folder/A_Tag.value}
In the example above, the expression would attempt to return the value of the Tag at path "A_Folder/A_Tag", in the Tag Provider named "default".