Saturday Apr 04, 2009

OpenID for JEE Applications - Part I

Please note that I have started a project site to provide a platform for further discussion and development. You will also find souce code from the OpenID-JSR-196 Login Module and a wiki page on the project site:
http://code.google.com/p/openid4java-jsr196/

You are welcome to join this project.


A few months ago I started to work on a Internet Web Application using OpenID as the primary login mechanism. In the following I will explain how you can use OpenID in your JEE Application.

OpenID is an open standard that allows a User to sign into web sites through a single URL (a single digital identity). This URL can be a personal home page, a blog or a web service (e.g from a OpenID Provider like myopenid or yahoo.com) that the user is already using. In any case the user must register only once with his OpenID service provider and therefore he need only one password. You can read more about the details on openid.net.

Using OpenID in a Web Application

There are different solutions available to enable a Web Application to login users with there OpenID url. One of the most auspicious mechanisms to integrate OpenID in JEE Applications is the jsr-196. This authentication service allows web containers to use different login modules - like an external openid provider. JSR-196 is part of Glassfish Server so a Login Mechanism based on the jsr-196 is very easy to use in a JEE or Web application. Ron Monzillo who is the specification lead gives a good overview about the jsr-192 on his blog  "concepts behind JRS-196".

The OpenSSO extension jsr196

As a subproject of the OpenSSO Project Ron has published a first implementation of a OpenID Login Module based on the OpneID Standard 1.0. in june 2008. I joined this project and started the work with Ron on this implementation. There is an Issue List available where you can see topics of the current work. And also the sources can be downloaded frome here: https://opensso.dev.java.net/source/browse/opensso/extensions/jsr196/

We implemented a new parser to optimize the handshake between the login module and the openid provider and in 2009 I added different enhancements. Finally I implemented a new version of the Login Module which now supports also OpenID 2.0 Providers like yahoo.com. This new login module is located in the package com.sun.security.sam.openid2 and is called OpenIDServerAuthModule. 

You can download the latest version of the library containing this OpenID Login Module from here: (sam.openid-0.0.1-SNAPSHOT.jar).

In the next part I will explain how you install the login module and which configuration on glassfish server is necessary.

In Part III. I will show how you enable your web application to logon users with an openID.

If you have any comments or suggestions let me know

Friday Nov 07, 2008

Generate MS-Word from Servlet will not work in IE ??

Today I spent a very long time to figure out why my JEE Servlet was unable to generate a dynamic MS Word document. - No the servlet dose generate a dynamic MS Word document!. But IE 7.0 in Windows XP with MS Office 2007 was not able to open the generated MS Word document! This was strange because using Firefox on Windows or also using Firefox on Linux Plattform works perfect! So why the hell IE on windows did not open MS Word?

After a long long frustrating period I found out that the solution is to not only set the ContentType to 'application/ms-word' but also set two additional header attributes to get word open on Windows Plattform.

So my servlet output code looks like this - at it works:

public class TestServlet extends javax.servlet.http.HttpServlet {

HttpServletRequest request;
HttpServletResponse response;

protected void doGet(HttpServletRequest arequest,
HttpServletResponse aresponse) throws ServletException, IOException {
this.request = arequest;
this.response = aresponse;
String sEncoding = "utf-8";
response.setCharacterEncoding(sEncoding);
response.setContentLength(5);
response.setContentType("application/msword;charset=utf-8");

response.setHeader("Content-disposition", "attachment; filename"
+ "Example.doc");
response.setHeader("Pragma", "public");
response.setHeader("Cache-Control", "cache");
response.setHeader("Cache-Control", "must-revalidate");

ServletOutputStream out = response.getOutputStream();
out.println("Hallo");
out.flush();
out.close();

}

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}

A helpful thread about this topic can be read here:

http://forums.sun.com/thread.jspa?threadID=586671

I can not understand wy Microsoft always needs so much welfare? "Convention over configuration" seems not be the rule for Microsoft.....

Monday Sep 01, 2008

New Version 1.6 of Imixs IX JEE Workflow

Yesterday I stated to work on new Version 1.6 of IX Workflow API and IX JEE Workflow Server. The new release will include a ReportService. This feature will be implemented as a kind of top-level feature. I decided to include the Report functionality directly into the workflow implementation as lot of people ask for a feature to run reports on a workflow management system.

Read more on

http://www-02.imixs.com:8081/roller/imixsworkflow/

or check out source code :

https://ix-workflow.dev.java.net/source/browse/ix-workflow/

Sunday Jul 06, 2008

using JNDI MailSession in Glassfish

Today I played around a long time figuring out how to lookup a Java Mail Session out of a EJB from Glassfish. This is the link which finaly helps me through:

http://forums.java.net/jive/thread.jspa?messageID=260133&#260133

before I read a lot of pages like:

https://glassfish.dev.java.net/javaee5/docs/DG/beaow.html

http://forums.java.net/jive/thread.jspa?messageID=265263&#265263

The problem for me was the lookup like thisone:

 Context ic = new InitialContext();
Session session = (Session)ic.lookup("java:comp/env/mail/testSession");

 To avoid a :

javax.naming.NameNotFoundException: No object bound to name java:comp/env/mail/testSession

 it is importend to add the right name mapping to the ejb-jar.xml and also to the sun-ejb-jar.xml

to the ejb-jar.xml add the following code to that EJB which makes the lookup:        

    <resource-ref>
        <res-ref-name>mail/testSession</res-ref-name>
        <res-type>javax.mail.Session</res-type>
        <res-auth>Container</res-auth>
        <res-sharing-scope>Shareable</res-sharing-scope>
    </resource-ref>

And to the sun-ejb-jar.xml file add the following to the same EJB

 <resource-ref>
        <res-ref-name>mail/testSession</res-ref-name>
        <jndi-name>testSession</jndi-name>
 </resource-ref>

Notice that this is only necessary to perform a jndi lookup. I think you can save oneself this using dependency injection using annotations (@ressource)

Wednesday Jun 18, 2008

Form based authentification using Facelets

Yesterday I found out how to configure my JEE Web Application with form-based login. In general it is not difficulty to secure a JEE Web Application with form based login. This is explained on lot of websites like this one: http://www.developinjava.com/readarticle.php?article_id=6

The problem I stumbled into was that my Web Application uses the facelets framework. So I have a lot of general layout parts like css and images which I wanted to use also in my Login Form and also some help pages which should be accessible without authentification.

To divide the web application into a restricted and a public area (where no authentification is needed) is easy:

in the web.xml you can specify the secured JSP pages separated in a folder e.g:

 <security-constraint>
    <web-resource-collection>
      <web-resource-name>restricted</web-resource-name>
      <url-pattern>/faces/pages/*</url-pattern>
       <http-method>GET</http-method>
      <http-method>POST</http-method>
    </web-resource-collection>
    <auth-constraint>
      <role-name>org.imixs.ACCESSLEVEL.AUTHORACCESS</role-name>
    </auth-constraint>
  </security-constraint>

The Login.xhtml which I placed outside my secured /pages folder makes use of facelets technology and looks as followed:

 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:z="http://www.qualcomm.com/jsf/core"
    xmlns:c="http://java.sun.com/jstl/core"
    xmlns:fn="http://java.sun.com/jsp/jstl/functions">

<ui:composition template="/layout/layout.xhtml">
    <ui:define name="content">
        <form
            method="post"
            action="#{facesContext.externalContext.requestContextPath}/j_security_check">
        <table>
            <tr>
                <td>User name:</td>
                <td><input type="text" name="j_username" /></td>
            </tr>
            <tr>
                <td>Password:</td>
                <td><input type="password"  name="j_password" /></td>
            </tr>
            <tr>
                <td><input type="submit"  value="Login" /></td>
            </tr>
        </table>
        </form>
    </ui:define>
</ui:composition>
</html>

/layout/layout.xhtml is accessible without authentification as this page is not placed inside my secured /pages/ folder. So the login.xhtml page looks perfect styled!

The real problem was how to jump into a secured page? I first have had a navigation.jsp page with a lot of jsf command links like:

<h:commandLink actionListener="#{workitemListBean.doRefresh}"
                    action="show_workitemlist">

My Navigation rule for "show_workitemlist" points to a secured page in the /pages folder.

faces-config.xml: 

......
    <navigation-case>
            <from-outcome>show_worklist</from-outcome>
            <to-view-id>/pages/workflow/worklist.jsp</to-view-id>
    </navigation-case>

But these commandLinks will not work because the JSF Framework will invoke all backing beans which are connected to the target page behind the navigation rule "show_workitmelist". And all my backing beans invoke a lot of EJBs which are secured using declarative JEE security.

So my command link did not show up the login.xhtml form as expected but throws a lot of "permission denied" exceptions :-(

The trick is to forward the anonymous user direct to the faces/ URL to access the secured page without JSF Navigation Rules. So I replaced my <h:commandLink> with a simple anchor tag:

<a href="#{facesContext.externalContext.requestContextPath}/faces/pages/workflow/worklist.jsp">
                <h:outputText value="#{global.login}" /></a>

So the result of these anchor tag is that the non authenticated user requests a secured page from my /faces/pages URL Pattern as defined in the web.xml.

The webContainer will invoke my Login Page, authenticate the user and after a successful login the JSF Framework starts up and builds all the necessary things to view the page with all backing-beans and EJBs. As the user is now authenticated everything works perfect as JSF has all the principal stuff and user informations to invoke my secured EJBs!

So: do not use commandLinks to login an anonymous user in a JSF Application inside a Facelets layouted login page.