LTPA Tokens

contendsCeptor support authenticating users using LTPA Tokens, and can also issue new LTPA Tokens to use as cookies to backend servers, thus enabling easy SSO with IBM products.

LTPA is short for Lightweight Third-Party Authentication - see more information here: https://en.wikipedia.org/wiki/IBM_Lightweight_Third-Party_Authentication 
Ceptor supports the most secure variant, LTPA2 signed by RSA keys and encrypted using AES encryption.

Configuration of LTPA Authentication Plugin

No matter if you need to issue new LTPA Tokens to others, or authenticate using tokens obtained elsewhere, you need to configure the LTPA Authentication plugin.

Enable it by adding the string dk.itp.security.authentication.ltpa.LTPAAuthenticationPlugin to the list of authentication plugin in the property server.authenticationplugins the Ceptor Session Controller.


You will also need to configure it, it supports the following configuration properties:

NameValueDescription
ltpa.tokensList of token names,
separated by comma or semicolon
List of token names to load - allows you to specify multiple different tokens which each use their own set of keys
ltpa.token.default.nameString

Name of token that will be used as default, if nothing else is indicated in the call.

Note that if only one token is configured, that token name will be used as default so in that case this does not need to be specified.

For the following <tokenname> is replaced with the name of the token
ltpa.token.<tokenname>.authenticate

true/false
Default: false

Set to true if authentication is allowed with this token - if false, LTPA tokens can be created for this, but authentication using such a token is not allowed. 
ltpa.token.<tokenname>.filenameString containing filename, macros
are allowed.

Specify a filename to load properties from - if not specified, ltpa.token.<tokenname>.properties must be specified.

If properties are not specified, and the file this points to does not exist, a new one will be generated with new keys. Note that this file must be kept the same across all clusters and kept in sync with all servers consuming the LTPA keys.

ltpa.token.<tokenname>.propertiesContents of LTPA key file

If specified, contains the contents of the key file - this key is in the format generated by the various IBM products.

Example:

#Mon May 21 10:27:07 CEST 2018
com.ibm.websphere.CreationDate=Mon May 21 10\:27\:07 CEST 2018
com.ibm.websphere.ltpa.version=1.0
com.ibm.websphere.ltpa.3DESKey=p7JQDC5aq5UIlfv5xtYsprRf8d8qItDvqthGSgXWQ14\=
com.ibm.websphere.CreationHost=localhost
com.ibm.websphere.ltpa.PrivateKey=hN2G2F59pWtFOVjUY...snipped...e81OlsaVp8\=
com.ibm.websphere.ltpa.Realm=defaultRealm
com.ibm.websphere.ltpa.PublicKey=AMKrclsDHhK...snipped...9vAQAB

You can use this property to keep the keys in Ceptor's configuration instead of having them on disk on all servers within a cluster.
If this property is specified, the ltpa.token.<tokenname>.filename property is ignored.

Note that the keys are encrypted with the password.

ltpa.token.<tokenname>.passwordPassword - may be encrypted.Specify the password that the keys are encrypted with - see Encrypting or Obfuscating Passwords for details on keeping the password safe.
ltpa.token.<tokenname>.create.useridMapper - used to specify userid in created tokens.
Default:
user:BasicRegistry/%{userid}

This mapper is used to specify the userid in a created token. The macro %{userid} will be replaced with the authenticated users userid, and %{xxxxx} will be replaced by any other input specified when calling the newToken() method on the authentication plugin.

This can also be a script (javascript / groovy / python) which generated and returns the value to use.

ltpa.token.<tokenname>.expiration.minutesLong

Token expiration time in minutes - newly created tokens will expires after the configured number of minutes.

Tokens created by the TAuthenticatorLTPAToken plugin in the Ceptor Gateway are cached and reused up to one minute before the expiration time.

ltpa.token.<tokenname>.create.scriptScriptThis script is called when creating new tokens - it allows adding additional attributes to the token, such as the users groups, name or anything else you want to add to the token itself.
ltpa.token.<tokenname>.parse.scriptScriptCalled when parsing the token - it allows you to specify which attributes are mapped to what within the session.

Example:

<group name="ltpa" description="LTPA Tokens">
	<property name="ltpa.token.liberty1.authenticate" value="true" description="If true, allow authentication using tokens signed by these keys"/>
	<property name="ltpa.token.liberty1.create.script" value="%{script}" description="Script called when creating token - allows adding additional attributes to the generated token"/>
	<property name="ltpa.token.liberty1.create.userid" value="user:BasicRegistry/%{userid}" description="Macro/script for specifying userid inside LTPA token"/>
	<property name="ltpa.token.liberty1.expiration.minutes" value="30" description="Expiration time in minutes, when creating new tokens"/>
	<property name="ltpa.token.liberty1.filename" value="${portalprotect.home}/config/ltpa.keys" description="Name of file that keys are stored within - created if it does not exist upon startup"/>
	<property name="ltpa.token.liberty1.parse.script" value="%{script}context.session.userid = context.token.getAttributes('u')[0];" description="Script used when parsing token - used to parse token content into session"/>
	<property name="ltpa.token.liberty1.password" value="changeit" description="Password that keys are encrypted with"/>
	<property name="ltpa.token.liberty1.properties" value="" description="If set, used instead of filename - can contain the LTPA keys file contents"/>
	<property name="ltpa.tokens" value="liberty1" description="List of LTPA tokens"/>
</group>

Scripts

The scripts are executed with a a variable; context pointing to an instance of this class:

package dk.itp.security.authentication.ltpa;

import dk.itp.security.authentication.ltpa.token.Token;
import dk.itp.security.passticket.User;
import portalprotect.org.json.JSONObject;

public class LTPAState {
	/** Contains input from the caller - e.g. the gateway */
	public JSONObject jo;
	/** The session being updated or used to create the token */
	public User session;
	/** LTPA Token configuration - contains the values from the configuration */
	public LTPATokenConfig cfg;
	/** The token used as input when authenticating or newly created when creating a token */
	public Token token;
}


The JSON Object "jo" contains the input from the caller - e.g. the gateway. This allows specifying additional values when creating the token, and these can be used by the script. Note that he token variable is not available when calling the create.userid script - it is only present after creation and available for the create.script and parse.script to use.

See Authentication Plugins for more information.

Example script for parsing:

// Copy the userid directly from the token to the user
// Most LTPA tokens only contain this and no other attributes.
context.session.userid = context.token.getAttributes('u')[0];


Example script for creating and adding additional attributes to a token:

// Add the username
context.token.addAttribute("name", context.session.username);
// Add each group - will end up as an array of string in the token.
if (context.session.userGroups != null) {
  for(int i = 0; i < context.session.userGroups.length; i++) {
	context.token.addAttribute("group", context.session.userGroups[i]);
  }
}

Creating New Tokens Programmatically

To create a new token, call:

JSONObject json = new JSONObject();
json.put("tokenname", "liberty1");
json.put("additionalattribute", "available to the create script");

String result = Agent.getInstance().newToken(sessionId, json.toString()); // result is now a JSON string with two attributes; token and expiration

JSONObject resultObject = new JSONObject(result);
String generatedToken = resultObject.get("token");
long expiresAt = resultObject.get("expiration"); // Time this expires at, in milliseconds since 1/1 1970, GMT.

Programmatically Authenticating Using a Token

Normally, you would use the Ceptor Gateway and configure the LTPA Authentication plugin (see Location - Authentication ) but to do it programmatically, you can call this:

// Use JSON input - allows you to specify additional attributes that are available to the scripts
JSONObject json = new JSONObject();
json.put("tokenname", "liberty1");
json.put("token", myLTPAToken);
json.put("myadditionalattribute", "myvalue");
Agent.getInstance().login(sessionId, AuthTypes.AUTHTYPE_LTPA, "ltpa", json.toString());


// Alternatively - Use the token directly, no JSON
Agent.getInstance().login(sessionId, AuthTypes.AUTHTYPE_LTPA, "liberty1", myLTPAToken);

© Ceptor ApS. All Rights Reserved.