package org.jboss.seam.security.jaas;
import static org.jboss.seam.security.Identity.ROLES_GROUP;
import java.security.acl.Group;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
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.login.LoginException;
import javax.security.auth.spi.LoginModule;
import org.jboss.seam.core.Expressions.MethodExpression;
import org.jboss.seam.log.LogProvider;
import org.jboss.seam.log.Logging;
import org.jboss.seam.security.Identity;
import org.jboss.seam.security.SimpleGroup;
import org.jboss.seam.security.SimplePrincipal;
import org.jboss.seam.security.management.IdentityManager;
/**
* Performs authentication using a Seam component
*
* @author Shane Bryzak
*/
public class SeamLoginModule implements LoginModule
{
private static final LogProvider log = Logging.getLogProvider(SeamLoginModule.class);
protected Set<String> roles = new HashSet<String>();
protected Subject subject;
protected Map<String,?> options;
protected CallbackHandler callbackHandler;
protected String username;
public boolean abort() throws LoginException
{
return true;
}
public boolean commit() throws LoginException
{
subject.getPrincipals().add(new SimplePrincipal(username));
Group roleGroup = null;
for ( Group g : subject.getPrincipals(Group.class) )
{
if ( ROLES_GROUP.equalsIgnoreCase( g.getName() ) )
{
roleGroup = g;
break;
}
}
if (roleGroup == null) roleGroup = new SimpleGroup(ROLES_GROUP);
for (String role : roles)
{
roleGroup.addMember(new SimplePrincipal(role));
}
subject.getPrincipals().add(roleGroup);
return true;
}
public void initialize(Subject subject, CallbackHandler callbackHandler,
Map<String, ?> sharedState, Map<String, ?> options)
{
this.subject = subject;
this.options = options;
this.callbackHandler = callbackHandler;
}
public boolean login()
throws LoginException
{
try
{
NameCallback cbName = new NameCallback("Enter username");
PasswordCallback cbPassword = new PasswordCallback("Enter password", false);
// Get the username and password from the callback handler
callbackHandler.handle(new Callback[] { cbName, cbPassword });
username = cbName.getName();
}
catch (Exception ex)
{
log.warn("Error logging in", ex);
LoginException le = new LoginException(ex.getMessage());
le.initCause(ex);
throw le;
}
// If an authentication method has been specified, use that to authenticate
MethodExpression mb = Identity.instance().getAuthenticateMethod();
if (mb != null)
{
try
{
return (Boolean) mb.invoke();
}
catch (Exception ex)
{
log.warn("Error invoking login method", ex);
LoginException le = new LoginException(ex.getMessage());
le.initCause(ex);
throw le;
}
}
// Otherwise if identity management is enabled, use it.
IdentityManager identityManager = IdentityManager.instance();
if (identityManager != null && identityManager.isEnabled())
{
Identity identity = Identity.instance();
try
{
boolean success = identityManager.authenticate(username, identity.getCredentials().getPassword());
if (success)
{
for (String role : identityManager.getImpliedRoles(username))
{
identity.addRole(role);
}
}
return success;
}
catch (Exception ex)
{
log.warn("Error invoking login method");
LoginException le = new LoginException(ex.getMessage());
le.initCause(ex);
throw le;
}
}
else
{
log.error("No authentication method defined - " +
"please define authenticate-method for <security:identity/> in components.xml");
throw new LoginException("No authentication method defined");
}
}
public boolean logout() throws LoginException
{
return true;
}
}