Expand my Community achievements bar.

SOLVED

Exception: "Could not validate SAML Token"

Avatar

Level 1

We have an evaluation system setup that we are using to generate PDF from PS. We're connecting via the EJB client, and typically have had no problems. Until today. At some point today we began seeing exceptions being thrown on the client:

Caused by: com.adobe.idp.um.api.UMException | [com.adobe.idp.um.api.impl.AuthenticationManagerImpl] errorCode:16421 errorCodeHEX:0x4025 message:Could not validate SAML Token --- Assertion has expired and hence not valid for user [administrator@DefaultDom]. Its valid till time [Tue Feb 04 10:58:45 MST 2014] was found to be before the current time [Tue Feb 04 16:04:41 MST 2014]

Simply bouncing the app server where the client code is running solved the problem, however we'd like to better understand what is going on and why. Nothing that I can find in the docs seems to indicate the cause/solution, and possible solutions have links that appear to no longer function: http://cookbooks.adobe.com/post_Renewing_the_context_to_handle_session_expiry-16410.html

Any suggestions and/or insight would be greatly appreciated. Thanks!

1 Accepted Solution

Avatar

Correct answer by
Level 3

PROBLEM

Using the same instance of ServiceClientFactory to remotely invoke the services exposed by the LiveCycle container can lead to

exception related to assertion expiry

Solution

To handle the timeout use the ThrowHandler mechanism provided by the ServiceClientFactory framework

Detailed explanation

LiveCycle provides a client sdk for java based client to invoke its services remotely.

An invocation involves Creation of a ServiceClientFactory instance Setting the user credential in thefactory instance Pass that factory to a service client or use that to create InvocationRequest directly

Use the client to make the actual request.

For more details refer to Invoking

LiveCycle ES Using the Java API .

A ServiceClientFactory instance once created is valid for a ceratin

period of time which is by default 120 min. if the same instance is used to invoke beyond this period then it would lead to an exception stating that

the session has expired [com.adobe.idp.um.api.impl.AuthenticationManagerImpl]

errorCode:16421 errorCodeHEX:0x4025 message:Could not validate SAML

Token --- Assertion has expired and hence not valid for user

[administrator@DefaultDom]. Its valid till time [Thu Oct 22

17:07:53 IST

2009] was found to be before the current time [Thu Oct

22 17:58:18 IST 2009]

This is not an issue if the ServiceClientFactory instance is used for short duration. However if you are going to perform a long

running task like converting large number of documents to pdf ,applying policies to them etc then it would be an issue.

Session Expiry

Before fxing the issue some info on what is session expiry.

  • When you use a ServiceClientFactory instance to invoke the service following fow happens
  • You set the credentials in the properties and invoke theservice
  • LiveCycle on server side validates the credentials and issues a Context. It is sort of a ticket which can be reused later instead of the actual credentials.
  • Upon receiving the response from the server the ServiceClientFactory instance deletes its own copy of credentials and instead stores the Context For later invocations this Context instance is passed instead of the user credentials
  • This whole fow is done to ensure that user's credentials are not sent for each remote call thus improving the security.

For more information on Context refer to

User Identity in LiveCycle .

Solution

To fx this issue you would have to re authenticate to LiveCycle and get the Context reissued. the best way to do that is to make use of the ThrowHandler provided by the ServiceClientFactory framework

STEP1 -  Create a Throwhandler

______________________________________________________________________ ______________________________________________

/**

* This ThrowHandler caches the user credentials and uses them

to refresh the Context in the

* ServiceClientFactory upon expiry.

*/

private static class SimpleTimeoutThrowHandler implements

ThrowHandler {

private String username;

private String password;

public SimpleTimeoutThrowHandler(String username, String

password) {

this.username = username;

this.password = password;

}

public boolean handleThrowable(Throwable t, ServiceClient

sc,

ServiceClientFactory scf, MessageDispatcher md,

InvocationRequest ir, int numTries) throws

DSCException {

if(timeoutError(t)){

//The call to AuthenticationManager do not require

authentication so the default properties

//are suffcient

AuthenticationManager am =

new

AuthenticationManagerServiceClient(ServiceClientFactory.createInstance (getDefaultProperties()));

AuthResult ar = null;

try {

ar =

am.authenticate(username,password.getBytes());

} catch (UMException e) {

throw new IllegalStateException(e);

}

Context ctx = new Context();

ctx.initPrincipal(ar);

//Refresh the ServiceClientFactory instance with

the new context

scf.setContext(ctx);

logger.info("Refreshed the context associated with

ServiceCLientFactory");

//Now tell SCF to try the invocation again

return true;

}

//Check so that we do not wrap the exception again

if(t instanceof DSCException)

throw (DSCException)t;

if(t instanceof RuntimeException)

throw (RuntimeException)t;

// how is it possible to get this far?

throw new IllegalStateException(t);

}

private boolean timeoutError(Throwable t) {

if(!(t.getCause() instanceof UMException)){

return false;

}

UMException ue = (UMException) t.getCause();

//Check that UMException is due to the

assertion/context expiry

if(UMConstants.ErrorCodes.E_TOKEN_INVALID ==

ue.getErrCode()){

return true;

}

return false;

}

}

______________________________________________________________________ __________________________________________

This ThrowHandler would be invoked by the ServiceClientFactory upon receiving any exception. The handler would then determine if its a timeout related exception and then would refresh the Context associated with the factory instance and tells it to retry the invocation.

STEP - 2 Register the handler

______________________________________________________________________ __________________________________________

ServiceClientFactory.installThrowHandler(new

SimpleTimeoutThrowHandler(username, password));

______________________________________________________________________ __________________________________________

Note: The handler should be registered only once in the application

STEP 3 - Perform your invocation

Following sample would try to apply policies on all the fles present in a directory

______________________________________________________________________ __________________________________________

Properties p = getDefaultProperties();

p.setProperty(DSC_CREDENTIAL_USERNAME, username);

p.setProperty(DSC_CREDENTIAL_PASSWORD, password);

ServiceClientFactory scf =

ServiceClientFactory.createInstance(p);

//Now do some long running operation

String inputDirName ="path-to-input-dir";

String outDirName = "path-to-out-dir";

String policyName = "the-policy-name";

File inDir = new File(inputDirName);

File outDir = new File(outDirName);

RightsManagementClient rmClient = new

RightsManagementClient(scf);

DocumentManager docManager = rmClient.getDocumentManager();

//Iterate over all the pdf in the inDir and apply the

policies. If this takes a

for(File pdfFile : inDir.listFiles()){

Document inDoc = new Document(pdfFile, false);

Document securedDoc = docManager.applyPolicy(inDoc,

pdfFile.getName(), null, policyName, null, null);

securedDoc.copyToFile(new

File(outDir,pdfFile.getName()));

}

______________________________________________________________________ __________________________________________

Now the invocation would complete even if it takes a long time. if any session expiry occurs then our ThrowHandler would take care of that.

here's a sample:

TimeOutSample.zip

View solution in original post

2 Replies

Avatar

Correct answer by
Level 3

PROBLEM

Using the same instance of ServiceClientFactory to remotely invoke the services exposed by the LiveCycle container can lead to

exception related to assertion expiry

Solution

To handle the timeout use the ThrowHandler mechanism provided by the ServiceClientFactory framework

Detailed explanation

LiveCycle provides a client sdk for java based client to invoke its services remotely.

An invocation involves Creation of a ServiceClientFactory instance Setting the user credential in thefactory instance Pass that factory to a service client or use that to create InvocationRequest directly

Use the client to make the actual request.

For more details refer to Invoking

LiveCycle ES Using the Java API .

A ServiceClientFactory instance once created is valid for a ceratin

period of time which is by default 120 min. if the same instance is used to invoke beyond this period then it would lead to an exception stating that

the session has expired [com.adobe.idp.um.api.impl.AuthenticationManagerImpl]

errorCode:16421 errorCodeHEX:0x4025 message:Could not validate SAML

Token --- Assertion has expired and hence not valid for user

[administrator@DefaultDom]. Its valid till time [Thu Oct 22

17:07:53 IST

2009] was found to be before the current time [Thu Oct

22 17:58:18 IST 2009]

This is not an issue if the ServiceClientFactory instance is used for short duration. However if you are going to perform a long

running task like converting large number of documents to pdf ,applying policies to them etc then it would be an issue.

Session Expiry

Before fxing the issue some info on what is session expiry.

  • When you use a ServiceClientFactory instance to invoke the service following fow happens
  • You set the credentials in the properties and invoke theservice
  • LiveCycle on server side validates the credentials and issues a Context. It is sort of a ticket which can be reused later instead of the actual credentials.
  • Upon receiving the response from the server the ServiceClientFactory instance deletes its own copy of credentials and instead stores the Context For later invocations this Context instance is passed instead of the user credentials
  • This whole fow is done to ensure that user's credentials are not sent for each remote call thus improving the security.

For more information on Context refer to

User Identity in LiveCycle .

Solution

To fx this issue you would have to re authenticate to LiveCycle and get the Context reissued. the best way to do that is to make use of the ThrowHandler provided by the ServiceClientFactory framework

STEP1 -  Create a Throwhandler

______________________________________________________________________ ______________________________________________

/**

* This ThrowHandler caches the user credentials and uses them

to refresh the Context in the

* ServiceClientFactory upon expiry.

*/

private static class SimpleTimeoutThrowHandler implements

ThrowHandler {

private String username;

private String password;

public SimpleTimeoutThrowHandler(String username, String

password) {

this.username = username;

this.password = password;

}

public boolean handleThrowable(Throwable t, ServiceClient

sc,

ServiceClientFactory scf, MessageDispatcher md,

InvocationRequest ir, int numTries) throws

DSCException {

if(timeoutError(t)){

//The call to AuthenticationManager do not require

authentication so the default properties

//are suffcient

AuthenticationManager am =

new

AuthenticationManagerServiceClient(ServiceClientFactory.createInstance (getDefaultProperties()));

AuthResult ar = null;

try {

ar =

am.authenticate(username,password.getBytes());

} catch (UMException e) {

throw new IllegalStateException(e);

}

Context ctx = new Context();

ctx.initPrincipal(ar);

//Refresh the ServiceClientFactory instance with

the new context

scf.setContext(ctx);

logger.info("Refreshed the context associated with

ServiceCLientFactory");

//Now tell SCF to try the invocation again

return true;

}

//Check so that we do not wrap the exception again

if(t instanceof DSCException)

throw (DSCException)t;

if(t instanceof RuntimeException)

throw (RuntimeException)t;

// how is it possible to get this far?

throw new IllegalStateException(t);

}

private boolean timeoutError(Throwable t) {

if(!(t.getCause() instanceof UMException)){

return false;

}

UMException ue = (UMException) t.getCause();

//Check that UMException is due to the

assertion/context expiry

if(UMConstants.ErrorCodes.E_TOKEN_INVALID ==

ue.getErrCode()){

return true;

}

return false;

}

}

______________________________________________________________________ __________________________________________

This ThrowHandler would be invoked by the ServiceClientFactory upon receiving any exception. The handler would then determine if its a timeout related exception and then would refresh the Context associated with the factory instance and tells it to retry the invocation.

STEP - 2 Register the handler

______________________________________________________________________ __________________________________________

ServiceClientFactory.installThrowHandler(new

SimpleTimeoutThrowHandler(username, password));

______________________________________________________________________ __________________________________________

Note: The handler should be registered only once in the application

STEP 3 - Perform your invocation

Following sample would try to apply policies on all the fles present in a directory

______________________________________________________________________ __________________________________________

Properties p = getDefaultProperties();

p.setProperty(DSC_CREDENTIAL_USERNAME, username);

p.setProperty(DSC_CREDENTIAL_PASSWORD, password);

ServiceClientFactory scf =

ServiceClientFactory.createInstance(p);

//Now do some long running operation

String inputDirName ="path-to-input-dir";

String outDirName = "path-to-out-dir";

String policyName = "the-policy-name";

File inDir = new File(inputDirName);

File outDir = new File(outDirName);

RightsManagementClient rmClient = new

RightsManagementClient(scf);

DocumentManager docManager = rmClient.getDocumentManager();

//Iterate over all the pdf in the inDir and apply the

policies. If this takes a

for(File pdfFile : inDir.listFiles()){

Document inDoc = new Document(pdfFile, false);

Document securedDoc = docManager.applyPolicy(inDoc,

pdfFile.getName(), null, policyName, null, null);

securedDoc.copyToFile(new

File(outDir,pdfFile.getName()));

}

______________________________________________________________________ __________________________________________

Now the invocation would complete even if it takes a long time. if any session expiry occurs then our ThrowHandler would take care of that.

here's a sample:

TimeOutSample.zip

Avatar

Level 1

Perfect - this is exactly what we needed. As an interim solution we were catching the timeout, reinitializing the connection if the timeout was caught and then resubmitting the request - more or less the same thing, but I'm much happier using the built in API for such a manuever. Thanks!