Skip to content
Draft
113 changes: 113 additions & 0 deletions docs/janssen-server/auth-server/tokens/oauth-tx-tokens.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,119 @@ transaction token (not regular `access_token`).
- View full obtain execution log [here](../../../assets/log/tx-token-request-run-log.txt)
- View full replace execution log [here](../../../assets/log/tx-token-replace-run-log.txt)

### TxToken custom script

Custom script allows to modify TxToken JWT payload claim, response or lifetime.

The TxTokenType interception script extends the base script type with the `init`, `destroy` and `getApiVersion` methods:

| Inherited Methods | Method description |
|:-----|:------|
| `def init(self, customScript, configurationAttributes)` | This method is only called once during the script initialization. It can be used for global script initialization, initiate objects etc |
| `def destroy(self, configurationAttributes)` | This method is called once to destroy events. It can be used to free resource and objects created in the `init()` method |
| `def getApiVersion(self, configurationAttributes, customScript)` | The getApiVersion method allows API changes in order to do transparent migration from an old script to a new API. Only include the customScript variable if the value for getApiVersion is greater than 10 |

The `configurationAttributes` parameter is `java.util.Map<String, SimpleCustomProperty>`.

The TxTokenType interception script also adds the following method(s):

| Method | Method description |
|:----------------------------------------------------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `def getTxTokenLifetimeInSeconds(self, context)` | Used to modify Tx Token lifetime in seconds. <br/> `context` is `io.jans.as.server.service.external.context.ExternalScriptContext` |
| `def modifyTokenPayload(self, jsonWebResponse, context)` | Used to modify TxToken object before it is persisted. <br/> `jsonWebResponse` is `io.jans.as.model.token.JsonWebResponse`<br/> `context` is `io.jans.as.server.service.external.context.ExternalScriptContext` |
| `def modifyResponse(self, response, context)` | Used to modify response from `/token` endpoint for transaction tokens. <br/> `response` is `org.json.JSONObject`<br/> `context` is `io.jans.as.server.service.external.context.ExternalScriptContext` |


```java


import io.jans.as.model.token.JsonWebResponse;
import io.jans.as.server.service.external.context.ExternalScriptContext;
import io.jans.model.SimpleCustomProperty;
import io.jans.model.custom.script.model.CustomScript;
import io.jans.model.custom.script.type.token.TxTokenType;
import io.jans.service.custom.script.CustomScriptManager;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;

public class TxToken implements TxTokenType {

private static final Logger scriptLogger = LoggerFactory.getLogger(CustomScriptManager.class);

/**
*
* @param context context refers to io.jans.as.server.service.external.context.ExternalScriptContext
* @return lifetime of tx_token in seconds. It must be more then 0 or otherwise it will be ignored by server.
*/
@Override
public int getTxTokenLifetimeInSeconds(Object context) {
boolean condition = false; // under some condition return 1 day lifetime
if (condition) {
return 86400;
}
return 0;
}

/**
*
* @param jsonWebResponse refers to io.jans.as.model.token.JsonWebResponse
* @param context refers to io.jans.as.server.service.external.context.ExternalScriptContext
* @return true if tx_token should be created or false to forbid tx_token creation.
*/
@Override
public boolean modifyTokenPayload(Object jsonWebResponse, Object context) {
ExternalScriptContext scriptContext = (ExternalScriptContext) context;
JsonWebResponse jwr = (JsonWebResponse) jsonWebResponse;
jwr.getClaims().setClaim("custom_claim", "custom_value");

return true;
}

/**
* @param responseAsJsonObject - response represented by org.json.JSONObject
* @param context - script context represented by io.jans.as.server.service.external.context.ExternalScriptContext
* @return true if changes must be applied to final response or false if whatever made in this method has to be cancelled
*/
@Override
public boolean modifyResponse(Object responseAsJsonObject, Object context) {
ExternalScriptContext scriptContext = (ExternalScriptContext) context;

JSONObject json = (JSONObject) responseAsJsonObject;
json.accumulate("custom_key", "custom_value");
return true;
}

@Override
public boolean init(Map<String, SimpleCustomProperty> configurationAttributes) {
scriptLogger.info("Initialized TxToken Java custom script.");
return true;
}

@Override
public boolean init(CustomScript customScript, Map<String, SimpleCustomProperty> configurationAttributes) {
scriptLogger.info("Initialized TxToken Java custom script.");
return true;
}

@Override
public boolean destroy(Map<String, SimpleCustomProperty> configurationAttributes) {
scriptLogger.info("Destroyed TxToken Java custom script.");
return true;
}

@Override
public int getApiVersion() {
return 11;
}
}


```


### References

- Transaction Tokens [spec](https://drafts.oauth.net/oauth-transaction-tokens/draft-ietf-oauth-transaction-tokens.html)
83 changes: 83 additions & 0 deletions docs/script-catalog/tx_token/TxToken.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@

import io.jans.as.model.token.JsonWebResponse;
import io.jans.as.server.service.external.context.ExternalScriptContext;
import io.jans.model.SimpleCustomProperty;
import io.jans.model.custom.script.model.CustomScript;
import io.jans.model.custom.script.type.token.TxTokenType;
import io.jans.service.custom.script.CustomScriptManager;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;

public class TxToken implements TxTokenType {

private static final Logger scriptLogger = LoggerFactory.getLogger(CustomScriptManager.class);

/**
*
* @param context context refers to io.jans.as.server.service.external.context.ExternalScriptContext
* @return lifetime of tx_token in seconds. It must be more then 0 or otherwise it will be ignored by server.
*/
@Override
public int getTxTokenLifetimeInSeconds(Object context) {
boolean condition = false; // under some condition return 1 day lifetime
if (condition) {
return 86400;
}
return 0;
}

/**
*
* @param jsonWebResponse refers to io.jans.as.model.token.JsonWebResponse
* @param context refers to io.jans.as.server.service.external.context.ExternalScriptContext
* @return true if tx_token should be created or false to forbid tx_token creation.
*/
@Override
public boolean modifyTokenPayload(Object jsonWebResponse, Object context) {
ExternalScriptContext scriptContext = (ExternalScriptContext) context;
JsonWebResponse jwr = (JsonWebResponse) jsonWebResponse;
jwr.getClaims().setClaim("custom_claim", "custom_value");

return true;
}

/**
* @param responseAsJsonObject - response represented by org.json.JSONObject
* @param context - script context represented by io.jans.as.server.service.external.context.ExternalScriptContext
* @return true if changes must be applied to final response or false if whatever made in this method has to be cancelled
*/
@Override
public boolean modifyResponse(Object responseAsJsonObject, Object context) {
ExternalScriptContext scriptContext = (ExternalScriptContext) context;

JSONObject json = (JSONObject) responseAsJsonObject;
json.accumulate("custom_key", "custom_value");
return true;
}

@Override
public boolean init(Map<String, SimpleCustomProperty> configurationAttributes) {
scriptLogger.info("Initialized TxToken Java custom script.");
return true;
}

@Override
public boolean init(CustomScript customScript, Map<String, SimpleCustomProperty> configurationAttributes) {
scriptLogger.info("Initialized TxToken Java custom script.");
return true;
}

@Override
public boolean destroy(Map<String, SimpleCustomProperty> configurationAttributes) {
scriptLogger.info("Destroyed TxToken Java custom script.");
return true;
}

@Override
public int getApiVersion() {
return 11;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ public class RegisterRequest extends BaseRequest {
private List<String> updateTokenScriptDns;
private List<String> logoutStatusJwtScriptDns;
private List<String> parScriptDns;
private List<String> txTokenScriptDns;
private List<String> postAuthnScriptDns;
private List<String> tokenExchangeScriptDns;
private List<String> consentGatheringScriptDns;
Expand Down Expand Up @@ -204,6 +205,7 @@ public RegisterRequest() {
this.updateTokenScriptDns = new ArrayList<>();
this.logoutStatusJwtScriptDns = new ArrayList<>();
this.parScriptDns = new ArrayList<>();
this.txTokenScriptDns = new ArrayList<>();
this.postAuthnScriptDns = new ArrayList<>();
this.tokenExchangeScriptDns = new ArrayList<>();
this.consentGatheringScriptDns = new ArrayList<>();
Expand Down Expand Up @@ -1738,6 +1740,26 @@ public RegisterRequest setParScriptDns(List<String> parScriptDns) {
return this;
}

/**
* Gets tx token script dns
*
* @return tx token script dns
*/
public List<String> getTxTokenScriptDns() {
return txTokenScriptDns;
}

/**
* Sets tx token script dns
*
* @param txTokenScriptDns tx token script dns
* @return register request
*/
public RegisterRequest setTxTokenScriptDns(List<String> txTokenScriptDns) {
this.txTokenScriptDns = txTokenScriptDns;
return this;
}

/**
* Gets logout status jwt script dns
*
Expand Down Expand Up @@ -1949,6 +1971,7 @@ public static RegisterRequest fromJson(JSONObject requestObject) throws JSONExce
result.setUpdateTokenScriptDns(extractListByKey(requestObject, UPDATE_TOKEN_SCRIPT_DNS.toString()));
result.setLogoutStatusJwtScriptDns(extractListByKey(requestObject, LOGOUT_STATUS_JWT_SCRIPT_DNS.toString()));
result.setParScriptDns(extractListByKey(requestObject, PAR_SCRIPT_DNS.toString()));
result.setTxTokenScriptDns(extractListByKey(requestObject, TX_TOKEN_SCRIPT_DNS.toString()));
result.setPostAuthnScriptDns(extractListByKey(requestObject, POST_AUTHN_SCRIPT_DNS.toString()));
result.setTokenExchangeScriptDns(extractListByKey(requestObject, TOKEN_EXCHANGE_SCRIPT_DNS.toString()));
result.setConsentGatheringScriptDns(extractListByKey(requestObject, CONSENT_GATHERING_SCRIPT_DNS.toString()));
Expand Down Expand Up @@ -2280,6 +2303,7 @@ public void getParameters(BiFunction<String, Object, Void> function) {
applyArray(function, UPDATE_TOKEN_SCRIPT_DNS, updateTokenScriptDns);
applyArray(function, LOGOUT_STATUS_JWT_SCRIPT_DNS, logoutStatusJwtScriptDns);
applyArray(function, PAR_SCRIPT_DNS, parScriptDns);
applyArray(function, TX_TOKEN_SCRIPT_DNS, txTokenScriptDns);
applyArray(function, POST_AUTHN_SCRIPT_DNS, postAuthnScriptDns);
applyArray(function, TOKEN_EXCHANGE_SCRIPT_DNS, tokenExchangeScriptDns);
applyArray(function, CONSENT_GATHERING_SCRIPT_DNS, consentGatheringScriptDns);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,11 @@ public enum RegisterRequestParam {
*/
PAR_SCRIPT_DNS("par_script_dns"),

/**
* list of tx token script dns
*/
TX_TOKEN_SCRIPT_DNS("tx_token_script_dns"),

/**
* list of post authn script dns
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ public class ClientAttributes implements Serializable {
@JsonProperty("parScriptDns")
private List<String> parScriptDns = Lists.newArrayList();

@JsonProperty("txTokenScriptDns")
private List<String> txTokenScriptDns = Lists.newArrayList();

@JsonProperty("backchannelLogoutUri")
private List<String> backchannelLogoutUri;

Expand Down Expand Up @@ -475,6 +478,16 @@ public ClientAttributes setParScriptDns(List<String> parScriptDns) {
return this;
}

public List<String> getTxTokenScriptDns() {
if (txTokenScriptDns == null) txTokenScriptDns = Lists.newArrayList();
return txTokenScriptDns;
}

public ClientAttributes setTxTokenScriptDns(List<String> txTokenScriptDns) {
this.txTokenScriptDns = txTokenScriptDns;
return this;
}

public Boolean getRunIntrospectionScriptBeforeJwtCreation() {
if (runIntrospectionScriptBeforeJwtCreation == null) {
runIntrospectionScriptBeforeJwtCreation = false;
Expand Down Expand Up @@ -602,6 +615,7 @@ public String toString() {
", updateTokenScriptDns=" + updateTokenScriptDns +
", logoutStatusJwtScriptDns=" + logoutStatusJwtScriptDns +
", parScriptDns=" + parScriptDns +
", txTokenScriptDns=" + txTokenScriptDns +
", backchannelLogoutUri=" + backchannelLogoutUri +
", backchannelLogoutSessionRequired=" + backchannelLogoutSessionRequired +
", additionalAudience=" + additionalAudience +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,9 @@ public void updateClientFromRequestObject(Client client, RegisterRequest request
if (requestObject.getParScriptDns() != null) {
client.getAttributes().setParScriptDns(requestObject.getParScriptDns());
}
if (requestObject.getTxTokenScriptDns() != null) {
client.getAttributes().setTxTokenScriptDns(requestObject.getTxTokenScriptDns());
}
if (requestObject.getPostAuthnScriptDns() != null) {
client.getAttributes().setPostAuthnScripts(requestObject.getPostAuthnScriptDns());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public boolean createPar(CustomScriptConfiguration script, Par par, ExternalScri
public boolean createPar(Par par, ExternalScriptContext context) {
List<CustomScriptConfiguration> scripts = getScripts(context);
if (scripts.isEmpty()) {
return false;
return true;
}
log.trace("Executing {} 'createPar' scripts.", scripts.size());

Expand Down
Loading
Loading