ScriptingΒΆ
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.
Introduction to scriptsΒΆ
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
- Token Procedures - Used when issuing tokens
- Validation Procedures - Used when validating incoming form data
- Transformation Procedures - Used when transforming data such as usernames
- Filter Procedures - Used when filtering data such as which authenticator to select
- EventListener Procedures - Used to react to Server Events
- Global Scripts - - Provides global functions that become available in all procedures
- Pre-processing Procedures - Used to customize input request before processing the same
- Post-processing Procedures - Used to customize output after processing
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.
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.
Procedures during authenticationΒΆ
Authentication can be done in many ways, but there are typically two main requests that are interesting to look at from a script perspective.
- Displaying a list of authentication methods
- Posting the credentials to the authentication or registration endpoint from a webform
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.
Procedures during token issuance and processingΒΆ
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.
Tip
Factory default procedures are located in $IDSVR_HOME/etc/init
under named folders, see the configuration section for details on how to use this.
Configuring ScriptsΒΆ
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.
Script TypesΒΆ
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.-
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.
PreparationsΒΆ
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.
Configuring using etc/initΒΆ
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.
Create a new scriptΒΆ
- Add a new .js file in the appropriate location
- Update the running configuration of the server
$ ${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.
Example adding script using etc/initΒΆ
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
namedmy-validator.js
Edit the file in any editor and add the following content
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
$ ${IDSVR_HOME}/bin/idsvr --reload
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.
Writing ScriptsΒΆ
The developer guide contains examples and instructions on how to implement these scripts.