I'm trying to implement an authentication/authorization module just for check username and password, in a Java EE application with JAAS. I'm using Jboss EAP 6.1 to deploy. But I get 403 (Access Denied) after use LoginModule in all pages for my webapp. My LoginModule is hard coded to check "user123" and "pass123", and put a "admin" role to my user.
import javax.security.auth.Subject;
import javax.security.auth.callback.*;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;
import java.io.IOException;
import java.security.Principal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class LoginMod implements LoginModule {
private CallbackHandler handler;
private Subject subject;
private UserPrincipal userPrincipal;
private RolePrincipal rolePrincipal;
private String login;
private List<Principal> userGroups;
private boolean succeeded = false;
@Override
public void initialize(
Subject subject,
CallbackHandler callbackHandler,
Map<String, ?> sharedState,
Map<String, ?> options)
{
handler = callbackHandler;
this.subject = subject;
}
@Override
public boolean login() throws LoginException
{
Callback[] callbacks = new Callback[2];
callbacks[0] = new NameCallback("login");
callbacks[1] = new PasswordCallback("password", true);
try {
handler.handle(callbacks);
String name = ((NameCallback) callbacks[0]).getName();
String password = String.valueOf(((PasswordCallback) callbacks[1])
.getPassword());
if (name != null &&
name.equals("user123") &&
password != null &&
password.equals("pass123")) {
System.out.println("\t\t[LoginMod] login:"+name);
login = name;
userGroups = new ArrayList<Principal>();
userGroups.add(new RolePrincipal("admin"));
succeeded = true;
return true;
}
throw new LoginException("Authentication failed");
} catch (IOException e) {
throw new LoginException(e.getMessage());
} catch (UnsupportedCallbackException e) {
throw new LoginException(e.getMessage());
}
}
@Override
public boolean commit() throws LoginException
{
if (succeeded == false) {
return false;
} else {
userPrincipal = new UserPrincipal(login);
subject.getPrincipals().add(userPrincipal);
if (userGroups != null && userGroups.size() > 0) {
for (Principal role : userGroups) {
rolePrincipal = new RolePrincipal(role.getName());
subject.getPrincipals().add(rolePrincipal);
}
}
System.out.println("\t\t[LoginMod] subject contains the role:"+
subject.getPrincipals().contains(rolePrincipal));
return true;
}
}
@Override
public boolean abort() throws LoginException
{
System.out.println("\t\t[LoginMod] Aborted" );
return false;
}
@Override
public boolean logout() throws LoginException
{
subject.getPrincipals().remove(userPrincipal);
subject.getPrincipals().remove(rolePrincipal);
return true;
}
}
I create a security domain and put a reference for this module in my standalone.xml:
<security-domains>
<security-domain name="acfwebRealm" cache-type="default">
<authentication>
<login-module code="acfweb.autenticacao.teste.LoginMod" flag="required"/>
</authentication>
</security-domain>
</security-domains>
And declare the realm in my app a jboss-web.xml file:
<?xml version='1.0' encoding='UTF-8'?>
<jboss-web>
<context-root>acfweb</context-root>
<security-domain>acfwebRealm</security-domain>
</jboss-web>
In my web.xml I have:
<welcome-file-list>
<welcome-file>interfaces/pages/index.xhtml</welcome-file>
</welcome-file-list>
<security-constraint>
<web-resource-collection>
<web-resource-name>Usuarios Autenticados</web-resource-name>
<url-pattern>/interfaces/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>admin</role-name>
</security-role>
<login-config>
<auth-method>FORM</auth-method>
<realm-name>acfwebRealm</realm-name>
<form-login-config>
<form-login-page>/logar.xhtml</form-login-page>
<form-error-page>/logar.xhtml</form-error-page>
</form-login-config>
</login-config>
I create a j_ form to use the LoginModule, and this calls my LoginModule correctly.
<form method="post" action="j_security_check">
<h:panelGrid columns="2">
<h:outputLabel value="Username: " />
<input type="text" id="j_username" name="j_username" />
<h:outputLabel value="Password: " />
<input type="password" id="j_password" name="j_password" />
<h:outputText value="" />
<h:panelGrid columns="1">
<input type="submit" name="submit" value="Login" />
</h:panelGrid>
</h:panelGrid>
<br />
</form>
After sending the form data my server console show me the LoginModule sysout log:
INFO [stdout](http-/127.0.0.1:8080-2) [LoginMod] login:user123
INFO [stdout](http-/127.0.0.1:8080-2) [LoginMod] subject contains the role true
And then I get 403 (Access Denied), for all pages after that.
Actually I don't need to authenticate my users in database, or an external LDAP, because I have another service available for this. Maybe I don't need an complete security module using JAAS, but I need control my users by roles in my EJBS, without send data representing my users in every call from Managed Beans to EJBs, captured by a Servlet filter e.g. Anyone could help me? What I'm doing wrong in this LoginModule? What is my options for described requirements?