This section introduces scripts as a general concept in the Curity Identity Server. For details on how to write a script see the developer guide’s scripting section.
The Curity Identity Server is highly customizable on the server side. Many features can simply be configured, but many times it’s desirable to do more advanced operations. This ranges from doing custom validation of input parameters when a user authenticates or creates an account, to issuing tokens with a different structure than what’s provided by default. Even more advanced scenarios include issuing multiple tokens, or tokens from endpoints that normally don’t provide a token such as the introspection endpoint.
For this purpose the Curity Identity Server provide a configurable subsystem of procedures or scripts. Scripts are compiled at configuration time and executed efficiently on the server alongside other components as an integral part of the request pipeline, depending on the type of requests, more than one type of script may be executed.
The following types of scripts are available
For details about each type, please consult the Scripting Guide.
For reference documentation about the context for each type of script, see Common Procedure Objects.
context
Tip
Scripts are written in JavaScript and it’s recommended to convert the entire script into a base64 encoded string before setting it in the configuration, to avoid having to xml encode individual characters.
Authentication can be done in many ways, but there are typically two main requests that are interesting to look at from a script perspective.
For how to filter the listing of authentication methods, see authentication filters.
When posting credentials to the authentication service, the following pipeline is executed:
Fig. 33 Processing of authentication request
There are many things going on during authentication and most steps are configurable in different ways. As the illustration shows, one of the first things that takes place is input validation. There are always built in validations that will execute, but sometimes more validation is desired. A good example of that could be to validate the format if a phone number, or a social security number etc. To do this a procedure can be added on that endpoint to validate the input data.
1 2 3 4 5 6 7 8 9 10 11
function result(object) { var errors = {}; var phoneRegex = /^\+\d{2}\d+$/; var matches = phoneRegex.exec(object.phoneNumber) if (!matches) { errors.phonenumber = "error.validation.invalid.phonenumber"; } return errors; }
More on validation procedures and how to write those can be found in the validation procedure section in the developer guide.
After the input validation has taken place, the pipeline continues and before the SSO session is created a step of name and attribute transformation is executed. Here one or many transformers will add, update and remove data on the authenticated object. This is the second place where the admin can choose to execute a script.
1 2 3 4
function result(attributes) { attributes.subject = attributes.subject + "@phonenumber"; return attributes; }
The above examples illustrate how authentication using phone number as username can be validated with custom validation before processed, and before the session is created, the username was transformed into a string containing @phonenumber as a marker appended to the username.
@phonenumber
In the same way as procedures are used during the authentication processing, procedures are used in token issuance and processing in the Security Token Server.
During authentication procedures are optional and used for additional functionality, but during token issuance they become a key component.
Fig. 34 Token generation example
In the common cases the factory default scripts provided with the Curity installation will be enough. But when updates are needed, these can be used as a base for updates and it’s recommended to keep them as is and add other scripts alongside with the default ones. The factory default scripts are found at $IDSVR_HOME/etc/init in the named subfolders.
$IDSVR_HOME/etc/init
Factory default procedures are located in $IDSVR_HOME/etc/init under named folders, see the configuration section for details on how to use this.
Scripts are configured in the processing section of the configuration schema. There all procedures are defined and then later referenced by the subsystem configuration that needs it.
The following types and subtypes of scripts are possible to configure:
filter-procedure
Filter procedures perform filtering operation on data. The currently only supported type of filters is authenticator filters. See here for configuration reference.
authenticator
Filter procedure for authenticator selection.
These are used to filter which authenticators are displayed when a user starts authentication. For more about authentication filtering see the authenticator filtering guide.
See the filter procedure configuration reference for more details on the parameters available.
global-script
Global JavaScript functions and libraries can be placed here. All global scripts are made available to any other script before compilation. Commonly these are used to created reusable functions, or to include libraries such as underscore.js etc. Global scripts are not sub-typed.
token-procedure
Token Procedures are the most prominent scripts. They are invoked on calls to the various token processing and generating endpoints. Each endpoint-kind will provide its own context to the procedure, and will expect a result object of a certain type. To distinguish between these types, each token procedure is typed with an :endpoint-types marker which is the same marker that is used when configuring endpoints. For details on parameters when configuring token-procedures see the configuration reference.
endpoint-types
oauth-assisted-token
The oauth-assisted-token type marks the script compatible with the OAuth assisted token endpoint.
oauth-authorize
The oauth-authorize type marks the script compatible with the OAuth authorize endpoint. This endpoint is responsible for the OAuth Implicit flow and the OAuth Code flow, as well as the OpenID Connect companion flows.
oauth-introspect
The oauth-introspect type marks the script compatible with the ref:OAuth introspection endpoint<oauth_endpoints_introspect>. This script is different from the other in the sense that most of the times it does not issue tokens, but merely produce the result of the introspection as json content. However, a common pattern is to issue internal tokens from the introspect endpoint, which is possibly by updating these procedures.
oauth-token
The oauth-token type marks the script compatible with the OAuth token endpoint. This endpoint is responsible for the OAuth client credentials flow, Resource owner password credentials flow, refresh token flow and the token call of the code flow, as well as the OpenID Connect companion flows.
transformation-procedure
Transformation Procedures are used to transform attributes. The commonly used place is within an attribute transformer configured on an authenticator. Transformation procedures are not sub-typed.
validation-procedure
Validation procedures are used in the Curity Authentication Server for input validation. When custom requirements are needed for input validation, such as certain password rules during creation of passwords, or formats of emails or phone numbers, these procedures can be used to implement these more advanced or custom scenarios.
request
The only type of validation procedure available is the request type.
event-listener-procedure
EventListener procedures are used to handle Server Events.
It is recommended to base64 (RFC 4648) encode the script before setting it in the configuration. However as a shortcut to avoid this step, especially in development environments scripts can be provided as JavaScript source code files placed in the $IDSVR_HOME/etc/init folder in the appropriate sub-directory.
There are 5 sub-folders under $IDSVR_HOME/etc/init that are used for the source files. Each folder may contain subfolders for the sub-type of the script. The structure looks as follows with the default files in place:
├── filter-procedures │ └── authenticator ├── global-scripts ├── token-procedures │ ├── oauth-assisted-token │ ├── oauth-authorize │ ├── oauth-introspect │ └── oauth-token ├── transformation-procedures └── validation-procedures └── request
Note
Each file will be parsed and converted into a base64 encoded (RFC 4648) configuration setting with the name of the file as the id and the folder and sub-folder as type and subtype.
id
$ ${IDSVR_HOME}/bin/idsvr --reload
Using --reload causes the server to merge the existing configuration with the files in $IDSVR_HOME/etc/init. If a complete replace is needed instead, then --force-reload can be used.
--reload
--force-reload
This example sets a new validation procedure that can be used during registration of new accounts to validate that the License agreement has been accepted before allowing the registration to continue.
Create a new file in $IDSVR_HOME/etc/init/validation-procedures/request named my-validator.js
$IDSVR_HOME/etc/init/validation-procedures/request
my-validator.js
Edit the file in any editor and add the following content
Listing 88 Example of validation procedure¶ function result(object) { var errors = {}; var acceptTerms = object.request.getFormParameter("agreeToTerms"); if (acceptTerms !== 'on') { errors.acceptTerms = "error.validation.terms"; } return errors; }
function result(object) { var errors = {}; var acceptTerms = object.request.getFormParameter("agreeToTerms"); if (acceptTerms !== 'on') { errors.acceptTerms = "error.validation.terms"; } return errors; }
Update the running configuration
Now a new configuration entry has been added to the running configuration with the following format:
<validation-procedure> <id>my-validator</id> <script>ZnVuY3Rpb24gcmVzdWx0KG9iamVjdCkgewoJCQl2YXIgZXJyb3JzID0ge307CgoJCQl2 YXIgYWNjZXB0VGVybXMgPSBvYmplY3QucmVxdWVzdC5nZXRGb3JtUGFyYW1ldGVyKCJhZ3JlZVRv VGVybXMiKTsKCiAgICBpZiAoYWNjZXB0VGVybXMgIT09ICdvbicpIHsKCWVycm9ycy5hY2NlcHRU ZXJtcyA9ICJlcnJvci52YWxpZGF0aW9uLnRlcm1zIjsKICAgIH0KICAgIAogICAgcmV0dXJuIGVy cm9yczsKfQo=</script> <type>request</type> </validation-procedure>
The procedure has been encoded into base64 and a new entry with the id of the filename has been created. This entry can now be referenced from other parts of the system where validation procedures are used.
The developer guide contains examples and instructions on how to implement these scripts.