Goal

UserSync 2.1/2.2 supports syncing any IdP attributes into Communardo User Profiles fields. This tutorial will show how to configure this.



Requirements

  • UserSync 2.1.x/SAML 5.1.x for Confluence or UserSync 2.2.x/SAML SSO 5.2.x for Jira
  • Communardo User Profiles for Jira, Communardo User Profiles for Confluence
  • Configured fields in the User Profiles app


Steps


  1. Go to UserSync and click Edit for your UserSync connector.



  2. Go to Provisioning Settings and scroll down to the Attribute Mapping table.



  3. Click New Mapping and select the User Profiles field you want to map. You may have to scroll down in the popup to find it.



  4. Select which attribute from the IdP should be the data source. You can also do any transformation.



  5. Click Apply to close the modal. You can see the new mapping in the table.





  6. Click Save and Return to finish the configuration.




Manager

If you want to sync manager attributes, you will need to use a Groovy code to achieve it. Since the manager field has the type userField (and not just a text field), it uses the userKey to identify a user.

Please edit the Manager attribute in the User Sync connector settings:

edit_attribute_manager

Choose Groovy as a Source Type:

source_type

Enter the following Groovy code and Apply the changes.

findUserKeyByUsername(con?.manager?.userPrincipalName) ?: ""
GROOVY

Now, the Manager Attribute will be displayed in the public profile.

manager_visible

Please note that:

  1. The manager user needs to be existing in your Atlassian instance already. If the manager user doesn’t exist, the manager field will not be updated for the employee. Also, if the manager user was synced after the employee user in the full sync, and that was a newly created user in your IdP (e.g. Azure), then the manager field wouldn’t be updated for the employee in that execution of full sync, but it would appear in the following one (since the manager user would have been synced already this time).

  2. In the above Groovy code, you need to use the manager attribute that matches the manager username in your Atlassian instance. In our example, the usernames are mapped to the UserPrincipialName.

Result

After syncing users, you can see the field in the user profile

Map Select or Multi-Select fields

Values can be mapped to select or multi-select fields. In this case, the value must be translated to one (or more in case of a multi-select) existing option-ids.

Find the Option IDs

Currently, the option ids are not visible directly. To find out the ID of a value, edit the element to have the dialog open, right-click into the page and select "inspect" (this works in Firefox, may be different in other browsers). This opens the inspector-pane.

For each option, there is a hidden input field. The value-attribute of this field is what we're looking for.

Map data to the Option ID

To map data to an option field, create a Groovy-transformation that maps the data to the appropriate option.

There are many ways to do this, these examples use map-lookups for that:

Single Select

For as single select, return the ID as a single value. This example assumes that the connector-data contains a field "language" with the either "de", "en" or "es" which have to be mapped to the numeric values.

If there is another value coming, the lookup will return null so the field is cleared.

def optionMap = [ 
    "de" : 1,
	"en":  2,
    "es" : 3 
    ]
    
return optionMap[con.language]
GROOVY

Multi Select

For a multi-select, return a list of IDs representing the selected options. This example assumes that the connector-data contains a filed "plangs" with an array of identifiers like "java", "groovy" or "kotlin".

This code translates each of this identifier to the option id looking up in the optionMap. Identifiers not included in the map will produce null-values that needs to be filtered before returning the result.

// Use this to map the values
// from the IdP to the ids of the Communardo-options
def optionMap = [
    "java" :   4, 
    "groovy" : 5,
    "kotlin" : 6 ,
    "js"     : 7
    ]
    
return con.plangs?.collect{ optionMap[it]} // lookup the option map
    ?.findAll{it != null}                  // filter null-values
GROOVY



Known Issues

Problem

When reinstalling the User Profiles app, the SAML SSO/User Sync app crashes with the following stack trace in the Atlassian log file:


2021-10-18 07:45:08,368 ERROR [http-nio-8080-exec-9] [common.error.jersey.ThrowableExceptionMapper] toResponse Uncaught exception thrown by REST service: de/communardo/atlassian/plugins/userprofile/external/api/service/UppProfileElementDataManager
 -- referer: https://.../plugins/servlet/samlsso/usersync | url: /rest/samlsso-admin/1.0/reconfigure/frontenddto/usersync | traceId: b793c7ddef9a0611 | userName: admin
java.lang.NoClassDefFoundError: de/communardo/atlassian/plugins/userprofile/external/api/service/UppProfileElementDataManager
	at de.resolution.atlasuser.impl.user.communardo.CommunardoUserProfileAdapterImpl.<init>(CommunardoUserProfileAdapterImpl.java:39)
	at de.resolution.atlasuser.impl.user.communardo.DelegatingCommunardoProfileAdapter.updateDelegate(DelegatingCommunardoProfileAdapter.java:51)
	at de.resolution.atlasuser.impl.user.communardo.DelegatingCommunardoProfileAdapter.getAvailableAttributes(DelegatingCommunardoProfileAdapter.java:71)
	at de.resolution.retransform.frontend.AttributeMappingUtils.createCommunardoAttributeOptions(AttributeMappingUtils.java:86)
	at de.resolution.retransform.frontend.ConfluenceAttributeMappingOptionProvider.getSpecificOptions(ConfluenceAttributeMappingOptionProvider.java:24)
	at de.resolution.retransform.frontend.AbstractAttributeMappingOptionProvider.getOptions(AbstractAttributeMappingOptionProvider.java:17)
	at com.resolution.atlasplugins.samlsso.configuration.frontend.SamlSsoConfigurationService.getFrontendDTO(SamlSsoConfigurationService.java:186)
CODE

Solution

To fix this issue, reinstall SAML SSO/User Sync too or restart the instance. Afterward, the UI will load again. We will address the UI crashing with an upcoming update. However, you will still need to reinstall the app or restart the instance.