Intercepting and Customising Forgerock IDM Activation Emails

The problem

We had a requirement from a customer to add dynamic properties to the activation emails and to send them through Notify.

Since Notify acts only as REST API, and not as SMTP server, we couldn’t just change IDM settings to use it.

The proposed solutions were:

  1. Implement a custom SMTP server to intercept the emails and redirect to Notify; or,
  2. Create a custom endpoint in IDM to bypass the SMTP server.

After the analysis of pros and cons we decided to go for the second option, which would avoid having an SMTP server just for the redirection.

The solution

First I created notify.groovy in {IDM_HOME}/script, which implements the endpoint:

import uk.gov.service.notify.NotificationClient;

def provisionUserParameters(userName, paramDef, paramMap){

  def query = [_queryId:'for-userName',uid:userName];
  def user = openidm.query("managed/user", query).result[0];

  def params = paramDef.split('\\|');
  params.each {

    def pair = it.split(':');
    paramMap.put(pair[0], user[pair[1]]);
  }
}

final String apiKey = System.properties['notify.api.key'];

final String templateId = request.additionalParameters.templateId;

parameters = new java.util.HashMap();
parameters.put("link", request.content.body.asString());

if (request.additionalParameters.contactLink) {
  parameters.put("contactlink", request.additionalParameters.contactLink);
}

final String userEmail = request.content.to.asString();
if (request.additionalParameters.userParameters) {
  provisionUserParameters(userEmail, request.additionalParameters.userParameters, parameters);
}

client = new NotificationClient(apiKey);
client.sendEmail(templateId, userEmail, parameters, "", "");

return {}

The function provisionUserParameters() retrieves the User’s properties specified in selfservice-reset.json under “userParameters” and add them to the parameters sent to Notify.

The apiKey and templateId are specified in the json configuration files (see selfservice-registration.json and selfservice-reset.json)

Next I created endpoint-notify.json {IDM_HOME}/conf to map the endpoint:

{
  "type" : "groovy",
  "file" : "notify.groovy",
  "context" : "endpoint/notify/*"
}

We then need to grant permission in access.js {IDM_HOME}/script to access the endpoint:

{
	"pattern"   : "endpoint/notify",
	"roles"     : "*",
	"methods"   : "action",
	"actions"   : "send",
	"customAuthz" : "(checkIfUIIsEnabled('forgotUsername') || checkIfUIIsEnabled('passwordReset') || checkIfUIIsEnabled('selfRegistration')) && isSelfServiceRequest()"
}

Finally, we need to update selfservice-registration.json and selfservice-reset.json in {IDM_HOME}/conf to use the new endpoint to send emails:

"name" : "emailValidation",
"identityEmailField" : "mail",
"emailServiceUrl" : "endpoint/notify",
"emailServiceParameters" : {
	"waitForCompletion" : false,
	"templateId" : "xxx",
	"contactLink" : "https://www.xyz.com/contact-us"
}
"name" : "emailValidation",
"identityEmailField" : "mail",
"emailServiceUrl" : "endpoint/notify",
"emailServiceParameters" : {
	"waitForCompletion" : false,
	"templateId" : "yyy",
	"userParameters" : "firstname:givenName|lastname:sn",
	"contactLink" : "https://www.xyz.com/contact-us"
}

templateId” is the identifier of the Notify template to use.

userParameters” is a map where the key is the name of a template’s parameter and the value is a property of the User’s object. These are retrieved by the script and forwarded to Notify (see provisionUserParameters in notify.groovy)

Leave a Reply

Your email address will not be published. Required fields are marked *