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; } }