Consentors

Consentors are a Curity extensibility mechanism used to perform additional processing during delegation and token issuance, including validation, information retrieval, and user interaction. Consentors are executed as a part of the authorization request for various flows (e.g., code, implicit and assisted token), after user-consent has been gathered and before the delegation or token is issued.

There are two types of consentors: generic consentors (frequently named only by consentors), and signing consentors.

Generic consentors receive the consent attributes, which are made up of the client identifier, authentication attributes, and consented scope and claims, and produce a consentor result, that is added to the created delegation. During their execution, generic consentors can also:

  • Interact with the user via multiple HTML pages and forms, for instance to gather extra information.
  • Interact with external services and data sources.
  • Terminate the flow with a non-success response, which is propagated to the client.

Signing consentors are a specialization of generic consentors, used when the goal is just to sign the consented information. They receive a text-to-display and an object-to-sign and use this information to produce a signature that is added to the resulting delegation:

  • The text-to-display is computed by a configured JavaScript procedure.
  • The object-to-sign is a JWT token, issued by a configured token issuer, which contains the consent attributes as well as the text-to-display.

Signing consentors can also involve user interaction, namely to show the information that will be signed. However this interaction is rather constrained when compared with the one available to generic consentors.

Curity already includes built-in consentors, namely BankID, however new consentors can be added as plugins.

Profile configuration

Each token profile defines the list of consentors usable on that profile. This list is configured under the consentors element, where each consentor is defined by a consentor element.

The following figure illustrates this list, present in the profile’s configuration user interface.

../../_images/profile-consentor-list.png

Fig. 153 Profile consentor list configuration.

Consentor configuration is comprised by consentor-independent information and consentor-specific information. The consentor-specific information is described in the documentation for each consentor.

The consentor-independent configuration information for generic consentors is comprised by:

  • Mandatory id with the consentor instance identifier.
  • Optional description with a consentor description for human-interface purposes.

For signing consentors, this common configuration information is extended with:

  • Optional token-issuer with the identifier for a token issuer with generic purpose.
  • Mandatory text-to-display-procedure with the definition of a JavaScript procedure.
  • Optional webservice with a definition of a web service client.
  • Optional attribute-data-source with an identifier to an existing data source.

The configured token-issuer is used to sign the JWT containing the consent attributes and the text-to-display. If no token-issuer is configured, then the profile’s default token issuer is used.

The text-to-display-procedure is used to create the text-to-display from the consented information. It must include the definition of a result function that returns this text-to-display string. This function receives a context object with:

  • The consentAttributes field with the consent attributes object, comprised by the following inner fields:
    • clientId - the client identifier string.
    • authenticationAttributes - the authentication attributes object.
    • scopes - a string array with the consented scope names.
    • claims - a string array with the consented claim names.
  • The attributeDataAccessProvider field with a data source, if the attribute-data-source configuration element is defined.
  • The getWebServiceClient() method that returns a Web Service Client, if the webservice configuration element is defined.
  • The getClient() method that returns the requesting client object.

The following code excerpt illustrates the context available to the text-to-display procedure.

Listing 215 Example text-to-display procedure.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
function result(context) {
  // Just to illustrate subject attributes usage
  var subject = context.consentAttributes.authenticationAttributes.subject.subject;
  if(subject != context.subjectAttributes().subject) {
     // Send error back to the requesting client
     throw exceptionFactory.forbiddenException("Subject mismatch");
  }
  // Just to illustrate context attributes usage
  var acr = context.consentAttributes.authenticationAttributes.context.acr;
  if(acr != context.contextAttributes().acr) throw exceptionFactory.forbiddenException("Acr mismatch");

  // Just to illustrate the attribute data source
  var attributes = context.attributeDataAccessProvider.getAttributes(subject);
  if (!attributes) throw exceptionFactory.forbiddenException("missing attributes")

  // Just to illustrate the web service client
  var response = context.getWebServiceClient().get()
  if (response.statusCode != 200) throw exceptionFactory.forbiddenException("bad response status " + response.statusCode)

  // To illustrate the client object
  var client = context.client;
  var clientName = client.name;

  var scopesAndClaims = Java.from(context.consentAttributes.claims)
    .concat(Java.from( context.consentAttributes.scopes));


  // the text-to-display
  return clientName + " requests access to: " + scopesAndClaims.join(', ');
}

Any log entries issued by the text-to-display procedure, using the logger global object, are associated with the se.curity.identityserver.scripting.textToDisplayProcedure.<consentorId> logger name, where consentorId is the consentor’s instance identifier.

The following figure illustrates the configuration for a signing consentor:

../../_images/signing-consentor-config.png

Fig. 154 Signing consentor configuration example.

  • The configuration elements above “Signing Consentor Type” are common to all signing consentors.
  • The “Signing Consentor Type” input selects the concrete signing consentor to use (bankid-signing-consentor in the example).
  • The configuration elements below “Signing Consentor Type” are specific to the concrete signing consentor being used.

Client configuration

Consentors are enabled per client when the client’s user-consent setting is enabled. By default, all the profile’s consentor instances are applicable to a client. However a client configuration can define a subset of the profile’s consentor instances that should be used.

As an example, if a profile has the consentor-1 and consentor-2 consentor instances configured, then the client behaviour will be as follows:

  • If client has user-consent disabled, then no consentor is considered.
  • If client has user-consent enabled but doesn’t specify any consentor, then both consentor-1 and consentor-2 are considered.
  • If client has user-consent enabled and defines a consentor list with consentor-1, then only consentor-1 is considered.

It is also possible to disable the built-in consent form and have only consentors run. This is achieved by enabling the only-consentors element.

The following diagram illustrate the configuration user interface for a specific client.

../../_images/client-consentor-config.png

Fig. 155 Client consentor configuration example.

In this case, the client is explicitly listing a single consentor (the-consentor-id), so only this consentor will be applicable when this client is used, independently of the consentors configured on the profile. Notice also that “Only Consentors” is disabled, meaning that both the built-in consent form and the configured consentor will be used.

A similar configuration also exists for the profile’s non-templatized dynamic clients.

Consentor selection

If more than one consentor is applicable to a given request, then a consentor selection form is presented to the user. This form is defined by the consentor-chooser.vm and consentor-chooser-single-color.vm templates, located in the templates/core/fragments. The choice between these two templates, as well as additional presentation characteristics, are defined by the settings single_color_consentor_chooser and icons_only_consentor_chooser.

The messages used by the form are located in messages/core/{lang}/views/select-consentor.

Consentor result

The result of a successful consentor execution is stored in the issued delegation and is available to procedures. The following code excerpt illustrates how this information can be obtained.

Listing 216 Consentor result usage example.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// a procedure with access to issued delegations
function result(context) {
  ...
  var issuedDelegation = ...;
  var consent = issuedDelegation.consent;
  var consentorId = consent.consentorId;
  var consentorResultAttributes = consent.consentorResultAttributes;
  var consentorSpecificInfo = consentorResultAttributes.consentorSpecificInfo.
  ...
}

The issued delegation consent field is an object with consent-related information.

  • If user consent is disabled in the client and was not forced via the prompt request parameter, then this field is absent (i.e. no user consent logic was run).
  • If a consentor was executed, this field will have the following nested fields.
    • consentorId field with the consentor identifier.
    • consentorResultAttributes field with the consentor result object. The shape of this object depends on the concrete consentor used, and is described in the consentor’s documentation. In the case of signing consentors, the consentorResultAttributes will contain an attribute of signingConsentorObjectToSign which is a JWT consisting of the data that were previously signed from the signing consentor.