Group and Property Mapping with OpenID Connect or JSON Web Tokens (JWT)
Purpose of this Document
These instructions are meant to help getting started with configuring group-mapping and property-mapping based on JSON web token (JWT) authentication, both for OpenID Connect (OIDC) and plain JWT authentication.
User property mappings can be configured not only based on a claim name, but also with a JSONPath (RFC 9535) reference to claim content.
Configuration
Plugins
The following plugins have to be activated. Excerpt of plugins.xml:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<pluginConfig>
<plugins>
…
<plugin name="AccessManager"/>
<!-- For OpenID Connect -->
<plugin name="AccessManager_Oidc" />
<!-- For plain JWT -->
<plugin name="AccessManager_Sso_Jwt"/>
…
Access Manager Configuration
In order to activate authentication and group-mapping for OpenID Connect or JWT-based authentication, they have to be defined in the accessmanager config in the section authenticators. Excerpt of accessmanager-config.xml:
<?xml version="1.0" encoding="UTF-8"?>
<userRegistry>
<authenticators>
<!-- For OpenID Connect -->
<authenticator refid="OIDC">
<groupMapping refid="OIDC" />
<propertyMapping refid="OIDC" />
</authenticator>
<!-- For plain JWT -->
<authenticator refid="JWT">
<groupMapping refid="JWT" />
<propertyMapping refid="JWT" />
</authenticator>
<!-- Further authenticator definitions, if applicable: -->
<authenticator refid="LDAP">
<groupMapping refid="LDAP" />
</authenticator>
</authenticators>
…
</userRegistry>
Configure Group Mapping
The principle and format for group mapping definition are the same for both OpenID Connect and plain JWT authentication.
The group mappings are defined within a groupMapping element.
Group mappings can be configured not only based on a claim name, but also with a JSONPath (RFC 9535) reference to claim content.
-
In case of OpenID Connect the element
groupMappingis placed after theprivateKeyelement in theaccessmanageroidcconfig. -
In case of plain JWT authentication the element
groupMappingis placed after thejwtValidation(orgenericJwtValidation) element in theaccessmanagerssojwtconfig.
The group-mapping contains two configurations:
-
The definition of the claim to be used for groups in the token.
-
Information on how Cadenza should interpret the groups extracted from the token, the actual mapping.
The groups claim can be referenced as claim name, but also with a JSONPath reference to the claim content.
The mapping configuration can be declared either as static mapping or dynamic mapping:
-
static mapping: Each claim value has to be mapped explicitly to a Cadenza group using its group mapping ID (defined in the Management Center). If no mapping is provided for a certain claim value, it is not mapped to any Cadenza group.
-
dynamic mapping: Each claim value is used as a group name and mapped to the Cadenza group mapping IDs of the same value. It is not possible to define transformation rules.
<?xml version="1.0" encoding="UTF-8"?>
…
<groupMapping>
<!-- either-->
<claim>groups</claim>
<!-- or-->
<claimPath>$.groups</claimPath>
<staticMapping claimValue="source1" groupName="target1"/> <!-- target1 being a group mapping ID -->
<staticMapping claimValue="source2" groupName="target2"/> <!-- target2 being a group mapping ID -->
…
<dynamicMapping>true</dynamicMapping>
</groupMapping>
…
Examples of possible configurations (OpenID Connect and plain JWT)
Plain definition of the claim name:
<?xml version="1.0" encoding="UTF-8"?>
…
<groupMapping>
<claim>groups</claim>
…
</groupMapping>
…
Definition of the claim via JSONPath:
<?xml version="1.0" encoding="UTF-8"?>
…
<groupMapping>
<claimPath>$.groups</claimPath>
…
</groupMapping>
…
Definition of static mapping rules (if the token contains a group claim value "where", it is not mapped to a Cadenza group):
<?xml version="1.0" encoding="UTF-8"?>
…
<groupMapping>
…
<staticMapping claimValue="this" groupName="that"/>
<staticMapping claimValue="here" groupName="there"/>
<!-- default value for dynamicMapping -->
<!-- <dynamicMapping>false</dynamicMapping> -->
</groupMapping>
…
Activation of dynamic mapping (if the token contains a group claim value "where", it is mapped to a Cadenza group "where"):
<?xml version="1.0" encoding="UTF-8"?>
…
<groupMapping>
…
<dynamicMapping>true</dynamicMapping>
</groupMapping>
…
A mixture of static and dynamic mapping is possible. In this case the claim values "this" and "here" are mapped to "that" and "there" respectively and a claim value "where" is automatically mapped to a group with the name "where":
<?xml version="1.0" encoding="UTF-8"?>
…
<groupMapping>
<staticMapping claimValue="this" groupName="that"/>
<staticMapping claimValue="here" groupName="there"/>
<dynamicMapping>true</dynamicMapping>
</groupMapping>
…
Configure Property-Mapping
The principle and format for property mapping definition is the same for both OpenID Connect and plain JWT authentication. The property mappings are defined within a propertyMapping element.
User property mappings can be configured not only based on a claim name, but also with a JSONPath (RFC 9535) reference to claim content.
-
In case of OpenID Connect the element
propertyMappingis placed after thegroupMappingelement in theaccessmanageroidcconfig. -
In case of plain JWT authentication the element
propertyMappingis placed after thegroupMappingelement in theaccessmanagerssojwtconfig.
The propertyMapping element contains one or several property elements. Each property element has a name attribute and contains either a claim or a claimPath element:
<?xml version="1.0" encoding="UTF-8"?>
…
<propertyMapping>
<property name="property1">
<claim>claim1</claim>
</property>
<property name="property2">
<claimPath>$.claim2[:].sub_claim1</claimPath>
</property>
</propertyMapping>
…
Given the following hypothetical JSON web token:
{
"sub": "user1",
"nbf": 1684829639,
"exp": 1684858439,
"mail": "user1@example.com",
"name": "User One",
"iss": "idp.example.com",
"claim1": "value1"
"claim2": [
{
"sub_claim1": "value2a.1",
"sub_claim2": "value2a.2"
},
{
"sub_claim1": "value2b.1",
"sub_claim2": "value2b.1"
}
],
"groups": [
"group1",
"group2"
]
}
With the above property mapping configuration two Cadenza properties are defined: property1 and property2. property1 is a list and contains a single value: value1. property2 is a list as well and contains two values value2a.1 and value2b.1.
Logging
For easy system analysis Cadenza logs the claims it has received in the JSON web tokens. Depending on the authentication type this can be activated by setting the logging level to trace for the following loggers:
-
OpenID Connect:
net.disy.cadenza.accessmanager.oidc.OidcUserPropertyMapper -
Plain JWT:
net.disy.cadenza.accessmanager.sso.jwt.JwtUserPropertyMapper
The logger only writes information if property mapping is active in the accessmanager config. Logger names may change without prior announcement.
|
| Logger names may change without prior announcement |
| Enabling trace-level logging will include personally-identifying information in the logs. Trace-level logging can impact performance considerably. |