Content only available in english
Custom User Provisioning Logic with Groovy
AuthM supports custom Groovy scripts that allow dynamic determination of user attributes and group memberships during the authentication process. This provides fine-grained control over user provisioning and group assignment based on identity provider (IdP) data.
Purpose
Custom provisioning logic is especially useful when:
- The identity provider (IdP) returns user claims that need to be transformed or mapped.
- Users and groups should be auto-created or updated during login.
- You want to enforce specific rules or filters before finalizing authentication.
Configuration Requirements
To enable and use a custom Groovy provisioning script:
- Place the script file under the directory specified by the property:
groovy-scripts-directory=<absolute_path_to_scripts_folder>- Set the script path in the AuthM configuration file:
...
openid.configs[x].post-authentication-script=<script_name>.groovy
or
...
saml2.configs[x].post-authentication-script=<script_name>.groovyScript Environment
When your Groovy script executes, the following global variables are available:
| Variable | Description |
|---|---|
log | A logger instance for logging within the script. |
idpType | The IdP type of authentication: OpenId or Saml2 |
externalUsername | The external username retrieved from the IdP |
attributes | A map of all claims (attributes) returned from the IdP. |
user | A User object representing the existing user (if already present in the system). If the user does not exist yet, this will be null. |
Return Format
The script must return a Map containing the following optional keys:
| Key | Type | Description |
|---|---|---|
User | Map | A map with the user data to be created or updated. |
Groups | List<String> | A list of groups that the user should be assigned to. |
Example:
groovy
return [
User: [
username: attributes.email,
email: attributes.email,
fullName: attributes.name
],
Groups: ['default-users', 'admins']
]Auto-Provisioning & Group Mapping
- If the user does not exist (user == null), the User map will be used to create the user.
- If the user exists, the User map will be used to update the user.
- Any groups listed in the Groups list will be created (if needed) and assigned to the user.
INFO
- Group assignment is handled automatically.
- Returning null or an empty map will skip user and group provisioning but allow authentication to continue (if permitted).
WARNING
Be cautious with logic that depends on claim availability — always check for nulls.
Examples:
Creating/updating a user after a successful authentication
groovy
// log.info("user attributes {{ attributes: ${attributes} }}")
//
// attributes: [
// primaryPhone:[+000 000 000 000],
// firstName:[John],
// lastName:[Doe],
// displayName:[john Doe],
// notOnOrAfter:2025-05-28T09:19:31.577Z,
// email:john.doe@cob.pt,
// notBefore:2025-05-28T09:09:31.577Z],
// roles: [admin]
// }}
def contact = attributes["primaryPhone"]?.get(0)
contact = contact != null ? contact.replaceAll(" ", "") : null
def user = [
name : attributes["displayName"][0],
email : attributes["email"],
contact : contact,
externalUsername: externalUsername
]
// Keep existing groups that are part of the CoB Platform
def finalGroups = user?.groups.findAll { it -> it == "System" } ?: []
// Add roles returned from IDP as user groups
attributes.roles.each {it -> finalGroups << "FUNC ${IT}" }
return [user: user, groups: finalGroups]