jakarta-eejaspic

Jaspic: handle access to a protected resource


I'm (still) studying JASPIC, doing some experiments by simple project: this one. When I call a protected resources ServerAuthModule checks credentials via validateRequest and returns AuthStatus.SUCCESS. HTTP response is 200 but it is empty. I use these two curl commands to test:

curl -H "Content-Type: application/json" -X POST -d '{"username":"xxx","password":"xxx"}' http://localhost:8080/JaspicWeb/services/user/login
curl -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0NzE0NzE1ODcsInN1YiI6InVzZXJBIn0.Gyf7w2192vlz3uSwjwtf8z1p9n9k3IqtQMQrubA7oYI" -X GET http://localhost:8080/JaspicWeb/services/user/userA

The first command is to get the token used in the second one. I'm using Jaspic with Wildfly10 and RestEasy.

Update: I updated the linked project. Now it is a full working Jaspic example.


Solution

  • The SAM's CallbackHandler is the cause of your troubles.

    First it.jaspic.sec.TokenConfigProvider disregards the handler passed to it by the runtime:

    public ServerAuthConfig getServerAuthConfig(String layer, String appContext, CallbackHandler handler) throws AuthException {
      return serverAuthConfig;
    }
    

    Then it.jaspic.sec.TokenServerConfig uses its own handler, which basically does nothing:

    public TokenServerConfig() throws AuthException {
      // ...
      handler = new CallbackHandler() {
        @Override
        public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
          // just logs its arguments
        }
      };
    }
    

    Consequently, it.jaspic.sec.TokenSAM#validateRequest is unable to communicate the caller's identity to the runtime. Since it still erroneously returns AuthStatus.SUCCESS though, it is pretty much undefined behaviour from that point on, at least as far as JASPIC is concerned. It is, amusingly, as if the Servlet container were trying to keep both parties happy in this case, by honoring both the SAM's AuthStatus that suggests a successful authentication message exchange, on the one hand, as well as the application's <security-constraint> on the other. Admittedly, a 401, 403, or perhaps better yet, a 500 response--indicative of an authentication mechanism not obeying its contract--might have been less confusing.

    The obvious solution is to pass the runtime-provided handler to the SAM. The API clearly doesn't help much, but for the single message layer/single app/single authentication mechanism use case, it should be sufficient to just lazily instantiate the ServerAuthConfig with the handler, when it is first requested by the runtime via a getServerAuthConfig invocation:

    public synchronized ServerAuthConfig getServerAuthConfig(String layer, String appContext, CallbackHandler handler) {
      if (serverAuthConfig == null) {
        serverAuthConfig = new TokenServerConfig(handler);
      }
      return serverAuthConfig;
    }
    

    And, of course, the new constructor called above (which only has to store the handler argument) has to be introduced into it.jaspic.sec.TokenServerConfig.

    Those two changes should render the /services/user/userA endpoint accessible.