1

My application is currently protected by BASIC authentication configured by the web.xml descriptor. It contains a REST API with resources protected by the annotation @RolesAllowed. The users are stored in a simple SQL database which is used in a Realm configured on Payara.

My goal is to try to reimplement this authentication part with pac4j.

For the moment, I configured a DirectBasicAuthClient with my custom Authenticator which lookup for a IdentityStoreHandler to validate the credentials:

@Dependent
public class SecurityConfig {

    @Produces @ApplicationScoped
    private Config buildConfiguration() {
        final DirectBasicAuthClient directBasicAuthClient = new DirectBasicAuthClient(new MyAuthenticator());
        directBasicAuthClient.setRealmName("MyRealm");
        final Clients clients = new Clients(directBasicAuthClient);

        return new Config(clients);
    }

    public static final class MyAuthenticator implements Authenticator {
        @Override
        public void validate(Credentials credentials, WebContext context, SessionStore sessionStore) {
            var userNamePasswordCredentials = (UsernamePasswordCredentials) credentials;
            var identityStoreHandler = CDI.current().select(IdentityStoreHandler.class, new Annotation[0]).get();
            CredentialValidationResult result = identityStoreHandler.validate(new UsernamePasswordCredential(userNamePasswordCredentials.getUsername(), userNamePasswordCredentials.getPassword()));
            if (result.getStatus() == CredentialValidationResult.Status.INVALID) {
                throw new CredentialsException("Nope nope nope.");
            }

            BasicUserProfile userProfile = new BasicUserProfile();
            userProfile.setId(result.getCallerPrincipal().getName());
            var roles = new HashSet<>(result.getCallerGroups());
            roles.add("ADMIN"); // temporary for test purpose
            userProfile.setRoles(roles);
            credentials.setUserProfile(userProfile);
        }
    }
}

In debug mode, when I access to my protected REST API resource, the validation of the credentials works (MyAuthenticator#validate) but I receive a 401 Unauthorized. I suspect it is because pac4j does not update the security context. And I fail to see how I could make it do it in order to make the @RolesAllowed annotation work when I try to access to my protected REST resource.

The dependencies I use are:

  • org.pac4j:javaee-pac4j:7.1.0
  • org.pac4j:pac4j-http:5.7.1

My questions:

  • Is there a way to make pac4j to update the JEE security context in order to make @RolesAllowed work?
  • Is there a module to bridge Pac4J with Java Security ([javax|jakarta].security.enterprise)?
tlegrand
  • 776
  • 1
  • 8
  • 14

1 Answers1

1

I was expected it to work.

When using the pac4j SecurityFilter, the authenticated user is saved: https://github.com/pac4j/jee-pac4j/blob/master/javaee-pac4j/src/main/java/org/pac4j/jee/filter/SecurityFilter.java#L84 as the JEE principal: https://github.com/pac4j/jee-pac4j/blob/master/javaee-pac4j/src/main/java/org/pac4j/jee/util/Pac4JHttpServletRequestWrapper.java

I haven't tested, but I thought that the isUserInRole method was used by the @RolesAllowed annotation.

Can you debug what is tested by the @RolesAllowed annotation? Thanks

jleleu
  • 2,309
  • 1
  • 13
  • 9
  • During the debug with a breakpoint on the invokation of the `com.sun.enterprise.security.auth.login.common.LoginException`, I see the invokation of the `RolesAllowedRequestFilter` which checks if the `securityContext.getCallerPrincipal()` is not null.A problem is that the package of this filter is weird: `fish.payara.microprofile.jwtauth.jaxrs.RolesAllowedRequestFilter`. I suspect that JAAS/JASPIC is on the way because I have things like `org.glassfish.soteria.mechanisms.jaspic` on the call stack. – tlegrand May 16 '23 at 14:26
  • This is really interesting. So the main question is how to populate this `SecurityContext`. Can you track that? Is this something specific to the app server implementation? – jleleu May 17 '23 at 05:43
  • Do you have some `SecurityContextUtil` class or something like that? – jleleu May 17 '23 at 06:05