Is this a JBP 2.6.1 bug? (403 Error From Dashboard Link)
nm-156 Sep 26, 2007 8:59 AMI have a custom JAAS LoginModule configured for JBP 2.6.1, running in AS 4.0.5. After logging in, everything looks alright with the page. The only problem is that when I click the Dashboard link, I get a 403 Access Denied error. I have added Authenticated, Users, & Admin roles to the user in my LoginModule, and I see "Logged in as 'my user'" and also I have the Dashboard | Admin |Logout links on the page after signing in.
The Admin and Logout links work correctly. When I click on the Dashboard link, I get the 403 error, but there are no exceptions when I check the log.
Is it possible that this is a bug in JBP 2.6.1? If not, is there any way to turn on a lower level trace? I do not see anything in the LoginModule examples that would imply that it is necessary to link a user with a dashboard, programmatically speaking.
Here is my LoginModule. Can you please let me know if the 403 is due to a bug in the portal, or if I am doing something wrong when adding the roles (see getRoleSets())? Thank you for any light that you can shed.
package test.custom.jaas.impl;
import java.io.IOException;
import java.security.Principal;
import java.security.acl.Group;
import java.util.Map;
import javax.naming.NamingException;
import javax.security.auth.Subject;
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.LoginException;
import org.apache.log4j.Category;
import org.jboss.security.SimpleGroup;
import org.jboss.security.SimplePrincipal;
import org.jboss.security.auth.spi.AbstractServerLoginModule;
import test.jaas.LoginAuthenticator;
import test.jaas.LoginAuthenticatorFactory;
import test.login.exception.LoginConfigurationException;
public class SsoPortalLoginModule extends AbstractServerLoginModule
{
private static final String SSO_USER_PROMPT_TEXT = "User Name: ";
private static final String SSO_PASSWORD_PROMPT_TEXT = "Password: ";
private static final Category logger = Category.getInstance(SsoPortalLoginModule.class);
private CallbackHandler callbackHandler = null;
private boolean successfulLogin = false;
private String loginUser = null;
private String loginPassword = null;
private Principal identity = null;
/**
* Default constructor
*/
public SsoPortalLoginModule(){logger.info("%%%%% CALLING SsoPortalLoginModule constructor from PORTAL %%%%%");}
/**
* Initialization method that is called by the container. Subject represents the user or service that is logging in
* and will be populated automatically. Callbackhandler is also populated by the JBoss portal because this implementation
* extends AbstractServerLoginModule
*
* @param Subject subject
* @param CallbackHandler callbackHandler
* @param Map sharedState
* @param Map options
*/
public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options)
{
logger.info("%%%%% CALLING SsoPortalLoginModule.initialize() method from PORTAL %%%%%");
// Call base class constructor. This is a requirement.
super.initialize(subject, callbackHandler, sharedState, options);
// Set internal state
setSubject(subject);
setCallbackHandler(callbackHandler);
setSharedState(sharedState);
setOptions(options);
// Set base class' loginOk variable. This flag must be set as
// a requirement for successful login
resetLoginOKInBaseClass();
}
/**
* Set subject. This object represents the user or service that is logging in.
*
* @param Subject subject
*/
private void setSubject(Subject subject)
{
this.subject = subject;
}
/**
* Login method that is called by the container
*
* @return boolean
*/
public boolean login() throws LoginException
{
return executeLDAPLogin();
}
/**
* Execute LDAP login
*
* @return boolean
*/
private boolean executeLDAPLogin()
{
try
{
// Get credentials:
getCredentials();
// Authenticate credentials against LDAP server
authenticateUserOnLDAPServer();
// Set login user as portal identity:
setLoginUserAsIdentity();
}
catch (Exception e)
{
e.printStackTrace();
resetLoginOKInBaseClass();
setSuccessfulLogin(false);
return isSuccessfulLogin();
}
setLoginOKInBaseClass();
return isSuccessfulLogin();
}
/**
* Set login user as portal identity.
*/
private void setLoginUserAsIdentity()
{
setIdentity(new SimplePrincipal(getLoginUser()));
// setIdentity(new SimplePrincipal("admin")); // ***** TEST ONLY *******
}
/**
* Use call back handler to retrieve login credentials from the user
*
* @throws IOException
* @throws UnsupportedCallbackException
*/
private void getCredentials() throws IOException, UnsupportedCallbackException
{
Callback[] callbacks = createUICallBacks();
getCallbackHandler().handle(callbacks);
extractLoginUserFromCallback(callbacks);
extractLoginPasswordFromCallback(callbacks);
}
/**
* Create callback objects that will store user input
*
* @return Callback[]
*/
private Callback[] createUICallBacks()
{
return new Callback[] {
new NameCallback(SSO_USER_PROMPT_TEXT),
new PasswordCallback(SSO_PASSWORD_PROMPT_TEXT, false)};
}
/**
* Authenticate user credentials on LDAP server
*
* @throws NamingException
* @throws LoginConfigurationException
*/
private void authenticateUserOnLDAPServer() throws NamingException, LoginConfigurationException
{
LoginAuthenticator authenticator =
LoginAuthenticatorFactory.create(LoginAuthenticatorFactory.LDAP);
setSuccessfulLogin(authenticator.isLoginValid(getLoginUser(), getLoginPassword()));
}
/**
* As per JBoss documentation, the loginOk protected variable must be set in the base
* class based on login results
*/
private void setLoginOKInBaseClass()
{
super.loginOk = true; // Set base class login flag to successful
}
/**
* Reset loginOk protected variable in base class
*/
private void resetLoginOKInBaseClass()
{
super.loginOk = false; // Reset base class login flag to false
}
/**
* Extract user ID string from Callback array
*
* @param Callback[] callbacks
*/
private void extractLoginUserFromCallback(Callback[] callbacks)
{
setLoginUser(((NameCallback)callbacks[0]).getName());
}
/**
* Extract password string from Callback array
*
* @param Callback[] callbacks
*/
private void extractLoginPasswordFromCallback(Callback[] callbacks)
{
// Be sure to create a String object from the getPassword() call or login will fail:
setLoginPassword(new String(((PasswordCallback) callbacks[1]).getPassword()));
}
/**
* Set call back handler for obtaining credentials from the user
*
* @param CallbackHandler callbackHandler
*/
private void setCallbackHandler(CallbackHandler callbackHandler)
{
this.callbackHandler = callbackHandler;
}
/**
* Return portal identity. This is the portal user ID. This method is called by the container.
*
* @return Principal
*/
@Override
protected Principal getIdentity()
{
return this.identity;
}
/**
* Get role set. This is where roles are loaded from the back end.
* Note that Group is a subinterface of Principal. This method is
* called by the container.
*
* @return Group[]
*/
@Override
protected Group[] getRoleSets() throws LoginException
{
logger.info("%%%%% CALLING SsoPortalLoginModule.getRoleSets() method from PORTAL %%%%%");
Group rolesGroup = new SimpleGroup("Roles");
rolesGroup.addMember(new SimplePrincipal("Authenticated")); // Must add authenticated principle
rolesGroup.addMember(new SimplePrincipal("Users")); // Gives portal Users rites (Test)
rolesGroup.addMember(new SimplePrincipal("Admin")); // Gives portal admin rites (Test)
// Note that the identity needs to exist as a user account inside the portal prior to login
rolesGroup.addMember(getIdentity()); // Add login identity as role (Test)
return new Group[] { rolesGroup };
}
/**
* Get call back handler. This object is used to obtain credentials from the user.
*
* @return CallbackHandler
*/
private CallbackHandler getCallbackHandler()
{
return callbackHandler;
}
/**
* Get login password string
*
* @return String
*/
private String getLoginPassword() {
return loginPassword;
}
/**
* Set login password string
*
* @param String loginPassword
*/
public void setLoginPassword(String loginPassword) {
this.loginPassword = loginPassword;
}
/**
* Get login user string
*
* @return String
*/
private String getLoginUser() {
return loginUser;
}
/**
* Set login user string
*
* @param String loginPassword
*/
private void setLoginUser(String loginUser) {
this.loginUser = loginUser;
}
/**
* This method signals whether the login attempt was successful or not.
*
* @return boolean
*/
private boolean isSuccessfulLogin() {
return successfulLogin;
}
/**
* This method sets the successful login flag.
*
* @return boolean
*/
private void setSuccessfulLogin(boolean successfulLogin) {
this.successfulLogin = successfulLogin;
}
/**
* Set login options as Map
*
* @param Map options
*/
private void setOptions(Map options)
{
this.options = options;
}
/**
* Set shared state options as Map
*
* @param Map sharedState
*/
private void setSharedState(Map sharedState) {
this.sharedState = sharedState;
}
/**
* Set portal identity
*
* @param Principal identity
*/
private void setIdentity(Principal identity)
{
this.identity = identity;
}
}