This section describes the common API available to all procedures in Curity.
For a full reference, check the Procedures API Documentation.
This API can effectively be extended by the use of Global Scripts because, as the common API, global scripts are also available to all procedures.
The following objects are available to all procedures:
They are global variables, hence can be accessed easily anywhere. Example usages are shown later on in this document.
Many more objects are exposed via the context object, explained in the next section.
context
All Javascript procedures in Curity also receive a context object (as an argument to their result function) which gives them access to data and functionality they may need to perform their task.
result
The type of each context object depends on the kind of procedure.
The following tables associate each kind of procedure to its context type:
Token procedure context types are shown separately below as they may have different types depending on whether OpenID Connect is enabled:
The base class of all context types is ProcedureContext.
The following section shows some common utility objects that may be available to different procedures via the context object. Check each procedure type documentation for a comprehensive list of which objects are available for each type of procedure.
Note
global scripts cannot make use of these objects unless they receive the context from a procedure as a function argument.
The logger object is an instance of SLF4J Logger. Usage from JavaScript is as from Java.
Example usage:
Listing 260 Using the logger object¶ 1 2 3 logger.debug("Format message: {}", parameter) logger.warn("Something about {} went wrong: {}", parameter, error)
logger
1 2 3
logger.debug("Format message: {}", parameter) logger.warn("Something about {} went wrong: {}", parameter, error)
To set cookies, use the response object (of type ScriptResponse), accessible from most context types.
response
Listing 261 setEncryptedCookie example¶ 1 2 3 4 5 6 7 8 9 10function result(context) { ... var settings = { "maxAge" : 3600, "persist": true, "path" : "/authn" }; context.response.setEncryptedCookie("myCookie", "someValue", settings); }
1 2 3 4 5 6 7 8 9 10
function result(context) { ... var settings = { "maxAge" : 3600, "persist": true, "path" : "/authn" }; context.response.setEncryptedCookie("myCookie", "someValue", settings); }
Curity’s Data Sources are accessible from most context objects.
Listing 262 Attributes as Table¶ 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 26var subjectMap = {"subject": context.subject}; var attributes = dataStore.getAttributes(subjectMap); var dataRows = attributes.allRows.iterator(); var attributeClaims = {}; while (dataRows.hasNext()) { // row is a Map var row = dataRows.next(); if (row.containsKey("linked_account_id") && row.containsKey("linked_account_domain_name")) { console.log("Attributes found and contain linked account"); // se.curity.identityserver.data.attribute.Attribute var linkedAccountId = row["linked_account_id"]; var linkedAccountDomainName = row["linked_account_domain_name"]; attribute_data["linked_accounts"].push({ "id": linkedAccountId, "domain": linkedAccountDomainName }); } else { console.log("Attributes do not contain linked account: " + attributes); } }
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
var subjectMap = {"subject": context.subject}; var attributes = dataStore.getAttributes(subjectMap); var dataRows = attributes.allRows.iterator(); var attributeClaims = {}; while (dataRows.hasNext()) { // row is a Map var row = dataRows.next(); if (row.containsKey("linked_account_id") && row.containsKey("linked_account_domain_name")) { console.log("Attributes found and contain linked account"); // se.curity.identityserver.data.attribute.Attribute var linkedAccountId = row["linked_account_id"]; var linkedAccountDomainName = row["linked_account_domain_name"]; attribute_data["linked_accounts"].push({ "id": linkedAccountId, "domain": linkedAccountDomainName }); } else { console.log("Attributes do not contain linked account: " + attributes); } }
Prefer to use errors created by using the exceptionFactory object, as JavaScript errors have no significance in Curity, hence will always result in 500 (Server Error) responses, which may not always be desired.
500
Listing 263 ExceptionFactory example¶ 1 2 3 4 5 6function result(context) { ... //Respond with 400 Bad request throw exceptionFactory.badRequestException("your message here"); ... }
1 2 3 4 5 6
function result(context) { ... //Respond with 400 Bad request throw exceptionFactory.badRequestException("your message here"); ... }
The json object, present in all context objects, can be used to (de)serialize any object, including Java and JS objects, unlike JavaScript’s JSON object, which can only handle JS objects.
JSON
Listing 264 context.json usage¶ 1 2 3 4 5 6 7 8 // serialize JS object var jsonString = context.json.toJson({ data: "example", headers: { "Accept": "application/json" } }); // de-serializing an object from a JSON string var data = context.json.fromJson(jsonString);
1 2 3 4 5 6 7 8
// serialize JS object var jsonString = context.json.toJson({ data: "example", headers: { "Accept": "application/json" } }); // de-serializing an object from a JSON string var data = context.json.fromJson(jsonString);
Many types of context include a ScriptWebServiceClient to make HTTP requests.
This is a configurable object which is normally configured together with the procedure itself.
Listing 265 WebServiceClient usage¶ 1 2 3 4 5 6 7 8 9 10 11 12 var response = context.webServiceClient.get({ path: "/some/resource", headers: { "Accept": "application/json" }, query: { type: "thing", filter: ["value > 10", "account_id == 'joe'"] } }); if (response.statusCode == 200) { // success logger.debug(response.body); } else { logger.warn("Something wrong"); }
1 2 3 4 5 6 7 8 9 10 11 12
var response = context.webServiceClient.get({ path: "/some/resource", headers: { "Accept": "application/json" }, query: { type: "thing", filter: ["value > 10", "account_id == 'joe'"] } }); if (response.statusCode == 200) { // success logger.debug(response.body); } else { logger.warn("Something wrong"); }
Curity allows procedures to store information inside a user session, making it easy to maintain state related to a particular user flow.
This is accomplished via the ScriptSessionManager object.
Example usage: Listing 266 SessionManager example¶ 1 2 3 4 5 6function result(context) { ... context.sessionManager.put("SomeKey", "SomeValue"); ... var mySavedValue = context.sessionManager.get("SomeKey"); // mySavedValue = "SomeValue" }
function result(context) { ... context.sessionManager.put("SomeKey", "SomeValue"); ... var mySavedValue = context.sessionManager.get("SomeKey"); // mySavedValue = "SomeValue" }
To issue a token in a token procedure, even though the details depend on what kind of token is being issued, the pattern is normally illustrated by the example below:
Listing 267 Issuing an access token¶ 1 2 3 4 5 6 7 8 9 10 11 12 13 14function result(context) { var delegationData = context.getDefaultDelegationData(); var issuedDelegation = context.delegationIssuer.issue(delegationData); var accessTokenData = context.getDefaultAccessTokenData(); var accessToken = context.accessTokenIssuer.issue(accessTokenData, issuedDelegation); return { scope: accessTokenData.scope, access_token: accessToken, token_type: 'bearer', expires_in: secondsUntil(accessTokenData.exp) }; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14
function result(context) { var delegationData = context.getDefaultDelegationData(); var issuedDelegation = context.delegationIssuer.issue(delegationData); var accessTokenData = context.getDefaultAccessTokenData(); var accessToken = context.accessTokenIssuer.issue(accessTokenData, issuedDelegation); return { scope: accessTokenData.scope, access_token: accessToken, token_type: 'bearer', expires_in: secondsUntil(accessTokenData.exp) }; }
Many other examples are available at Token Procedure Examples.
Footnotes