Ravi-A-Doer Ravi-A-Doer - 1 month ago 20
reST (reStructuredText) Question

How to Integrate with WebSSO from Java Layer

Forgive me for a lengthy query. I am in middle of integrating REST services with our WebSSO setup. The task appears complex; hence seeking advice. While I give specifics to add more detail, I request you to treat this as a generic problem on how to integrate with WebSSO setup from Java layer. This way you won’t be dissuaded by the specific technologies I must use.

Setup



We have built an application in AngularJS. Using this application, among other things, one can upload files to Filenet. Our Filenet platform provides REST API (our internal REST wrapper around Filenet native APIs). The Filenet has WebSSO enabled – and we need to make use of it. For reasons outside of my control, I cannot make direct calls to Filenet REST directly from AngularJS. Instead I need to create my own REST interface (Java Jersey on WebLogic) – let’s call this interface façade REST. The AngularJS code calls the façade REST, and façade REST implementation in turn calls Filenet REST. All is well when I use an application account (or system account or faceless account). However I need to raise the bar and implement WebSSO (we can’t use application account or basic authentication). Note:


  • We use RSA ClearTrust for WebSSO.

  • We use NTLM (I believe – but I am not entirely sure) as WebSSO token. As such, once logged onto our Windows machiens, we don’t have to enter username/password while logging onto any web applications (that are WebSSO enabled).

  • AngularJS code and façade REST implementation reside on the same Weblogic server. WebSOO is enabled on this server.

  • I use Jersey to implement façade REST. From façade rest, I use Apache HTTP Client to call into Filenet REST.

  • Our Filenet resides on a different server – IBM WebSphere. WebSSO is enabled on this server.



Pseudo Code



Following is how I envisage it will work and my subsequent queries.

1) The AngularJS makes a call to façade REST
2) Façade REST makes a call to Filenet REST
2.2) Filenet REST, upon finding that the WebSSO cookie is absent, redirects the caller to WebSSO login page (this is evident in the code that I have developed so far).
2.2) From façade, do I need to redirect the browser to this login page? I haven’t tried this yet. If I redirected the browser to login page, how would the browser then know that, after seamless and successful login, it should get back to my façade REST?


To repeat the point 2.2 above:


  • Do I need to redirect the browser to this login page?

  • If I redirected the browser to login page, how would the browser then know that, after seamless and successful login, it should get back to my façade REST?

  • What other challenges I may face?

  • Is my thought process accurate?

  • Am I missing anything?


Answer

While seemingly complex, the solution turned out to be relatively simple and straight-forward. This is what I had to do:

  • In Filenet Façade, read the CTSESSION cookie that was being generated by our underlying WebSSO product and pass it onto Filenet REST.
  • In Filenet Façade, while making the Apache HTTPClient call to Filenet REST, set the redirect policy to LaxRedirectStrategy() so that any redirections will be taken care of by Apache HTTPClient.

Following is the code (the irrelevant parts are removed):

@POST
@Path("/upload")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response upload(@CookieParam("CTSESSION") Cookie ctSessionCookie) {

    // Get the CTSESSION cookie value
    String ctSession = ctSessionCookie.getValue();

    // Initialize Apache HTTPClient and pass the obtained cookie as a header
    HttpPost request = new HttpPost("FileNet.REST.URL");
    request.addHeader("Cookie", "CTSESSION=" + ctSession);
    CloseableHttpClient client = HttpClientBuilder.create().setRedirectStrategy(new LaxRedirectStrategy()).build();
    CloseableHttpResponse result = client.execute(request);

    // Obtain the result, construct Jersey Response, and send it out to the original caller
    Response.ok(result.toString()).build();
}