How to do it...

Follow these steps to complete this recipe:

  1. First, let's define our roles list:
public class Roles {
public static final String ADMIN = "admin";
public static final String USER = "user";
}
  1. Now, let's define a list of tasks to be completed based on the role:
@Stateful
public class UserBean {

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

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

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

}
  1. Now, let's implement the IndentityStore interface. Here, we define our policy so that we can validate the user's identity:
@ApplicationScoped
public class UserIdentityStore implements IdentityStore {

@Override
public CredentialValidationResult validate(Credential credential) {
if (credential instanceof UsernamePasswordCredential) {
return validate((UsernamePasswordCredential) credential);
}

return CredentialValidationResult.NOT_VALIDATED_RESULT;
}

public CredentialValidationResult validate(UsernamePasswordCredential
usernamePasswordCredential) {

if (usernamePasswordCredential.
getCaller().equals(Roles.ADMIN)
&& usernamePasswordCredential.
getPassword().compareTo("1234"))
{

return new CredentialValidationResult(
new CallerPrincipal
(usernamePasswordCredential.getCaller()),
new HashSet<>(Arrays.asList(Roles.ADMIN)));
} else if (usernamePasswordCredential.
getCaller().equals(Roles.USER)
&& usernamePasswordCredential.
getPassword().compareTo("1234"))
{

return new CredentialValidationResult(
new CallerPrincipal
(usernamePasswordCredential.getCaller()),
new HashSet<>(Arrays.asList(Roles.USER)));
}

return CredentialValidationResult.INVALID_RESULT;
}

}
  1. Here, we need to implement the HttpAuthenticationMethod interface:
@ApplicationScoped
public class AuthenticationMechanism implements HttpAuthenticationMechanism {

@Inject
private UserIdentityStore identityStore;

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

if (httpMessageContext.isAuthenticationRequest()) {

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

return httpMessageContext.notifyContainerAboutLogin
(identityStore.validate(credential));
}

return httpMessageContext.doNothing();
}

}
  1. Finally, we need to create a servlet where the user will both authenticate and carry out their tasks:
@DeclareRoles({Roles.ADMIN, Roles.USER})
@WebServlet(name = "/OperationServlet", urlPatterns = {"/OperationServlet"})
public class OperationServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

@Inject
private SecurityContext securityContext;

@Inject
private UserBean userActivity;

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

String name = request.getParameter("name");
String password = request.getParameter("password");

Credential credential = new UsernamePasswordCredential(name,
new Password(password));

AuthenticationStatus status = securityContext.authenticate(
request, response,
withParams().credential(credential));

response.getWriter().write("Role \"admin\" access: " +
request.isUserInRole(Roles.ADMIN) + "\n");
response.getWriter().write("Role \"user\" access: " +
request.isUserInRole(Roles.USER) + "\n");

if (status.equals(AuthenticationStatus.SUCCESS)) {

if (request.isUserInRole(Roles.ADMIN)) {
userActivity.adminOperation();
response.getWriter().write("adminOperation
executed: true\n");
} else if (request.isUserInRole(Roles.USER)) {
userActivity.userOperation();
response.getWriter().write("userOperation
executed: true\n");
}

userActivity.everyoneCanDo();
response.getWriter().write("everyoneCanDo
executed: true\n");

} else {
response.getWriter().write("Authentication failed\n");
}

}
}

To try out this code, run it in a Jakarta EE 8-compatible server using the following URLs:

  1. An example of the ADMIN role's result is as follows:
Role "admin" access: true
Role "user" access: false

adminOperation executed: true
everyoneCanDo executed: true
  1. If you use a wrong username/password pair, you'll get the following result:
Role "admin" access: false
Role "user" access: false
Authentication failed