How to do it...

Follow these steps to complete this recipe:

  1. First, we will define some roles in a separate class so that we can reuse it:
public class Roles {
public static final String ROLE1 = "role1";
public static final String ROLE2 = "role2";
public static final String ROLE3 = "role3";
}
  1. Then, we need to define some things that the application's users can do:
@Stateful
public class UserActivity {

@RolesAllowed({Roles.ROLE1})
public void role1Allowed(){
System.out.println("role1Allowed executed");
}

@RolesAllowed({Roles.ROLE2})
public void role2Allowed(){
System.out.println("role2Allowed executed");
}

@RolesAllowed({Roles.ROLE3})
public void role3Allowed(){
System.out.println("role3Allowed executed");
}

@PermitAll
public void anonymousAllowed(){
System.out.println("anonymousAllowed executed");
}

@DenyAll
public void noOneAllowed(){
System.out.println("noOneAllowed executed");
}

}
  1. Let's create an interface for executable tasks:
public interface Executable {
void execute() throws Exception;
}
  1. Now, let's create another for the roles that will execute them:
public interface RoleExecutable {
void run(Executable executable) throws Exception;
}
  1. We need to create an executor for each role. An executor is like an environment that owns the rights of that role:
@Named
@RunAs(Roles.ROLE1)
public class Role1Executor implements RoleExecutable {

@Override
public void run(Executable executable) throws Exception {
executable.execute();
}
}
@Named
@RunAs(Roles.ROLE2)
public class Role2Executor implements RoleExecutable {

@Override
public void run(Executable executable) throws Exception {
executable.execute();
}
}
@Named
@RunAs(Roles.ROLE3)
public class Role3Executor implements RoleExecutable {

@Override
public void run(Executable executable) throws Exception {
executable.execute();
}
}
  1. Then, we implement HttpAuthenticationMechanism:
@ApplicationScoped
public class AuthenticationMechanism implements
HttpAuthenticationMechanism {

@Override
public AuthenticationStatus validateRequest(HttpServletRequest
request, HttpServletResponse response, HttpMessageContext
httpMessageContext) throws AuthenticationException {

if (httpMessageContext.isAuthenticationRequest()) {

Credential credential =
httpMessageContext.getAuthParameters()
.getCredential();
if (!(credential instanceof CallerOnlyCredential)) {
throw new IllegalStateException("Invalid
mechanism");
}

CallerOnlyCredential callerOnlyCredential =
(CallerOnlyCredential) credential;

if (null == callerOnlyCredential.getCaller()) {
throw new AuthenticationException();
} else switch (callerOnlyCredential.getCaller()) {
case "user1":
return
httpMessageContext.
notifyContainerAboutLogin
(callerOnlyCredential.getCaller(),
new HashSet<>
(asList(Roles.ROLE1)));
case "user2":
return
httpMessageContext.
notifyContainerAboutLogin
(callerOnlyCredential.getCaller(),
new HashSet<>
(asList(Roles.ROLE2)));
case "user3":
return
httpMessageContext.
notifyContainerAboutLogin
(callerOnlyCredential.getCaller(),
new HashSet<>
(asList(Roles.ROLE3)));
default:
throw new AuthenticationException();
}

}

return httpMessageContext.doNothing();
}

}
  1. Finally, we create the servlet that will manage all these resources:
@DeclareRoles({Roles.ROLE1, Roles.ROLE2, Roles.ROLE3})
@WebServlet(name = "/UserAuthorizationServlet", urlPatterns = {"/UserAuthorizationServlet"})
public class UserAuthorizationServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

@Inject
private SecurityContext securityContext;

@Inject
private Role1Executor role1Executor;

@Inject
private Role2Executor role2Executor;

@Inject
private Role3Executor role3Executor;

@Inject
private UserActivity userActivity;

@Override
public void doGet(HttpServletRequest request,
HttpServletResponse
response) throws ServletException, IOException {

try {
String name = request.getParameter("name");
if (null != name || !"".equals(name)) {
AuthenticationStatus status =
securityContext.authenticate(
request, response, withParams().credential(
new CallerOnlyCredential(name)));

response.getWriter().write("Authentication
status: " + status.name() + "\n");
}

String principal = null;
if (request.getUserPrincipal() != null) {
principal = request.getUserPrincipal().getName();
}

response.getWriter().write("User: " + principal +
"\n");
response.getWriter().write("Role \"role1\" access: " +
request.isUserInRole(Roles.ROLE1) + "\n");
response.getWriter().write("Role \"role2\" access: " +
request.isUserInRole(Roles.ROLE2) + "\n");
response.getWriter().write("Role \"role3\" access: " +
request.isUserInRole(Roles.ROLE3) + "\n");

RoleExecutable executable = null;

if (request.isUserInRole(Roles.ROLE1)) {
executable = role1Executor;
} else if (request.isUserInRole(Roles.ROLE2)) {
executable = role2Executor;
} else if (request.isUserInRole(Roles.ROLE3)) {
executable = role3Executor;
}

if (executable != null) {
executable.run(() -> {
try {
userActivity.role1Allowed();
response.getWriter().write("role1Allowed
executed: true\n");
} catch (Exception e) {
response.getWriter().write("role1Allowed
executed: false\n");
}

try {
userActivity.role2Allowed();
response.getWriter().write("role2Allowed
executed: true\n");
} catch (Exception e) {
response.getWriter().write("role2Allowed
executed: false\n");
}

try {
userActivity.role3Allowed();
response.getWriter().write("role2Allowed
executed: true\n");
} catch (Exception e) {
response.getWriter().write("role2Allowed
executed: false\n");
}

});

}

try {
userActivity.anonymousAllowed();
response.getWriter().write("anonymousAllowed
executed: true\n");
} catch (Exception e) {
response.getWriter().write("anonymousAllowed
executed: false\n");
}

try {
userActivity.noOneAllowed();
response.getWriter().write("noOneAllowed
executed: true\n");
} catch (Exception e) {
response.getWriter().write("noOneAllowed
executed: false\n");
}

} catch (Exception ex) {
System.err.println(ex.getMessage());
}

}
}

To try this code out, run the following URLs:

The result for user1, for example, will be as follows:

Authentication status: SUCCESS
User: user1
Role "role1" access: true
Role "role2" access: false
Role "role3" access: false
role1Allowed executed: true
role2Allowed executed: false
role2Allowed executed: false
anonymousAllowed executed: true
noOneAllowed executed: false

If you try this out with a user that doesn't exist, the result will be as follows:

Authentication status: SEND_FAILURE
User: null
Role "role1" access: false
Role "role2" access: false
Role "role3" access: false
anonymousAllowed executed: true
noOneAllowed executed: false