https / secure access to ITMill applications

Hi,

I am using ITMill 5.3.1 under JBoss 4.0.5.

  1. Is there anything in ITMill that prevents me from running all of my connections to the ITMill Application over https, rather than http ?

  2. Is there any info available on how this can be done (if anything special needs to be done with ITMill) ?

Thanks
Andrew

Hi,

There shouldn’t be any problems and I’m not aware of any special things you need to do to use https in your applications.

SSL is configured at the web server level, so the server documentation is the best place to start.

I’ve also seen applications using SSL client certificate authentication: User log in simply using their installed certificate (without any username/password form). This approach needs some kind of communication between the server (protocol) and the IT Mill Toolkit application to make the user information available to the rest of the application.

Sami,

Good to hear there is nothing special that needs to be done.

Do you know if any code in the incubator, samples, etc uses the SSL client certificate authentication method ? - I noticed the tkIRC application in the incubator was using SSL, but haven’t looked into it in any detail - do you know if that application uses the SSL client certificate authentication method ?

Thanks
Andrew

Here is an example:


public class MyApp extends Application implements TransactionListener {

...

	public void transactionEnd(Application application, Object transactionData) {
		if (application == this
				&& transactionData instanceof HttpServletRequest && 
				getUser() == null) {
			HttpServletRequest r = (HttpServletRequest) transactionData;
			String user = getValidEmail(null, (java.security.cert.X509Certificate[]) r
					.getAttribute("javax.servlet.request.X509Certificate"));
			if (user != null)
				setUser(user);
		}
	}

	private String getValidEmail(String requiredDomain, X509Certificate[] certs) {
		if (certs == null) return null;
		for (int i=0;i<certs.length; i++) {
			String dn=certs[i]
.getSubjectDN().getName();
			int start = dn.indexOf("EMAILADDRESS=");
			if (start>=0) {
				String email = dn.substring(start+13);
				if (email.indexOf(',')>=0) email=email.substring(0,email.indexOf(','));
				if (requiredDomain == null || email.endsWith("@"+requiredDomain)) {
					try {
						certs[i]
.checkValidity();
						return email;
					} catch (CertificateExpiredException e) {
						e.printStackTrace();
					} catch (CertificateNotYetValidException e) {
						e.printStackTrace();
					}
				}
			}
		}
		return null;
	}
	
	public void transactionStart(Application application, Object transactionData) {
	}
}

Also remember to turn on client authentication from your application server. For instructions on how this in done in Tomcat 6.0:

http://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html

Joonas, just saw that your authentication code is placed into the transactionEnd method. Im always using transactionStart to access servlet and http objects to prepare some extra info for the application, am I wrong and should use transactionEnd instead ?

When both callback methods are invoked during the single request life-cycle ?

Start is invoked in the beginning of the transaction and end in the end. Placing auth to end seems strange to me too (just cut n pasted the code from one old app). It should work fine in the transactionStart too.

  • Joonas

Is transaction end equals http request end ? If yes, making an auth there seems to be strange because this request is already processed and auth data (principal set) will be available on next request only. Or Im missing something ?

Yes… Applications servlet calls transactionStart before variableChange and paint and transactionEnd after those.

Fully agree. My example seems strange to me too :D

It should be:


 public class MyApp extends Application implements TransactionListener {
 
 ...
 
 	public void transactionEnd(Application application, Object transactionData) {
 	}
 
 	private String getValidEmail(String requiredDomain, X509Certificate[] certs) {
 		if (certs == null) return null;
 		for (int i=0;i&lt;certs.length; i++) {
 			String dn=certs[i]
.getSubjectDN().getName();
 			int start = dn.indexOf("EMAILADDRESS=");
 			if (start&gt;=0) {
 				String email = dn.substring(start+13);
 				if (email.indexOf(',')&gt=0) email=email.substring(0,email.indexOf(','));
 				if (requiredDomain == null || email.endsWith(&quot;@&quot;+requiredDomain)) {
 					try {
 						certs[i]
.checkValidity();
 						return email;
 					} catch (CertificateExpiredException e) {
 						e.printStackTrace();
 					} catch (CertificateNotYetValidException e) {
 						e.printStackTrace();
 					}
 				}
 			}
 		}
 		return null;
 	}
 	
 	public void transactionStart(Application application, Object transactionData) {
 		if (application == this
 				&& transactionData instanceof HttpServletRequest && 
 				getUser() == null) {
 			HttpServletRequest r = (HttpServletRequest) transactionData;
 			String user = getValidEmail(null, (java.security.cert.X509Certificate[]) r
 					.getAttribute(&quot;javax.servlet.request.X509Certificate&quot;));
 			if (user != null)
 				setUser(user);
 		}
 	}
 }

(above code has not been tested)