This week's book giveaway is in the Mac OS forum.
We're giving away four copies of a choice of "Take Control of Upgrading to Yosemite" or "Take Control of Automating Your Mac" and have Joe Kissell on-line!
See this thread for details.
The moose likes JBoss/WildFly and the fly likes java.lang.SecurityException: Authentication exception, principal=null Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


JavaRanch » Java Forums » Products » JBoss/WildFly
Bookmark "java.lang.SecurityException: Authentication exception, principal=null" Watch "java.lang.SecurityException: Authentication exception, principal=null" New topic
Author

java.lang.SecurityException: Authentication exception, principal=null

Seji Thomas
Greenhorn

Joined: Oct 31, 2004
Posts: 6
I am deploying a EAR file in JBoss-4.0.0RC2 version, which is exported from Websphere Studio Application Developer. The application runs fine in Websphere 5.0. I have added lot of jboss specific configuration files like

1. jboss.xml
2. jboss-web.xml
3. db2-ds.xml
4. jaws.xml
5. login-config.xml
6. auth.conf
in the appropriate directories as specified in most of the documentation, and referring also to mail postings on configuring application to JBoss. JNDI names, and DataSource for JBoss connection pooling are been set properly. Connection pool is also created successfully. I have a JAAS LoginModule to be configured, for which I have made changes to the jboss.xml, jboss-web.xml, and login-config.xml files in an appropriate manner. But as the application server is started I get an error as mentioned in the subject. Also when I inspect the log file - server.txt, I see an exception as below

'DEBUG [org.jboss.web.tomcat.security.SecurityAssociationValve] Failed to determine servlet'.

Can any one help me resolve this. Any help on this matter is highly appreciated.

--Seji
Seji Thomas
Greenhorn

Joined: Oct 31, 2004
Posts: 6
Last week I successfully ported the application on to JBoss (It was very difficult to find what configuration changes was needed to port it to JBoss).

Now my issue is how to associate security roles for JAAS authenticated user?

In the web.xml file, at present I have commented out all the <security-constraint>, <login-config>, and <security-role> elements (authentication mechanism is form-based). I need to associate the roles defined in this file to all the authenticated users(JAAS authentication) so that they can access the application. At present the JAAS authentication is happening properly, but since the roles in web.xml are not associated to authenticated user, I am getting the following exception on the browser window - 'HTTP Status 403 - Access to the requested resource has been denied'. Does any one know how to associate these roles to authenticated user? In Websphere Application server there is a way to associate roles to 'All Authenticated users' and 'Everyone'. Is there any thing similiar in JBoss? I am using JBoss Version-4.0.0.RC2. Any help in this regard is highly appreciated. Thanks a tonne........
Seji Thomas
Greenhorn

Joined: Oct 31, 2004
Posts: 6
Finally the web security roles are also being associated to the JAAS authenticated user. What I have done is created a JBoss specific LoginModule (MyUserLoginModule.java) which extends the org.jboss.security.auth.spi.UsernamePasswordLoginModule which uses my applications LDAPLoginModule to authenticate the user. If this is successful it associates roles (APPUser, and Public) by invoking a getRoleSets() method which is specific to JBoss. This is the class which has been written is given below

package com.sample.security.authentication;

import java.security.acl.Group;
import java.util.*;
import java.util.HashMap;
import java.util.Map;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;

import javax.security.auth.Subject;
import java.security.Principal;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.FailedLoginException;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.jboss.security.SimpleGroup;
import org.jboss.security.SimplePrincipal;
import org.jboss.security.NestableGroup;
import org.jboss.security.auth.spi.UsernamePasswordLoginModule;

import com.sample.security.authentication.LDAPLoginModule;

public class MyUserLoginModule extends UsernamePasswordLoginModule
{
private static Log log = LogFactory.getLog(MyUserLoginModule.class);
private String username;
private char[] password;
private Principal identity;
private char[] credential;
private String hashAlgorithm = null;
private com.sample.security.LDAPLoginModule lm = null;
private boolean succeeded = false;
private Subject subject;

public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options)
{
super.initialize(subject, callbackHandler, sharedState, options);
this.subject=subject;
lm = new com.sample.security..LDAPLoginModule();
lm.initialize(subject, callbackHandler, sharedState, options);
}

public boolean login() throws LoginException
{
super.loginOk = false;
String[] info = getUsernameAndPassword();
String username = info[0];
String password = info[1];
if( username == null && password == null )
{
identity = unauthenticatedIdentity;
if(log.isDebugEnabled())
{
log.debug("Authenticating as unauthenticatedIdentity="+identity);
}
}

if( identity == null )
{
identity = new SimplePrincipal(username);
if(log.isDebugEnabled())
{
log.debug("Before LDAP login");
}
succeeded = lm.login();
if(log.isDebugEnabled())
{
log.debug("LDAP login status "+succeeded);
}
if( hashAlgorithm != null )
password = createPasswordHash(username, password);
String expectedPassword = getUsersPassword();

}


if( getUseFirstPass() == true )
{
sharedState.put("javax.security.auth.login.name", username);
sharedState.put("javax.security.auth.login.password", credential);
}
super.loginOk = succeeded;
if(log.isDebugEnabled())
{
log.debug("User '" + identity + "' authenticated, loginOk="+loginOk);
}
return super.loginOk;
}

public boolean commit() throws LoginException
{
try{
if(log.isDebugEnabled())
{
log.debug("commit, loginOk="+loginOk);
}
if( loginOk == false )
return false;
if(log.isDebugEnabled())
{
log.debug("before principals");
}
Set principals = subject.getPrincipals();
if(log.isDebugEnabled())
{
log.debug("principals="+principals);
}
if(log.isDebugEnabled())
{
log.debug("identity="+identity);
}
principals.add(identity);
if(log.isDebugEnabled())
{
log.debug("Add identity to principal");
}
Group[] roleSets = getRoleSets();
if(log.isDebugEnabled())
{
log.debug("Got rolesets");
}
for(int g = 0; g < roleSets.length; g ++)
{
Group group = roleSets[g];
if(log.isDebugEnabled())
{
log.debug("Got rolesets = "+group);
}
String name = group.getName();
if(log.isDebugEnabled())
{
log.debug("Got group name = "+name);
}
Group subjectGroup = createGroup(name, principals);
if(log.isDebugEnabled())
{
log.debug("Got subjectGroup = "+subjectGroup);
}
if( subjectGroup instanceof NestableGroup )
{
/* A NestableGroup only allows Groups to be added to it so we
need to add a SimpleGroup to subjectRoles to contain the roles
*/
SimpleGroup tmp = new SimpleGroup("Roles");
if(log.isDebugEnabled())
{
log.debug("Got SimpleGroup = "+tmp);
}
subjectGroup.addMember(tmp);
if(log.isDebugEnabled())
{
log.debug("Adding member to subjectGroup");
}
subjectGroup = tmp;
if(log.isDebugEnabled())
{
log.debug("Got subjectGroup = "+subjectGroup);
}
}
// Copy the group members to the Subject group
Enumeration members = group.members();
while( members.hasMoreElements() )
{
Principal role = (Principal) members.nextElement();
if(log.isDebugEnabled())
{
log.debug("Got Principal = "+role);
}
subjectGroup.addMember(role);
if(log.isDebugEnabled())
{
log.debug("Adding role to subjectGroup");
}
}
}
}
catch(Exception le){
if(log.isDebugEnabled())
{
log.debug("LoginException encountered, "+ le);
}
}

return true;
}

public boolean abort() throws LoginException
{
lm.abort();
if(log.isDebugEnabled())
{
log.debug("abort");
}
return true;
}



public boolean logout() throws LoginException
{
lm.logout();
if(log.isDebugEnabled())
{
log.debug("logout");
}
// Remove the user identity
Set principals = subject.getPrincipals();
principals.remove(identity);
// Remove any added Groups...
return true;

}


protected String getUsersPassword() throws LoginException
{
if (callbackHandler == null)
throw new LoginException(
"Error: no CallbackHandler available "
+ "to gather authentication information from the user");
Callback[] callbacks = new Callback[2];
callbacks[0] = new NameCallback("Dummy Prompt:");
callbacks[1] = new PasswordCallback("Dummy Prompt:", false);
try
{
callbackHandler.handle(callbacks);
username = ((NameCallback) callbacks[0]).getName();
char[] tmpPassword =
((PasswordCallback) callbacks[1]).getPassword();
password = new char[tmpPassword.length];
System.arraycopy(tmpPassword, 0, password, 0, tmpPassword.length);
((PasswordCallback) callbacks[1]).clearPassword();
if(log.isDebugEnabled())
{
log.debug("UserName = "+ username + ", Password = " + String.valueOf(password));
}
return String.valueOf(password);
}
catch (java.io.IOException ioe)
{
throw new LoginException(ioe.toString());
}
catch (UnsupportedCallbackException uce)
{
throw new LoginException(
"Error: "
+ uce.getCallback().toString()
+ " not available to gather authentication information "
+ "from the user");
}

}


protected Group[] getRoleSets() throws LoginException
{
String username = getUsername();
HashMap setsMap = new HashMap();
//Adding Web security roles for now hard coded
String name1 = "APPUser";
String name2 = "Public";
String groupName = "Roles";
Group group = (Group) setsMap.get(groupName);
if( group == null )
{
group = new SimpleGroup(groupName);
setsMap.put(groupName, group);
}
group.addMember(new SimplePrincipal(name1));
if(log.isDebugEnabled())
{
log.debug("Adding Roles"+ name1);
}
group.addMember(new SimplePrincipal(name2));
if(log.isDebugEnabled())
{
log.debug("Adding Roles"+ name2);
}
Group[] roleSets = new Group[setsMap.size()];
setsMap.values().toArray(roleSets);
return roleSets;
}

}

In the jboss-web.xml, I declare the a security domain as below.....

<security-domain>java:/jaas/MyApps</security-domain>

JBoss finds the appropriate LoginModule in the login-config.xml file. The entry for the same is as below.....

<application-policy name = "MyApps">
<authentication>
<login-module code="com.sample.security.authentication.MyUserLoginModule"
flag="required" />
</authentication>
</application-policy>


With this configuration whenever I am trying to login to the application it shows me the login page defined in the web.xml file as below......

<form-login-page>/jsp/login.jsp</form-login-page>

The above page has to be constructed observing the following.

1. This login.jsp needs to have form elements for accepting user name, and password with names 'j_username', and 'j_password' respectively, and

2. The form action should be '/j_security_check'.

I supply my valid LDAP userid, password. Gets authenticated and gets the relevant web-security roles through my custom LoignModule.


I have a question now. Does the JBoss App Server have an option to specify that all authenticated users be given the web-security roles to access the web resources (which I suppose is checked by the web-container to show the resource - lack of role mappings for the user result in 403- forbidden exception)? In Websphere and Weblogic we have that option. Also is there any way to bypass the login page declared by web.xml (<form-login-page>/jsp/login.jsp</form-login-page> so that we can use our application specific login functionality and at the same time associate web roles as what I have done.

Thanks for reading this long prose.....
Any help on this is most welcome.

Seji
Jeff Shelley
Ranch Hand

Joined: May 21, 2003
Posts: 70
The only way I can think of is like what you did, but you could probably put those into the login-config file as options, so at least you don't have to change the code. something like this

<application-policy name = "myPolicy">
<authentication>
<login-module code = "com.whatever.security.MyLogin"
flag = "required">
<module-option name = "principal"></module-option>
...
<module-option name = "AllUserRoles">common,hasEmail</module-option>
</login-module>
</authentication>
</application-policy>


Or something like that. Or you could add an extra lookup to your ldap somethere and stuff them in there. But I don't think jboss will add that for you. Does anybody else know?


It's almost Friday
Seji Thomas
Greenhorn

Joined: Oct 31, 2004
Posts: 6
Thanks a lot for your reply.

I have implemented a LdapLoginModule which is extended from JBoss's LdapLoginModule, and implemented the same way as you suggested. Now every thing works fine. There is no need for hard coding the roles.

I have another post on using Kookies with JBoss. Can you please look in to it.

Thanks in Advance
Jan Ivanov
Greenhorn

Joined: Jul 20, 2006
Posts: 19
- so what does it mean ? it happens only from time to time. why ?

thank you !
 
GeeCON Prague 2014
 
subject: java.lang.SecurityException: Authentication exception, principal=null