Hi!
Because of a respone to my blog post Perform programmatic logon I decided to provide a bit more complete example of how to use the jboss WebAuthentication. I will show how to do the logon in two ways, by an action in a handler and
by doing it in a servler. Logging in by executing an action in a handler could be nice in cases where you have a page that is open to the public, but if you log in you get access
to more information or features.
First I provide an example of a login-config that I’ve tested and used successfully with the WebAuthentication method,
<application-policy name = "myApplication">
<authentication>
<login-module code = "org.jboss.security.auth.spi.DatabaseServerLoginModule" flag = "required">
<module-option name = "dsJndiName">java:/myDatasource-ds</module-option>
<module-option name = "principalsQuery">Select password from user_table where user_name =?</module-option>
<module-option name = "rolesQuery">Select 'user', 'Roles', 'RoleGroups' from user_table where user_name =?</module-option>
<module-option name ="hashAlgorithm">md5</module-option>
<module-option name="hashEncoding">hex</module-option>
<module-option name="debug">false</module-option>
</login-module>
<login-module code="org.jboss.security.ClientLoginModule" flag="required" />
</authentication>
</application-policy>
Create a LoginHandler or something similar, with a method login() and two helper-methods getRemoteUser and getUserPrincipal. Something like this:
public class LoginHandler
{
public String login()
{
WebAuthentication webAuthentication = new WebAuthentication();
String hardcodedUserName = "user@somewhere.com";
String hardcodedPassword = "user123";
if (webAuthentication.login(hardcodedUserName, hardcodedPassword))
{
System.out.println("Logged in successfully");;
log.debug("userPrincipal: " + getUserPrincipal());
log.debug("remoteUser: " + getRemoteUser());
}
else
{
log.debug("Login failed");
}
return "";
}
public String getUserPrincipal()
{
FacesContext context = FacesContext.getCurrentInstance();
ExternalContext externalContext = context.getExternalContext();
return externalContext.getUserPrincipal() != null ? externalContext.getUserPrincipal().toString() : "null";
}
public String getRemoteUser()
{
FacesContext context = FacesContext.getCurrentInstance();
ExternalContext externalContext = context.getExternalContext();
String remoteUser = externalContext.getRemoteUser();
return remoteUser;
}
}
For this example we basically hardcode the username/password, and just test if we get login to work. You should of course use a page and navigation-rules or smth similar to set the username/password as properties in the loginHandler.
Then create a simple jsp, but don’t put it inside your protected folder. Create it one level up so that you can access it without being asked to log in.
In this jsp you will have a stupid commandButton, as well as two outputs that displays the remoteUser and userPrincipal:
<f:view >
<t:document>
<t:documentHead>
<f:loadBundle basename="MessageResources" var="messages" />
</t:documentHead>
<f:verbatim>
<body>
</f:verbatim>
<h:form>
<h:panelGrid>
<h:commandButton value="Login" action="#{loginHandler.login}"></h:commandButton>
<h:outputText value="User Principal: #{loginHandler.userPrincipal}"></h:outputText>
<h:outputText value="Remote User: #{loginHandler.remoteUser}"></h:outputText>
</h:panelGrid>
</h:form>
<f:verbatim>
</body>
</f:verbatim>
</t:document>
</f:view>
Now, launch your application by going to this page. You will see that userPrincipal shows “null” and remoteUser is empty. Press the Login button.
When the page reloads it should display your username in both outputTexts. If you check your log or console it should say “Logged in successfully.”
The user is now properly set in the web container. Also, if you now try to change the url to go to one of your protected pages,
you should not be redirected to any login.jsp, but the page should display properly – because you are already logged on.
Then, to do the logon from a servlet there’s really not a big difference. I set up my web.xml to use a FORM-based logon, like this:
<login-config>
<auth-method>FORM</auth-method>
<form-login-config>
<form-login-page>/login.faces</form-login-page>
<form-error-page>/loginFailed.faces</form-error-page>
</form-login-config>
</login-config>
I also register my LoginServlet in web.xml like this:
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.test.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/LoginServlet</url-pattern>
</servlet-mapping>
My login.jsp is 99% the same as when using j_security_check, we just point the action to the LoginServlet instead:
<form method="POST" name="loginform" action="${pageContext.request.contextPath}/LoginServlet">
<table style="vertical-align: middle;">
<tr>
<td>Username:</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>
My LoginServlet uses the parameters that was originally passed to the j_security_check. Also, if we successfully log on, we get the “Referer” from the request to redirect to the page that originally was the target for the user. I did not include the code that handles if the logon failed here:
public class LoginServlet extends HttpServlet
{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
// TODO Auto-generated method stub
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
String user = req.getParameter("j_username");
String pass = req.getParameter("j_password");
WebAuthentication webAuthentication = new WebAuthentication();
if( webAuthentication.login(user, pass))
{
String redirectUrl = "";
String referer = req.getHeader("Referer");
resp.sendRedirect(redirectUrl);
return;
}
else
{
System.out.println("Login attempt failed " + user);
...
Handle incorrect logon, go back to login page etc
...
}
}
}
So, to test this, start your application by pointing directly to some page that is protected. Your login.jsp should be presented, and when you press Login
the servlet uses the credentials you passed in the forms, authenticates and redirect you to the page.
For debug reasons you could add the same outputTexts here on this page (remoteUser and userPrincipal), and they SHOULD show the user you logged in with now.
There is also no problem to navigate to other protected pages.
Hope that these examples might help anybody that struggles with this!
16.04.2008 at 04:04:31
Hi,
This article is really good and you have explained it beautifully. I am going to try it now and was really hoping to get it worked !!
Thanks again for this wonderful post.
~Murali
30.06.2008 at 17:06:24
Hi,
thanks for this tutorial, the best I found for this subject.
I try to integrate it in my framework, but I’m blecked since 2 days with an exception “request is null”, while calling “login”:
WebAuthentication pwl = new WebAuthentication();
pwl.login(login, password);
java.lang.IllegalStateException: request is null
at org.jboss.web.tomcat.security.login.WebAuthentication.login(WebAuthentication.java:80)
it is thrown by WebAuthentication class :
public class WebAuthentication
public boolean login(String username, Object credential)
{
//Get the active request
Request request = (Request) SecurityAssociationValve.activeRequest.get();
if(request == null)
throw new IllegalStateException(“request is null”);
Could it be caused by the jboss 4.2.1 version I use ?
I don’t see differences between 4.2.1 and 4.2.2 in theses classes…
Should I configure something in tomcat ?
thanks,
Damien
02.07.2008 at 11:07:31
Hi Damien,
Sorry for not having replied to you earlier.
I believe that the problem is in the difference of the implementation of the security layer in 4.2.1 and 4.2.2. I haven’t tried to do this witth 4.2.1, but all jboss references I find state that WebAuthentication is available from version 4.2.2 and up..
Probably your easiest try is to test with the newer version of jboss?
- E -
05.08.2008 at 17:08:47
Damien,
We faced exactly the same problem as you did on Jboss 4.2.2. We narrowed it down to jbossweb-service.jar in our .war file. You need this file at the compile time for WebAuthentication class but since Jboss already has this in its runtime, this file should be excluded from the war.
Let me know if that helps.
Ritesh
03.09.2008 at 15:09:58
Ritesh & Damien,
I’m running into the same problem and I am not including the the WebAuthentication class in my war file. Damien, did you find a resolution to this.
Thanks.
Micah
07.11.2008 at 14:11:30
Hi, i have the same problem:
java.lang.IllegalStateException: request is null at org.jboss.web.tomcat.security.login.WebAuthentication.login
I’m using jBoss 4.2.3
Thanks,
Fer.
13.11.2008 at 09:11:06
Fer,
Are you sure that you’re not including the jbossweb-service.jar in your web-app lib folder? It should not be deployed as part of your application, it already exists in jboss inside the server/deploy/jboss-web.deployer dir.
Regards,
Eivind
20.11.2008 at 20:11:11
Hi,
thanks for this article, it helped me a lot but i’m still facing a problem.
i have set a custom jsf login webapp at /login that uses the same JAAS security-domain than another webapp deployed at /app2.
I can succesfully login thanks to the jsf login app but when i’m going to the /app2, it seems that my second app does not see that i’m logged in.
I’m usins jboss 4.2.3 with webauthentication as shown in the article.
Have any idea ? thanks.
21.11.2008 at 09:11:31
Guybedo,
Jboss have said that the support for the single-sign-on valve in combination with the programmatic logon (WebAuthentication) will not work till jboss 5. So I don’t think there are any proper solutions to this problem right now.
Regards,
Eivind
05.06.2009 at 00:06:45
Hi,
Congratulations, very complete article!
I’m facing a problem trying to get a jboss-4.2.3 work with WebAuthentication authentication and single sign on (ExtendedSingleSignOn valve). I’m facing a lot of problems in the EJB layer (Authentication Failure Exception) and I’m very woried about the fact that it maybe never work. Could you point me where you find this information about sso and programmatic authentication work only in jb 5?
Thanks in advance!
29.06.2009 at 11:06:21
Hi,
I myself have used the jboss wiki to aqquire the knowledge I have about jboss programmatic logon and SSO.
I would suggest you to go here, http://www.jboss.org/community/wiki/WebAuthentication, and maybe you from there can find an answer to your question.
I see that ExtendedSSO are stated to work also with 4.2.3 now, but I’ve never done this myself – so I can’t help you there..
Regards,
Eivind
20.01.2009 at 17:01:05
Hi,
When i tray this webauthentication code I have the following errors:
17:01:51,106 ERROR [UsersRolesLoginModule] Failed to load users/passwords/role files
java.io.IOException: No properties file: users.properties or defaults: defaultUsers.properties found
at org.jboss.security.auth.spi.Util.loadProperties(Util.java:315)
Can any help me?
Thanks
21.01.2009 at 13:01:20
Dalil,
This is because of some problems with your login-config and the security-domain that is set up. Somewhere you have done a mistake, and it tries to load the default login module which is the UsersRolesLoginModule.
Please check the naming you have used in:
* jboss-web.xml: The security-domain parameter shold be something like java:/jaas/myPolicyName
* the login-config.xml: The application-policy name parameter should match the way you spelled it in jboss-web.xml. In this example it would be application-policy name = “myPolicyName”
And then, if you use a njdi lookup for the database, make sure that in the login-config the dsJndiName is set to match your dataSource configuration. Example: java:/userDb-ds
Then you would need to have a datasource config in your deploy-dir that matches the jndi name like this:
userDb-ds
It can also be a connection problem for the datasource you specified, so verify that you can connect to the db with some other tool using the same parameters.
Good luck!
01.02.2009 at 16:02:50
Situation with “java.lang.IllegalStateException: request is null at org.jboss.web.tomcat.security.login.WebAuthentication.login” occurs when you attempt to execute login in a servlet mapped to “form-login-page”. It looks like SecurityAssociationValve is not activated in this case and that make a problem. Try to execute WebAuthentication.login in some test action which is not bound to a secured resource to avoid side effects.
04.02.2009 at 09:02:50
Montall,
Thanks for input!
- E -
18.03.2009 at 15:03:58
Hi,
I am also facing same kind of issue and using Jboss 4.2.3. The server log shows that the correct values are passed for user and password (testuser, testuser123) but i am unable to login. I have the required configuration for JAAS in place.
Also when i try to print the values using the above helper-methods getRemoteUser and getUserPrincipal, I see “null” in my log. Please help as I am unable to login.
My server log is as below:
**CUTTED**
19.03.2009 at 09:03:47
Lisha,
I would need to see your Jaas configuration (login-config) top be able to help you much. But this is just a wild guess, is the role ‘Roles’ included in your rolesProperties/queries? It’s mandatory for jboss that the group/role of the user is ‘Roles’. If it’s not there, login would fail.
As it says on this page: http://www.jboss.org/community/docs/DOC-9511
07.05.2009 at 13:05:41
hi,
thanks for the article!
i have the same problem with java.lang.IllegalStateException: request is null @ at org.jboss.web.tomcat.security.login.WebAuthentication.login(WebAuthentication.java:88)
BUT i am using JBoss 5.0.1.GA.
the jar file jbossweb-service.jar seems not to be contained in the distribution of jboss 5? so i tried to copy jbossweb-service.jar into my WEB-INF/lib from the jboss-4.2.3GA distribution. but this leads to the described problem.
has anyone got this working with jboss 5? where to get the jbossweb-service.jar (contains the WebAuthentication class) from and where to put it?
thanks,
jonas
07.05.2009 at 14:05:50
Jonas,
I’m running jboss 5.0.1 GA myself – even though I haven’t tested WebAuthentication on this version yet. But I find the jar file in the JBOSS_HOME\server\default\deploy\jbossweb.sar directory. It’s named jboss-web-service.jar, and contains the WebAuthentication class.
Hope that helps you!
- E-
07.05.2009 at 14:05:27
update on previous post.
I like those jboss guys, they are so funny. the jar is RENAMED and located at jboss-5.0.1.GA\server\default\deploy\jbossweb.sar\jboss-web-service.jar (notice the difference: jboss-web-service.jar instead of old jbossweb-service.jar).
so i removed the jar from the WEB-INF/lib but still the same problem with java.lang.IllegalStateException: request is null
any help would be really appreciated.
thx,
jonas
12.05.2009 at 12:05:02
Hi Eivind,
I have pointed portal’s db to oracle.I am trying to point my own DB just for login credentials. and for it i created 3 tables in my DB. I have not used encryption for password in DB.
The changes i made in jboss portal are
login-config.xml
java:/HEUSERDS
SELECT user_password FROM portal_users WHERE user_uname=?
SELECT portal_roles.role_name, ‘Roles’ FROM portal_roles_membership INNER JOIN portal_roles ON portal_roles_membership.role_rid = portal_roles.role_rid INNER JOIN portal_users ON portal_roles_membership.user_uid = portal_users.user_uid WHERE portal_users.user_uname=?
Authenticated
inside authentication tag.
The dsJndiName here used is to point my DB(Just for login).
i have not changed
jdbc/PortalDS
java:PortalDS
in jboss-web.xml of portal-server.war/WEB-INF
Should i mention jdbc/HEUSERDS here?
I have added
LoginServlet
org.bimal.tryout.LoginServlet
LoginServlet
/LoginServlet
[/code]
in web.xml of portal-server.war/WEB-INF
and this LoginServlet have been used as the action of login.jsp of portal-server
The code of LoginServlet.java is as follows
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String user = req.getParameter("j_username");
String pass = req.getParameter("j_password");
String baseURL = "/portal/auth/dashboard";
String referer = null;
System.out.println(user);
WebAuthentication webA = new WebAuthentication();
if(webA.login(user, pass)){
System.out.println(user);
System.out.println(pass);
System.out.println("Logged in successfully");
System.out.println(req.getRemoteUser() +"\n"+ req.getUserPrincipal());
referer = req.getHeader("Referer");
System.out.println(referer);
System.out.println(req.getRemoteUser());
System.out.println(req.getUserPrincipal());
resp.sendRedirect(baseURL);
} else {
referer = req.getHeader("Referer");
System.out.println(referer);
resp.sendRedirect(baseURL);
}
}
Here in this code, req.getRemoteUser() and req.getUserPrincipal() are not null and they are returning user. but still i am getting
HTTP Status 500 - No authenticated user while accessing /portal/auth/dashboard when LoginServlet redirects to /portal/auth/dashboard.
If i point to /portal it shows user logged in, but dashboard link is not present.
If the user is with admin role then Admin links appear and it's fully functional too.
But what is going on with Dashboard.
The Dashboard, Configure Dashboard links dont appear.
One thing to mention is I am using JBoss Portal 2.7.2 bundled edition, which has JBoss AS 4.2.3.
What might be the solution of it.
10.06.2009 at 19:06:58
So I got this all working well and good without too much trouble in JBoss 4.2.2.
A few questions though. Is it expected that you store the WebAuthentication in your servlet request’s Session? If not, do you just store the username and password into the Session, and use those to validate the WebAuthentication on each request, by using a servlet filter? At the end of each request you would want to log out too? ( i.e. webAuthentication.logout() )
If you use the WebAuthentication would you still want to use the LoginContext through a JAAS mechanism and save that into the Session so you can use that for EJB stuff?
Now I need to figure out what stuff I could try to backport to get the SSO in JBoss working in JBoss 4.2.2, as it seems it only works properly in JBoss 4.2.3 and higher (http://www.jboss.org/community/wiki/WebAuthentication).
04.08.2009 at 16:08:18
Hi,
a small mistake in your last code source:
String redirectUrl = “”;
String referer = req.getHeader(“Referer”);
resp.sendRedirect(redirectUrl);
I think it should be:
String referer = req.getHeader(“Referer”);
resp.sendRedirect(referer);
06.08.2009 at 12:08:06
Ondrej,
Thanks for pointing out my mistake. You are correct
Regards,
Eivind
06.08.2009 at 11:08:28
Great job! I made a nice login form using ZK framework http://zkoss.org. It works event when the login form is set as a in web.xml/
07.08.2009 at 09:08:14
Sorry for mistype, the last sentence should be: “It works even when the login page is set as in web.xml/” No null pointer exception in JBoss 5.1.0GA.
20.08.2009 at 21:08:53
We are using JBoss 4.3.0 and were hitting our heads against that NPE for both the request and response. In our valve class, I set SecurityAssociationValve.activeRequest.set(request); and
SecurityAssociationValve.activeResponse.set(response);
to the ThreadLocal public member variable and it works. This is a hack, but it works.
I wonder where in the lifecycle this class gets created?