Fynn
Fynn

Reputation: 212

Filter method of JAX-RS Provider is never called

I tried following this tutorial and implemented the Provider class as given in the example.

@Provider
@Secured
@Priority(Priorities.AUTHENTICATION)
public class AuthenticationFilter implements ContainerRequestFilter {

    private static final String REALM = "example";
    private static final String AUTHENTICATION_SCHEME = "Bearer";

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        // Get the Authorization header from the request
        String authorizationHeader =
                requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);

        // Validate the Authorization header
        if (!isTokenBasedAuthentication(authorizationHeader)) {
            abortWithUnauthorized(requestContext);
            return;
        }

        // Extract the token from the Authorization header
        String token = authorizationHeader
                            .substring(AUTHENTICATION_SCHEME.length()).trim();

        try {

            // Validate the token
            validateToken(token);

        } catch (Exception e) {
            abortWithUnauthorized(requestContext);
        }
    }

    private boolean isTokenBasedAuthentication(String authorizationHeader) {

        // Check if the Authorization header is valid
        // It must not be null and must be prefixed with "Bearer" plus a whitespace
        // The authentication scheme comparison must be case-insensitive
        return authorizationHeader != null && authorizationHeader.toLowerCase()
                    .startsWith(AUTHENTICATION_SCHEME.toLowerCase() + " ");
    }

    private void abortWithUnauthorized(ContainerRequestContext requestContext) {

        // Abort the filter chain with a 401 status code response
        // The WWW-Authenticate header is sent along with the response
        requestContext.abortWith(
                Response.status(Response.Status.UNAUTHORIZED)
                        .header(HttpHeaders.WWW_AUTHENTICATE, 
                                AUTHENTICATION_SCHEME + " realm=\"" + REALM + "\"")
                        .build());
    }

    private void validateToken(String token) throws Exception {
        // Check if the token was issued by the server and if it's not expired
        // Throw an Exception if the token is invalid
        
        //TODO validate against database
        if(!token.equals("exampleString")) {
            throw new AuthenticationException("Invalid token.");
        }
    }
}

This Provider class is also recognized by the server, which can be seen in the logs:

Dez 25, 2017 6:47:09 PM com.sun.jersey.api.core.ScanningResourceConfig logClasses
INFORMATION: Root resource classes found:
  class com.jwt.service.AuthenticationEndpoint
  class com.jwt.service.HelloWorldService
Dez 25, 2017 6:47:09 PM com.sun.jersey.api.core.ScanningResourceConfig logClasses
INFORMATION: Provider classes found:
  class com.jwt.service.AuthenticationFilter

I created an Interface for the annotation:

@NameBinding
@Retention(RUNTIME)
@Target({TYPE, METHOD})
public @interface Secured {
}

And also annotated my REST endpoint.

@GET
@Path("/secured")
@Secured
public Response getUserSecured() {
    return Response.status(200).entity("Secured getUser is called").build();
}

Even though my Provider class is recognized, it still does not do anything when the annotated method is called. Instead of outputting the unauthorized status code, "Secured getUser is called" is returned, even though no authentification is send.

Does someone have an idea why the filter method of my Provider class is never called?

Upvotes: 0

Views: 761

Answers (1)

Rouliboy
Rouliboy

Reputation: 1377

com.sun.jersey.api package (visible in the provided logs) is Jersey 1 while the tutorial you are following deals with jersey 2. Upgrade to Jersey 2 and it will work.

Upvotes: 1

Related Questions