Common Procedure API#

This section describes the common API available to all procedures in the Curity Identity Server.

Most script procedures must define a result function that receives a context object and returns a result. These result functions use both the context object as well as global objects and functions to perform their task.

For a full reference, check the Procedures API Documentation

Global Objects#

The following objects are always available to all procedures:

The set of global objects can effectively be extended by the use of Global Scripts because global scripts are also available to all procedures.

Many more objects are exposed via the context object, as explained in the next section.

Procedure Context object#

The type of each context object depends on the script procedure type.

The following tables associate each script procedure type to its context type.

Script Procedure TypeContext type
validation-procedureValidationProcedureContext
claims-provider-procedureClaimsProviderProcedureContext
transformation-procedureTransformationProcedureContext
credential-transformation-procedureCredentialTransformationProcedureContext
filter-procedureAuthenticatorFilterProcedureContext
event-listener-procedureEventListenerProcedureContext
signing-consentor-display-textSigningConsentorDisplayTextProcedureContext
pre-processing-procedureDcrPreProcessingProcedureContext
post-processing-procedureDcrPostProcessingProcedureContext

Token procedure context subtypes are shown separately below as they may have different types depending on whether OpenID Connect is enabled.

Script Procedure SubtypeContext type (OAuth)Context type (OpenID Connect)
oauth-assisted-tokenAssistedTokenProcedureContextAssistedTokenProcedureContext
oauth-authorize-authorization-codeAuthorizeTokenProcedureContextOpenIdConnectAuthorizeTokenProcedureContext
oauth-authorize-implicitAuthorizeTokenProcedureContextOpenIdConnectAuthorizeTokenProcedureContext
oauth-device-authorizationDeviceAuthorizationTokenProcedureContextDeviceAuthorizationTokenProcedureContext
oauth-introspectIntrospectionTokenProcedureContextIntrospectionTokenProcedureContext
oauth-introspect-application-jwtIntrospectionTokenProcedureContextIntrospectionTokenProcedureContext
oauth-token-assertionAssertionTokenProcedureContextAssertionTokenProcedureContext
oauth-token-authorization-codeAuthorizationCodeTokenProcedureContextOpenIdConnectAuthorizationCodeTokenProcedureContext
oauth-token-pre-authorized-codePreAuthorizedCodeTokenProcedureContext1N/A
oauth-token-backchannel-authenticationBackchannelAuthenticationTokenProcedureContextBackchannelAuthenticationTokenProcedureContext
oauth-token-client-credentialsClientCredentialsTokenProcedureContextClientCredentialsTokenProcedureContext
oauth-token-device-codeDeviceCodeTokenProcedureContextOpenIdConnectDeviceCodeTokenProcedureContext
oauth-token-refreshRefreshTokenProcedureContextRefreshTokenProcedureContext
oauth-token-resource-owner-password-credentialsPasswordTokenProcedureContextPasswordTokenProcedureContext
oauth-token-token-exchangeTokenExchangeProcedureContextTokenExchangeProcedureContext
openid-authorize-hybridAuthorizeTokenProcedureContextOpenIdConnectAuthorizeTokenProcedureContext
openid-userinfoN/AOpenIdConnectUserinfoTokenProcedureContext

The base class of all context types is ProcedureContext.

The following examples 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.

Global scripts cannot make use of these objects unless they receive the context from a procedure as a function argument.

Examples#

The following sections present some examples using both the global objects and the context object.

Logging#

logger.debug("Printing claims");

for(key in context.optionalClaims.claims) {
    logger.debug("Claim: {}={}", key, context.optionalClaims.claims[key]);
}

This will log to the server.log (or stdout if not running as a service) with the script name as part of the class name.

2016-08-27 08:14:28 DEBUG  {qtp1444635117-75} se.curity.identityserver.scripting.token_procedure.my-token-procedure:58 Printing claims
...

The Logger methods trace, debug, info, warn and error are available. The line number is also presented in the output.

In addition to the logger object, the perhaps more familiar console.log may also be used, which is equivalent of using logger.debug.

Exceptions#

To abort the procedure and report an error, an exceptionFactory object is available on all procedures.

The following example will result in an error response with the appropriate HTTP status code being reported back to the HTTP client.

throw exceptionFactory.unauthorizedException("The user is not authorized to perform this action")

If you want your message to be visible in the server’s response you would need to enable expose-detailed-error-messages

To set cookies, use the response object (of type ScriptResponse), accessible from most context types.

function result(context) {
  ...
  var settings = {
    "maxAge" : 3600,
    "persist": true,
    "path" : "/authn"
  };

  context.response.setEncryptedCookie("myCookie", "someValue", settings);
}

Using a Data Store#

data sources are accessible from most context objects.

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);
    }
}

Serializing and De-Serializing JSON#

The Json object, present in all context objects, can be used to serialize and deserialize any object, including Java and JS objects, unlike JavaScript’s JSON object, which can only handle JS objects.

Example usage:

// 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);

Sending HTTP Requests#

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.

Example usage:

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");
}

Storing Data Into a Session#

The Curity Identity Server 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:

function result(context) {
  ...
  context.sessionManager.put("SomeKey", "SomeValue");
  ...
  var mySavedValue = context.sessionManager.get("SomeKey"); // mySavedValue = "SomeValue"
}

Issuing a Token#

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:

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#

  1. The support for the pre-authorized code flow is experimental. See Pre-authorized Code Flow related documentation for more information.

Was this helpful?