Main | Next page »
Montag Jun 22, 2009

SIP-Communicator and Openfire

Today I installed the SIP-Communicator which is a really cool communicator software based on java. But I run into a problem connecting SIP-Communicator via the Jabber protocol with my OpenFire Server.

The problem was that I used my openfire account name directly for the "Jabber username". This did not work until I changed my "Jabber username" to the format:

myusername@myopenfire.server.com

After that change the connection from SIP-Communicator to openfire server works perfect! :-)

Samstag Mai 23, 2009

Eclipse JSF/Faclet Support in a Maven Web Project

In the following section I will describe how to configure a Maven Web Module in Eclipse Ganymede to get full support of Content assist, Hover Help and code completion for JSF and Facelets.

These features are supported by the Eclipse Web Tool Platform (WTP). So it seams not to be so difficult to configure a existing web project. But as Maven have some different in building a classpath and updating project configuration in Eclipse you need to be careful to reconfigure a Maven project. I spent a lot of time to find out why it sometimes did not work. So I hope my following walk-through will be helpful to you.

The Situation:

I have an existing Maven Web Project which I checked out from a code repository into my eclipse workspace. Therefor I used the Maven Plugin and the Maven SVN Integration Plugin.

The Maven Project I am working with is a JEE Web module with JSF and Faclets support and also uses the JBoss RichFaces JSF components.So the goal is to get content assist when editing a .xhtml faclets file in my web project.

The Facelets Plugin

To get things run I need first to install the faclets plugin for eclipse.  The reason for adding this plugin is that a faclets application typical uses .xhtml pages to represent the jsf resources. The Eclipse WTP did not support .xhml files per deault so the faclets plugin will add the JSF features to also .xhtml files. Additional the plugin includes some wizzards and a new WTP Facete.

You can download the plugin from here. Extract the file and copy the jars into your /plugin folder of your Eclipse Ganymede. Next restart Eclipse!

Adding a JSF Implementation and Server Runntime

Next step is to add a JSF Implementation into you Eclipse Workspace. You can use any Implementation. I take the JSF Implementation form my Glassfish server.  There is a Blog where  Cay Horstmann explains the details:
http://weblogs.java.net/blog/cayhorstmann/archive/2007/07/jsf_support_in.html

So open the Eclipse preferences dialog and go to Web->JavaServer Faces->Libraries.

Create a new JSF library and name the library "GlassfishJSF-impl". Add only the jsf-impl.jar file. This file is located in the /glassfish/lib folder from your glassfish installation.



Important: Make sure that the option "is JSF Implementation" is checked!

Next add the Server Runtime. Select the Server Node and add your JEE Server (in my case glassfish)

 

Now Restart you Eclipse!

Add the Server and JSF Libraries to the Java Build Path

Next check the "Java Build Path" settings of your Web Project. You need now to add two libraries to your project.

The Server Runtime Library of Glassfish and the JSF Implementation which added before to the workspace environment.

Click "Add Library..." and select "Server Runtime"

 

Choose the Glassfish Server from the Server Runtime list. Click finish.

Next I add the JSF Library created before. So click again "Add library..." and add a JSF Library and select you GlassfishJSF-Impl created before:

 

Finally your project library settings should look like this

Add the JSF and Faclets Facets

Next you need to add the Project Facets for JSF 1.2 support and Facelet 1.0. A Facet is a WTP specific feature which adds additional tools and features to a web project. The Facelet 1.0 Facete is an additional feature added by the Facelet plugin I added before.

To add a new Facete you open the preference dialog for your web project and select the "Project facets" node.

If this Node is not present in you project preferences Eclipse has not recognized your Maven web project as a Eclipse Web Project. So you need first to add the WTP Nature to your project manually.

  1. Switch in the "Navigator" View
  2. open the file ".project"
  3. add the nature
      <nature>org.eclipse.wst.common.project.facet.core.nature</nature>
  4. save the .project file

Now you can add the different facets in the following order:

  1. Select Java 5.0
  2. Select Dynamic Web Module 2.5
    after that you can see the link "Further configuration available" - open the dialog




    As I am working in a maven project I change the Content and Java Source Directory into
    /src/main/webapp
    /src/main/java
    which are the default maven source folders
    Also I unchecked the "Generate deployment descriptor" as my maven project still have the necessary descriptors.




  3. Next Select "JavaServerFaces 1.2".
    Again there is "Further configuration required"
    You can select the option "Server Supplied JSF Implementation"



    Choose the "Next" Button to switch through the different config pages.

  4. Finally add the "Facelet 1.0 " support.
    Again there is "Further configuration available"



    I disabled all options as my maven project is well configured

  5. Finally restart eclipse

Now you should have the content assist and hover help in your xhtml files.
Eclipse is parsing all necessary libraries so also my RichFaces tags are now known by Eclipse!

The first time you get the content assist from Eclipse it will take some time as Eclipse needs to analyze the tag libraries. 


If it did not work...

In some cases this did not work. Then the main reason seams to be that the Eclipse java build classpath is not well configured. Check the Java Build Path settings. Remove and add some Libraries - this will help Eclipse to update the Workspace settings and restart Eclipse. Also wait some time after restart until Eclipse have finished all inizalizing.

Donnerstag Mai 21, 2009

Error deploying EAR on Glassfish - error expanding jar

Today I was faced again with a deployment problem on glassish. When I tried to deploy my EAR application on glassfish I got some strange errors telling me that Glassfish was not able to expand some jars in my ear. In other cases an error can be that glassfish is did not find a jar in ear.

The problem occurs only when I build my EAR with Maven inside Eclipse Ganymed on a Windows Mashine. The Reason is the missing version tag in the ear pom file

....
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<configuration>
<version>5</version>
<modules>
.....  

I often did not use the version tag in the configuration of my maven-ear-plugin. But if you do so in Eclipse ganymede running on a windows machine the Eclipse/Maven Plugins will generate a EAR 1.3 Module! So the build process will add a wrong application.xml file into the ear.

This is strange as using eclipse on linux did not run into this configuration conflict.

anyway - do not miss the version tag in your ear pom! And if you run in the situation described here also clear your maven projects befor you run a new install. otherwise the old applicaiton.xml fill will stay in you target folder!

Dienstag Mai 19, 2009

Escape Problem downloading Files form a Web / JSF Application

Today I stumbled into a problem with my JSF Web Application supporting File Upload/Download Functionality.

Everything works fine until some user uploaded files with "blank" in the filename e.g. "my fantastic long filename.doc" or files with german characters like "große datei mit wörtern.doc"

The Upload of sees files is no problem for my JSF up. But if a user tries to download such a file an error 404 occurs.

My JSF Implementation supports a typical form to download the files from a file list. It looks like this:

 <h2>Download</h2>

<c:forEach var="attachment" items="#{workitemLobBean.files}">
<h:outputLink target="_blank"
value="#{facesContext.externalContext.requestContextPath}/Service/$file/#{attachment}">
<h:outputText value="#{attachment}" />
</h:outputLink>
<br />
</c:forEach>

So the filenames will be escaped into something like :

"my+fantastic+long+filename.doc"

which leads into the error 404. To avoid this escaping I used the following trick (not very nice but it works)

 <h2>Download</h2>

<c:forEach var="attachment" items="#{workitemLobBean.files}">
<h:outputText escape="false" value="&lt;a target='_balnk' href='" />
<h:outputText escape="false" value="#{facesContext.externalContext.requestContextPath}/Service/$file/#{attachment}" />
<h:outputText escape="false" value="'&gt;#{attachment}&lt;/a&gt;" />

<br />
</c:forEach>

If you find a better solution to escape filenems in JSF output let me know.

Mittwoch Apr 15, 2009

Using @runas in EJB 3.0

Today I implemented a EJB where I used the @runas annotation the first time.

This annotation allows you to skip over the security settings in your EJB module. I use the Imixs IX JEE Workflow so I have to deal with the workflow IX Workflow roles. My new EJB should create a new workflow task triggered by a not authenticated user (anonymous). So my EJB need the workflow role "org.imixs.ACCESSLEVEL.AUTHORACCESS" to get access to the workflow model and the grant to create a new workitem. This can be decleared by the @runas annotation in the EJB implemenation


package org.imixs.business;

....
@Stateless
@DeclareRoles( { "org.imixs.ACCESSLEVEL.AUTHORACCESS" })
@RunAs("org.imixs.ACCESSLEVEL.AUTHORACCESS")
public class ContactServiceBean implements ContactService {

// Workflow Manager
@EJB
org.imixs.workflow.jee.ejb.WorkflowManager wm;
ItemCollection workItem = null;

/**
* This method creates a new Contact worktiem.
*/
public ItemCollection create() throws Exception {
// create emtpy workitem
workItem = wm.createWorkItem(INITIAL_PROCESS);
workItem.replaceItemValue("type", "contact");
return workItem;
}
.....
}

Next it is necessary (I am running on Glassfish server) to add a User Principal to the sun-ejb-jar.xml and also declare the pricipal:

sun-ejb-jar.xml:

 

 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sun-ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 9.0 EJB 3.0//EN" "http://www.sun.com/software/appserver/dtds/sun-ejb-jar_3_0-0.dtd">
<sun-ejb-jar>
<security-role-mapping>
<role-name>org.imixs.ACCESSLEVEL.READERACCESS</role-name>
<principal-name>org.imixs.ACCESSLEVEL.READERACCESS</principal-name>
</security-role-mapping>
<security-role-mapping>
<role-name>org.imixs.ACCESSLEVEL.AUTHORACCESS</role-name>
<principal-name>org.imixs.ACCESSLEVEL.AUTHORACCESS</principal-name>
</security-role-mapping>
<security-role-mapping>
<role-name>org.imixs.ACCESSLEVEL.EDITORACCESS</role-name>
<principal-name>org.imixs.ACCESSLEVEL.EDITORACCESS</principal-name>
</security-role-mapping>
<security-role-mapping>
<role-name>org.imixs.ACCESSLEVEL.MANAGERACCESS</role-name>
<group-name>IMIXS-WORKFLOW-Manager</group-name>
<principal-name>WorkflowScheduler</principal-name>
</security-role-mapping>
<enterprise-beans>
<ejb>
<ejb-name>ContactServiceBean</ejb-name>
<jndi-name>ejb/ShareyourworkContactServiceBean</jndi-name>
<principal><name>WorkflowScheduler</name></principal>
</ejb>
</enterprise-beans>
</sun-ejb-jar>


Now the principal "WorkflowScheduler" is named as a principal in my EJB declaration and is mapped to the role "org.imixs.ACCESSLEVEL.MANAGERACCESS" this user will be able to call my EJB methods. As this role is declared as a @runas role in my contactEJB the principal "WorkflowScheduler" will be used by the EJB container to run the methods in my ejb.


Freitag Apr 10, 2009

Using OpenID for JForum

Today I want to post the solution I developed to use OpenID in JForum.

There are different Solutions for OpenID Authentication Modules. As I am running JForum on Glassfish Server I decided to use set OpenIDAuthModul based on JSR-196 . This module is easy to install see my blog OpenID for JEE Appplications Part II.

So now when you have installed the OpenID Module and configured on Glassfish there are only a few steps to complete.

1.) Add sun-web.xml

To use JSR-196 athtentication in you JForum you need to add a sun-web.xml which points to your OpenID Provider.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sun-web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 9.0 Servlet 2.5//EN" "http://www.sun.com/software/appserver/dtds/sun-web-app_2_5-0.dtd">

<sun-web-app error-url="" httpservlet-security-provider="OpenID2">
<context-root>/shareyourwork/jforum</context-root>
<security-role-mapping>
<role-name>user</role-name>
<principal-name>user</principal-name>
<group-name>Author</group-name>
</security-role-mapping>
<class-loader delegate="true" />
<jsp-config>
<property name="keepgenerated" value="true">
<description>Keep a copy of the generated servlet class javacode.</description>
</property>
</jsp-config>
</sun-web-app>  

Notice the Security Role Mapping I am using here! I map the JForums role "user" to my default Group "Auhtor" which I configured in my OpenID Autmodule as explained in Part II of my OpenID Blog.

2. Change web.xml

Next I changed the web XML to force a Login when Users access my JForum (this is wy we need not more Registration in JForum)

<security-constraint>
<web-resource-collection>
<web-resource-name>Restricted Area</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>user</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>user</role-name>
</security-role>

3. Implement a SSO Module for JForum

Next we need a so called SSO Moduel for JForum. This is a JForum specific way to allow individual authentification mechanism. Read more about JForums sso here.

This is the class I implemented:

package org.imixs.login;

import java.util.Collection;

import javax.servlet.http.Cookie;

import net.jforum.ControllerUtils;
import net.jforum.JForumExecutionContext;
import net.jforum.context.RequestContext;
import net.jforum.entities.UserSession;
import net.jforum.sso.SSO;
import net.jforum.util.preferences.ConfigKeys;
import net.jforum.util.preferences.SystemGlobals;

import org.imixs.workflow.ItemCollection;
import org.imixs.workflow.jee.ejb.EntityServiceRemote;

/**
* Simple SSO Implemetation for JForum
*
* @author Ralph Soika
* @version 0.0.1
*/
public class SSOLogin implements SSO {

String userName;
String userID;
String email;

public final String COOKIE_NAME = "jforumUserId";

public String authenticateUser(RequestContext request) {
String sUser = request.getRemoteUser();
userName = sUser;
if (sUser != null) {
// here you can complete user spcific informations if necessary
try {
/*
* Code was taken from
* http://www.jforum.net/doc/ImplementSSO
*/
ControllerUtils.addCookie("JforumSSO", userName); // refresh
}

} catch (NamingException e) {
System.out.println("------ SSO LOGIN - Error ");
e.printStackTrace();
}

}

return userName;
}

/**
* Code was taken from
*
* http://www.jforum.net/doc/ImplementSSO
*
*/
public boolean isSessionValid(UserSession userSession,
RequestContext request) {
String remoteUser = null;
Cookie SSOCookie = ControllerUtils.getCookie("JforumSSO");
if (SSOCookie != null)
remoteUser = SSOCookie.getValue(); // jforum username

// user has since logged out
if (remoteUser == null
&& userSession.getUserId() != SystemGlobals
.getIntValue(ConfigKeys.ANONYMOUS_USER_ID)) {
return false;

// user has since logged in
} else if (remoteUser != null
&& userSession.getUserId() == SystemGlobals
.getIntValue(ConfigKeys.ANONYMOUS_USER_ID)) {
return false;

// user has changed user
} else if (remoteUser != null
&& !remoteUser.equals(userSession.getUsername())) {
return false;
}
return true; // myapp user and forum user the same
// return true;
}

}
 

This code did not do much as I use the OpenID URL as the UserName used by JForum.

I an internal project we added some individual code in into the method authenticateUser() to get the Username and Email from a different application. But this is not necessary if you allow users to complete there profile in JForum. The Profile will be generated automatically.

4.) Customize SystemGlobals.properties.

  FinallyI customized the SystemGlobals.properties (located in  WEB-INF/config/).

....
authentication.type = sso
login.authenticator = net.jforum.sso.DefaultLoginAuthenticator
sso.implementation = org.imixs.login.SSOLogin
....

Conclusion

So this was an easy way for me to allow users to work with there OpenID (like yahoo.com accounts) in my JFourm. If you have any suggestions you can post your comments here.

Sonntag Apr 05, 2009

OpenID for JEE Applications - Part III

Now I will explain how you can configure your web application to use openid for login mechanism. If you have installed the OpenID Login module like described in part II. this step is quiet easy. 

web.xml & sun-web.xml

The first thing what you should do is remove existing tag login-config like basic or form-based authentification configuration from the web.xml if available. You now only need the security-constraint configuration.

This is an example of the security-constraint seciton in my web.xml

....
<security-constraint>
<display-name>Access Manager Security Constraint</display-name>
<web-resource-collection>
<web-resource-name>AUTHENTICATED_RESOURCE
</web-resource-name>
<url-pattern>/pages/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>org.imixs.ACCESSLEVEL.AUTHORACCESS
</role-name>
</auth-constraint>
</security-constraint>

<security-role>
<role-name>org.imixs.ACCESSLEVEL.AUTHORACCESS
</role-name>
</security-role>
.....

Next you need to specify your openid provider configured on glassfish admin client in the sun-web.xml. 

Therefor you need to add the attriubte "httpservlet-security-provider" with the name of your openid provider

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sun-web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 9.0 Servlet 2.5//EN" "http://www.sun.com/software/appserver/dtds/sun-web-app_2_5-0.dtd">
<sun-web-app error-url="" httpservlet-security-provider="OpenIDProvider">

<context-root>/openidtestclient</context-root>

<security-role-mapping>
<role-name>org.imixs.ACCESSLEVEL.AUTHORACCESS</role-name>
<group-name>Author</group-name>
</security-role-mapping>

<class-loader delegate="true" />
<jsp-config>
<property name="keepgenerated" value="true">
<description>Keep a copy of the generated servlet class java
code.</description>
</property>
</jsp-config>
</sun-web-app>

Thats it!

 

Now you application supports OpenID.

Role Mapping

Notice that we mapped also our default group "Author" to a application specific Rolename. The Group "Author" was configured in the OpenIDProvider property "assign.groups". So each user how have successfull authtenticated against his OpenID Proivder will default to this group and the role  "org.imixs.ACCESSLEVEL.AUTHORACCESS". You can change this settings to the requriements of your application.

Login Form

If you did not specific a login form with the additional property "loginpage" the OpenID Login Module will answer an unautenticated reqeust with an simple login form as shown above.

You can implement you own login form if you like and use this form as the default form for you openidProvider module. 

There for add the property "loginpage"  to your provider configuration and support a valid Page inside your application or a simple HTTP page located on a web server.

This is a simple example for a individual login form based on JSF :

	<form method="get"
action="#{facesContext.externalContext.requestContextPath}/openid_login">
<f:facet name="header">
<h:outputLabel value="#{global.login_title} " />
</f:facet>
<h:panelGrid columns="2">
<h:outputLabel value="#{global.username}:" />
<h:inputText id="openid_identifier" />

<h:inputHidden id="return_to"
value="#{loginMB.serverURI}#{facesContext.externalContext.requestContextPath}/pages/notes.jsf" />

</h:panelGrid>
<input type="submit" value="#{global.login}" />


<!-- BEGIN ID SELECTOR -->
<script type="text/javascript" id="__openidselector"
src="https://www.idselector.com/selector/e0ed3a269b77fa785de90aeaa20fa0f985746767"
charset="utf-8"></script>
<!-- END ID SELECTOR -->
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
var pageTracker = _gat._getTracker("UA-3469303-6");
pageTracker._trackPageview();
</script>
</form>
 

Your form need to care about three things:

  1. The form action method need to point to the method path "/openid_login". This path indicates the OpenIDLogin Module to start an OpenID Login process.
  2. The users Input field to enter his OpenID URL should be named "openid_identifier". Make sure that the "name" and "ID" attriubte are set to "openid_identifier"
  3. The form must support a hidden field "return_to" with points to a page where the user is redirected after login process succeed.

 

The ID Selector Script is just a funny script provided by http://www.idselector.com to support the user with a nice widget to simplify using openid.

Single Sign On (SSO)

OpenID supports single sing on. This means if your application knows the users OpenID you can easily logon the user to different pages from different web applications on the same server. To use this feature you only need to redirect the authenticated user to a new site providing his identity and the return url in the QueryString.

For example:

http://myhost/mynewapplication?openid.identity=[http://usersopenid]&openid.return_to=[http://myhost/mynewapplication]

The login process now depends on the users openid provider settings. Some providers like myid.net give the user a convenient way to control his personal settings for different pages and applications using openid

Conclusion

You can see that using JSR-196 and OpenID is a very comfortable way to support a new and easy to use login mechansim for web applications. For internet applications openid opens you web site to millions of users. It is easy to use and you dont have to handle all the stuff with managing userids and passwords.

As OpenID servers are also available als OpenSource JSR-196 and OpenID can be a competitive way for enterprises to implement a single sign on (SSO) architecture in an intranet or extranet.

If you have any suggestions or comments let me know.

Samstag Apr 04, 2009

OpenID for JEE Applications - Part II

In Part I. I described the general concepts behind the JSR 196 and the OpenID integration in Glassfish. Now I would like to explain how you can configure a OpenLogin Provider in Glassfish. 

To configure a OpenID Provider in glassfish you need first the libary containg the OpenID Login Module. You can download the latest version of the library containing this OpenID Login Module from here: (sam.openid-0.0.1-SNAPSHOT.jar).
Next you can put the jar file simply into the <GF_HOME>/lib folder of your Glassfish installation.

Configuration of a OpenID Login Provider

You can configure the OpenID Login Provider using the GlassFish Admin Console following the next steps:

  1. Make sure the GlassFish Application Server is running. If it is not already running, you can start it using the following command:
       <GF_HOME>bin/asadmin start-domain domain1

    where <GF_HOME> is the directory where you installed GlassFish

  2. Open the GlassFish Admin Console by pointing your browser to the URL: http://localhost:4848/.
  3. Login to the Admin Console by entering your ID and password.
  4. Expand the Configuration node at the bottom of the left-hand pane.
  5. Navigate to the Security node, expand it, and click MessageSecurity.




  6. Under Message Security Configurations, either open the HttpServlet layer if it already exists, or create it if it doesn't exist by clicking the New button. Clicking the button opens the New Message Security Configuration window.
  7. If you can not see the HttpServlet node you need to create the layer:

     

     Click the "New" button and you can than start to configure the new provider in one step. To do that:

    • Set the following in the New Message Security Configuration window:

      Provider Type: server
      Provider ID: OpenIDProvider
      Class Name: SAM, that is, com.sun.security.sam.openid2.OpenIDServerAuthModule

      Do not check the Default Provider: Enabled check box.

       

    • Click the OK button. This saves the settings and opens the Message Security Configurations window.
    • Click on HttpServlet in the Authentication Layer column.
    • Select the Providers tab. This opens the Provider Configuration window.
    • Select OpenIDProvider in the Provider ID column you just created. This opens the Edit Provider Configuration window.
    • Click the Save button to complete the configuration of the provider.

    If the HttpServlet layer already exists, you open first the provider list and add a new Provider:

    • Open the HttpServlet layer by selecting it in the Message Security Configurations window.
    • Select the Providers tab to open the Provider Configuration window.




    • Click the New button to open the New Provider Configuration window.
    • In the Provider Configuration area of the window, set the following:

      Provider Type: server
      Provider ID: OpenIDProvider
      Class Name: SAM, that is, com.sun.security.sam.openid2.OpenIDServerAuthModule

      Do not check the Default Provider: Enabled check box.

For the first configuration this is a little bit confusing as you need to create the HttpServlet Layer. But in general the hole configuration is very simple. 

Also note that the provider configuration utility also provides a dialog box that you can use to configure additional properties. We will use this properties to configure out OpenIDProvider for our applications.

Configure additional Properties

After adding the new OpenIDProvider like described before you can start using the provider in your web application. But there a also a few additional properties which can be configured for each provicer instance. You cann add these properties by using the box "additional properties at the end of you confiugration page:

 

The different properties and there usage are described below:

assign.groups

This property is the most important one. It defines which group will be assigend to a user how has loged on with its OpenID. Typical this is a default group used in your web application. 

debug

Defines is login module will print debug messages on the console file. Remove this property to turn debug modus off.

debug.stages

This property allows you define different debug stages. So you can follow the different phases during the logon process on the server log. Remove this property to turn the debug modus off.

loginpage

Per default the login module will promt the user with a simpel login page where he can enter his OpenID url. You can replace this default page with a individueal page supported by your web application (simmilar to a form based authentification). We will descuss this later.

verifymode

This property can be set to "once" or "allways". If the property is set to "once" the login module will verify the OpenID Token only first time the user enters a restricted page. If set to "allways" (default) the token will be verified for every request of a restricted ressource.


OpenID for JEE Applications - Part I

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

Samstag Mrz 28, 2009

Eclipse: maven install from runAs menu fails

A few days ago I updated my eclipse Ganymede via the update manager. After that I was unable to build my Maven projects with from the "runAs -> maven install" context menu:

I got the following error when I try to build my EAR module

 [INFO] org.imixs.callcenter.ear .............................. FAILED [0.634s]
[INFO] ------------------------------------------------------------------------
[ERROR]

The following mojo encountered an error while executing:
Group-Id: org.apache.maven.plugins
Artifact-Id: maven-ear-plugin
Version: 2.3.1
Mojo: ear
brought in via: packaging: ear

While building project:
Group-Id: org.imixs.examples
Artifact-Id: org.imixs.callcenter.ear
Version: 0.0.2
From file: /home/rsoika/eclipse-ganymede/sywapp/org.imixs.callcenter/org.imixs.callcenter.ear/pom.xml
Reason: Cannot copy a directory: /home/rsoika/eclipse-ganymede/sywapp/org.imixs.callcenter/org.imixs.callcenter.web/target/classes; Did you package/install active project artifact:
artifact = org.imixs.examples:org.imixs.callcenter.web:war:0.0.2:compile;
project: MavenProject: org.imixs.examples:org.imixs.callcenter.web:0.0.2 @ /home/rsoika/eclipse-ganymede/sywapp/org.imixs.callcenter/org.imixs.callcenter.web/pom.xml?



[INFO] ------------------------------------------------------------------------
[INFO] For more information, run with the -e flag
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILED

 

I can build all modules separately and it seams to be an known issue form the  m2eclipse plugin (http://jira.codehaus.org/browse/MNGECLIPSE-1173)

The problem  seams to be the "Resolve Workspace artifacts" option. My workarround was to use my own "run as" configuration.

 

When I use these settings (see "Resolve Workspace artifacts" is disabled!) everything works fine for me.

But I did not find out how to change the "Resolve Workspace artifacts" option in general for eclipse.


Mittwoch Mrz 04, 2009

Using JNDI and JavaMail with SMTP auth

Today I stumbled into a problem configuring a SMTP Mail session in Glassfish to be used out from my EJB.

My SMTP Host requires an authentification with a username and a special password.

Using the javax.mail.api the following params are responsible for a authenticated connection.

mail.smtp.host
mail.smtp.user
mail.smtp.password


The problem is that these params can not be read - or better will not be provided to the configured mail session in glassfish.

Here is a bugreport which explains the problem and show how the params need to be named:

https://glassfish.dev.java.net/issues/show_bug.cgi?id=4515

also there is a useful thread which a general descussion how to establish a authenticated smtp session:

http://forums.sun.com/thread.jspa?threadID=615393&start=0&tstart=0

So the smtp params in glassfish need to be renamed as followed:

mail-smtp.host
mail-smtp.user
mail-smtp.password

Freitag Feb 27, 2009

postfix and no worthy mechs found

Today I configured postfix on my unbutu machine to test some improvements sending out mails to a smtp mail server.

I followed this introductions: 

http://wiki.ubuntuusers.de/Postfix

My smtp server / relayhost needs an authentification. So I configured my main.cf with the following smtp params:

smtp_sasl_auth_enable = yes
# noplaintext weglassen, wenn Passwörter im Klartext übertragen werden müssen:
# (nicht empfohlen, nur wenn's anders nicht funktioniert)
smtp_sasl_security_options = noplaintext noanonymous
smtp_sasl_password_maps = hash:/etc/postfix/sasl_password

But now I received the following error message on my mail.log

Feb 28 00:25:44 xxx postfix/smtp[8756]: warning: SASL authentication failure: No worthy mechs found
Feb 28 00:25:44 xxx postfix/smtp[8756]: 2794717E510: to=<xxa@xx.com>, relay=www.xxx.com[xxxxxxx]:25, delay=21, delays=0.05/0.01/21/0, dsn=4.7.0, status=deferred (SASL authentication failed; cannot authenticate to server xxx[xxx]: no mechanism available)

To solve this problem I found this thread:

http://www.zimbra.com/forums/installation/1240-cannot-sasl-authenticate-server.html

So the solution for me was to set the following two smtp params to an empty string:

smtp_sasl_security_options =
smtp_sasl_mechanism_filter =
smtp_use_tls = no

Now postfix works fine and is able to send out mails to my relayhost.

Samstag Feb 07, 2009

RichFaces - TinyMCE Support

Since the new version 3.3 of RichFaces JSF Framework was released the TinyMCE Editor is now included in RichFaces! This is a cool feature and allows you to use the full featured TinyMCE Editor in your richfaces webapp.

To activate the Editor use the following tag:

    <rich:editor  theme="advanced" 
           value="#{myMB.content}" />

also it is possible to customize the editor in any way TinyMCE allows customization. So I use the following configuration to change width attribute and toolbar options:

        <rich:editor id="details_id"  theme="advanced" 
            plugins="fullscreen" value="#{workitemMB.item['htmldetail']}">
            <f:param name="theme_advanced_buttons1"
                value="fullscreen,undo,redo,cleanup,|,formatselect,bold,italic,underline,|,justifyleft,justifycenter,justifyright,justifyfull,bullist,numlist,insertdate,inserttime,hr,outdent,indent,|,link,unlink" />
            <f:param name="theme_advanced_buttons2" value="" />
            <f:param name="theme_advanced_buttons3" value="" />
            <f:param name="theme_advanced_toolbar_location" value="top" />
            <f:param name="theme_advanced_toolbar_align" value="left" />
            <f:param name="width" value="95%" />
            <f:param name="height" value="260" />
        </rich:editor>

Donnerstag Jan 22, 2009

RichFaces - Background for Input Fields

I played around a long time to found out to avoid RichFaces to set a background color for all input fields.

If you are using your own Skin all Input Fields will appear with a background image. This image has a "color-fading" effect. The effect can be general controlled by the following contxt-parameter in the web.xml file:

    <context-param>
        <param-name>org.richfaces.CONTROL_SKINNING</param-name>
        <param-value>enable</param-value>
    </context-param>

The image is generated by RichFaces from the skin property 'additionalBackgroundColor'. So my first thought was to set this attribute to 'FFFFFF'. After that each input field apears without the background. But a side effect of this change is that also all menues have no more mouse-over effect - every menue entry is now white (FFFFFF)  :-(

So it is no good idea to change the skin Attribute 'additionalBackgroundColor' to white!

So my solutions was to override the css definition of the input files using a custom css file like this:

textarea, textarea[type="textarea"], input[type="text"], input[type="password"], select {
    background-color:#FFFFFF;
    background-image: none;
    border-color: silver;
}

It works fine for me and all input fields appear now with white background and a silver border.

Sonntag Dez 07, 2008

RichFaces - How to handle external Login mechanism like OpenID

Today I found a solution for a login problem I was faced with since a long time using RichFaces and Facelets in my JEE Web App.
The problem was that my Login Form uses an external login mechanism (OpenID) to log in the user.
After the first successful login the RichFaces page is not loaded correctly (styles and scripts are not loaded). If the user reloads the page after the first login everything works well.
I saw that some people are faced with this problem in similar situations. So I will try to explain my solution I found today.

My application has to areas - a unrestricted (/*) and a restricted (/secured/*) area. So when the user try to access a restricted (RichFaces) page (e.g. /secured/page-a.jsf) my loginForm - located in the unrestricted area (/login.jsf) appears. So the user can first perform a login. Typical for OpenID the login mechanims is handled by a Servlet. The Servlet knows the first Request to the restricted page. After successful login the Servlet will redirect the user again to that restricted page. But this (RichFaces)page now will not be rendered correctly because the request goes no longer through the RichFaces Servlet Filter. So CSS and Scrips will not be loaded!
I solved this situation as I changed the startup mechanism of my application. The first thing the user will see is the Loginpage itself! The LoginPage is located in an unrestricted area. Now after the user logged in successfull, the login form (servlet) will redirect the user to an restricted RichFaces Page. And in this case the restricted RichFaces Page will be rendered correctly as the full request goes now through the RichFaces Servlet Filter. This works as there is no cascading redirect through different servlets.

I know that this sounds a little bit confusing but it works for me. If you have found other solutions for that problem please let me know.