8
votes

We have basic authentication enabled on Tomcat6. User is authenticated in browser and then JNLP is launched to launch application in Java Web Start. On start-up, java web start tries to download jar files from server but it is not using the same session which is already authenticated by browser. Based on forums I have tried to pass session id in JNLP by using sid property as well as be appending in URL. Environment is restricted so each and every request needs to be authenticated we cannot say to exclude requests for jar file not being authenticated. Below is my JSP creating JNLP file, can anyone please help how can we continue same session to download jars which is already authenticated by Browser.

<% response.setContentType("application/x-java-jnlp-file"); %>
<%= "<?xml version=\"1.0\" encoding=\"utf-8\"?>" %>
<!-- JNLP File for SimpleTableDemo -->
<%
String baseURL = request.getRequestURL().toString().replace(request.getRequestURI(), request.getContextPath());
%>
<jnlp codebase="<%=baseURL%>">

    <information>
        <title>Simple Table Demo Application</title>
        <vendor>Try</vendor>
        <description>SimpleTableDemo</description>
        <description kind="short">An application that demonstrates a simple table.</description>
    </information>

    <resources>
        <j2se version="1.6+" />
        <property name="sid" value="<%=request.getSession().getId()%>" />
        <property name="serviceHost" value="<%=request.getServerName()%>"/>
        <property name="servicePort" value="<%=request.getServerPort()%>"/> 
        <jar href="AuthenticateJNLPJars.jar;JSESSIONID=<%=request.getSession().getId()%>" />
    </resources>

    <application-desc main-class="SimpleTableDemo" >
    </application-desc>
</jnlp>
4

4 Answers

3
votes

I now have (some) answers....

I realize that this question is a year old, but since it`s the first result on google when searching for this issue I figured it was a good idea to complete it.

There is one problem with the jnlp code that you provided, but first, you have to check if adding the cookie to the url would actually work..... and that depends on your app deployment configuration.

I do not know how it is on Tomcat... I am using weblogic, and in it you have to check in weblogic.xml the following property

 <session-descriptor>
      <url-rewriting-enabled>true</url-rewriting-enabled>
 </session-descriptor>

This means that, if available, weblogic will get the session id from the URL (using the same format that you have in your code)

If it is false, then this solution will not work and you will have to send a cookie with the session id in each request.... and if you found a way to do to that PLEASE respond.... it would help me a lot.

now, if url-rewriting-enable is true, then this approach will work once you fix the following problem in your script.

The problem is that, once java web start gets the jnlp from the browser, it will download it again from the server, so you have to make sure that you add the session id to that request also. you do that by modifiing the initial tag like this:

<jnlp spec="1.0+" codebase="<%=baseURL%>" href="<%=NAME_OF_JNLP%>;JSESSIONID=<%=SESSION_ID%>"> 

And that is it, the code should work...

by the way, the properties that you added:

<property name="sid" value="<%=request.getSession().getId()%>" />
<property name="serviceHost" value="<%=request.getServerName()%>"/>
<property name="servicePort" value="<%=request.getServerPort()%>"/> 

are not relevant to this, you can delete them and the code will still work.

2
votes

(I don't have enough privileges to add a comment, so I'm putting this as a separate answer.)

Argod wrote:

The problem is that, once java web start gets the jnlp from the browser, it will download it again from the server, so you have to make sure that you add the session id to that request also. you do that by modifiing the initial tag like this:

<jnlp spec="1.0+" codebase="<%=baseURL%>" href="<%=NAME_OF_JNLP%>;JSESSIONID=<%=SESSION_ID%>">

Argod, when you add a href attribute to your jnlp element, you actually make JWS to download the jnlp file again from the server.

Check out Unofficial Java Web Start/JNLP FAQ. Here is what it says:

One trick is to make sure not to include the href attribute in the JNLP file that your servlet sends back to Web Start. This will tell Web Start to disable the update check on JNLP files, and Web Start will not treat each new JNLP file as an application update - only updated jar files will.

I have just checked this locally. With a href attribute, jnlp file actually gets downloaded three times, and jar file gets downloaded once. See my Tomcat logs:

127.0.0.1 ... "GET /my-servlet/jws/myjws.jnlp;JSESSIONID=58080491243456B6A653682FA0A3A738 HTTP/1.1" 200 741
127.0.0.1 ... "GET /my-servlet/jws/myjws.jnlp;JSESSIONID=58080491243456B6A653682FA0A3A738 HTTP/1.1" 200 741
127.0.0.1 ... "GET /my-servlet/jws/myjws.jnlp;JSESSIONID=342082FEA657D765699EADAF5486E9A7 HTTP/1.1" 200 741
127.0.0.1 ... "GET /my-servlet/jws/myjws.jar;JSESSIONID=342082FEA657D765699EADAF5486E9A7 HTTP/1.1" 200 7555

Notice how a new JSESSIONID is assigned in the end, which is bad. On the other hand, with no href attribute, jnlp file gets downloaded once, and jar file gets downloaded once, and JSESSIONID is preserved:

127.0.0.1 ... "GET /my-servlet/jws/myjws.jnlp;JSESSIONID=58080491243456B6A653682FA0A3A738 HTTP/1.1" 200 672
127.0.0.1 ... "GET /my-servlet/jws/myjws.jar;JSESSIONID=58080491243456B6A653682FA0A3A738 HTTP/1.1" 200 7555

Another point of interest, is that prorerty names like "sid", "serviceHost", "servicePort" (like OP used) will get rejected by JWS.

<property name="sid" value="<%=request.getSession().getId()%>" />
<property name="serviceHost" value="<%=request.getServerName()%>"/>
<property name="servicePort" value="<%=request.getServerPort()%>"/>

Again, check out Unofficial Java Web Start/JNLP FAQ. Here is what it says:

You can only set properties for untrusted/unsigned apps in the XML startup file if the property is "trusted". Currently trusted properties include:

  • javaws.*
  • jnlp.*
  • javax.swing.defaultlf
  • sun.java2d.noddraw

In other words, if you want to pass your own property to your app prefix it with javaws, for example, use javaws.myproperty instead of myproperty.

The same actually applies to trusted/signed JWS applications.

1
votes

Because you create your JNPL with JSP you can pass to your applet an argument with some security token or the session ID, then your applet must pass that value when request info from the server.

Check this: Generate JNLP dynamically

0
votes

You are really close!, but your security layer needs more components.

The key is the baseURL variable, create an URL to point to a servlet than respond with files required by the applet, and append to it the security token or ticket. Like this:

/codebaseServlet/ABC123123

Make the codebaseServlet to extract and validate the security token and responds with the requested files. And now be free to implement your security as you wish. You can make the security token to be valid for some time, or while the user session exist, validate the IP form the request is coming, etc.

Check: http://docs.oracle.com/javase/6/docs/technotes/guides/jweb/applet/codebase_determination.html