Template page scripting

You can use JavaScript to add server-side scripting for Advanced Access Control and Federation template pages. You can use JavaScript functions, closures, objects, and delegations.

Usage

You can customize template files or pages on the server. For example, you can customize an error message that is displayed by the runtime server.

The template files menu is located under both the Federation and AAC menus.

To edit a Federation template file, go Federation > Template Files, select the specific template file, and click Edit.

To edit an AAC template file, go to AAC > Template Files, select the specific template file, and click Edit.

The JavaScript engine supports the following syntax:

  • Insert JavaScript code between <% and %>.
  • Embed JavaScript expressions between <%= and %>.

Example tasks

  • Access whitelisted Java classes. For example,
    var javaStr = new java.lang.String("Hello")
  • Access all the macro variables through templateContext. The standard object to access a Java object is templateContext. For example,
    templateContext.macros["@TIMESTAMP@"]
  • Use the document.write function to write content to the output stream. For example,
    templateContext.response.body.write("Hello")

Examples

Table 1. Example JavaScript
Template HTML Output
<%
var contents = {product:"Verify Access",department:"Lab",country:"SG",region:"Asia"};
templateContext.response.body.write(contents.product); 
%>
Verify Access
<%
var date = templateContext.macros["@TIMESTAMP@"].substring(0, 10);
templateContext.response.body.write(date);
%>
2017-01-25

The following code example shows how to use repeatable macros. The following example shows an OAuth consent page.

<%
var test = templateContext.macros["oauthTokenScopeNewApprovalRepeatable"];
n = test.length;
for (i=0; i<n; i++){
		var scope = test[i]["@OAUTH_TOKEN_SCOPE_REPEAT@"];
		if (scope == "contacts"){
			label ="Do you grant permission to the client to access your phone book";
		}
		else if (scope == "photos"){
			label ="Do you grant permission to the client to access your photos";
		}
		else if (scope == "messages"){
			label ="Do you grant permission to the client to access your WhatsApp messages";
		}
		else{
			label ="Do you grant permission to the client to access your "+scope;
		}
%>

Setting an HTTP response header

You can use templateContext.response.setHeader(HeaderName, HeaderValue) to set an HTTP response header.

For example, you can set the Content-Type to support both a mobile-based browser and a traditional browser. A mobile-based browser might expect JSON format while a traditional browser expects forms-based HTML.

 <%
templateContext.response.setHeader("Content-Type","application/json");
var myObj = { "name":"John", "age":31, "city":"New York" };
templateContext.response.body.write(JSON.stringify(myObj));
%>

To set an HTTP header that uses forms-based HTML:

templateContext.response.setHeader("Content-Type","text/html");

Setting an HTTP status code

You can use templateContext.response.setStatus(Code) to set an HTTP response status code.

For example, if you want to set the status to 400 (standard code for a bad request):

templateContext.response.setStatus(400);

Setting a Redirect URL

You can use templateContext.response.sendRedirect(URL) to redirect the HTTP response to a different URL.

For example, when you configure single logout, you can redirect the response to a specific target page, based on the federation name. An example scenario is a deployment that has one SAML 2.0 federation with two partner federations. The partner federations are named saml20app2 and saml20sp. The saml20app2 federation uses an application that is named jkebank. The saml20sp federation uses an application that is named jkeschool. The page to display on logout is determined by the federation name.

var fedName = templateContext.macros[@FEDERATION_NAME@"];
if (fedName == "saml20app2")
{
    templateContext.response.sendRedirect("http://jkebank:1337");
}
else if 
{
(fedName == "saml20sp")
{
    templateContext.response.sendRedirect("http://jkeschool:1400");
}

Obtaining a list of macros that are available for a template page

In some scenarios, you might want to write JavaScript based on configuration values in your deployment. For example, you might implement one action based on the authentication type, such as if the OTP type is TOTP. Another example is you might implement an action if the Federation name of the single sign-on partner matches a certain value.

Information such as the OTP type and partner name can be retrieved only through the template page macros. To use such information, you need to know which macros are used by the page. The JavaScript engine support provides a utility that can print the available macros for a page.

Use the following syntax to obtain a list of the available macros.

<% templateContext.response.body.write(JSON.stringify(templateContext.macros)); %>

For example, the following sample code prints the macros from a template page that ran a single sign-on flow with a partner that does not exist.

{

    "@PAGE_IDENTIFIER@": "/saml20/invalid_init_msg.html",
    "@TARGET@": "https://www.mysp.ibm.com/isam/mobile-demo/diag",
    "@PARTNER_ENTITY_ID@": "",
    "@ERROR_MESSAGE@": "FBTSML002E The value https://saml.partner.com for attribute PartnerId is not valid.",
    "@FEDERATION_NAME@": "saml20idp",
    "@FEDERATION_ENTITY_ID@": "https://www.myidp.ibm.com/isam/sps/saml20idp/saml20",
    "@REQ_ADDR@": "/sps/saml20idp/saml20/logininitial",
    "@ERROR_CODE@": "FBTSML002E",
    "@EXCEPTION_STACK@": "",
    "@PARTNER_NAME@": "",
    "@TIMESTAMP@": "2017-06-22T03:34:39Z",
    "@SAMLSTATUS@": "<fim:FIMStatusCollection xmlns:fim=\"urn:ibm:names:ITFIM:saml\" 
     xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\"><fim:FIMStatusCollectionEntry>
     <samlp:Status><samlp:StatusCode Value=\"urn:oasis:names:tc:SAML:2.0:status:Responder\"></samlp:StatusCode>
     <samlp:StatusDetail><fim:FIMStatusDetail MessageID=\"invalid_attribute_value\">
     <fim:SubstitutionString>https://saml.salesforce.com</fim:SubstitutionString>
     <fim:SubstitutionString>PartnerId</fim:SubstitutionString></fim:FIMStatusDetail>
     </samlp:StatusDetail></samlp:Status></fim:FIMStatusCollectionEntry></fim:FIMStatusCollection>",
    "@EXCEPTION_MSG@": ""

}

The format is JSON { "name1":"value1","name2":"value2"}

Limitations

  • JavaScript validation is done only when a template file is edited (imported) or created. A template file that is imported as a part of an Import compressed file is not validated.
  • You must restart the runtime manually to activate changes to OpenID Connect template files. In the administrative interface, click Federation -> Runtime Tuning -> Restart Runtime.
  • When you access a variable, do not end the variable name with a semicolon. For example, in the following JavaScript, do not end <%=example%> with a semicolon <%=example;%>.
    <%var example = "Hello World"; %> 
    <%=example%>
    The correct syntax is <%=example%>. Do not use the incorrect syntax <%=example;%>.