JAX-RS: How to secure REST endpoints?

23,862

Solution 1

I solved this with following code.

note Token mechanism will be updated once I do that

I have solved this by modifying the interceptor I have, the following is code

Annotation

@Inherited
@InterceptorBinding
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface SecurityChecked {

}

Resource Class

public class SecureResource {

    @GET
    @SecurityChecked
    public Response getUser() {
        return Response.ok("authenticated successfully!").build();
    }
}

Interceptor class

@Interceptor
@Provider
@ServerInterceptor
@SecurityChecked
public class SecurityCheckInterceptor implements PreProcessInterceptor, AcceptedByMethod {
    private static final Logger LOGGER = LoggerFactory.getLogger(SecurityCheckInterceptor.class);

    @Nullable
    @Override
    public ServerResponse preProcess(final HttpRequest request, final ResourceMethod method) throws Failure, WebApplicationException {
        final List<String> authToken = request.getHttpHeaders().getRequestHeader("X-AUTH");

        if (authToken == null || !isValidToken(authToken.get(0))) {
            final ServerResponse serverResponse = new ServerResponse();
            serverResponse.setStatus(Response.Status.UNAUTHORIZED.getStatusCode());
            return serverResponse;
        }

        return null;
    }

    private static boolean isValidToken(@Nonnull final String authToken) {
        LOGGER.info("validating token: " + authToken);
        return true;
    }

    @SuppressWarnings("rawtypes")
    @Override
    public boolean accept(final Class declaring, final Method method) {
        // return declaring.isAnnotationPresent(SecurityChecked.class); // if annotation on class
        return method.isAnnotationPresent(SecurityChecked.class);
    }
}

and then I run my Integration tests by deploying the resource class in JBoss and issuing following commands on command-line

curl --header 'X-AUTH: 1a629d035831feadOOO4uFReLyEW8aTmrCS' http://localhost:8080/market-1.0-SNAPSHOT/rest/login
curl --header 'InvalidHeader: InvalidHeaderValue' http://localhost:8080/market-1.0-SNAPSHOT/rest/login

Solution 2

You need is a Stateless Spring Security configuration in front of your JAX RS end points. I have addressed exact problem you are trying to solve but I don't have my own code to share..

Here is one project which has done the exact thing you are asking, Some wise man has done it all for you ;)

https://github.com/philipsorst/angular-rest-springsecurity

What is the magic ?

  1. You have one unprotected URL which does the Authentication, and set the user roles as well..
  2. Then you return some kind of Token, put it some where in cache which will be expected on every subsequent call..
  3. Upon new request on other protected resources, you will check if the Token is present in your cache/session store ( you need some mechanism to keep track of valid tokens )
  4. If token is resent and valid, you do the programmatic Log-in in Spring Security which ensures that you can use all the Security features spring provides, ( Annotations, JSTL Tags etc.. ) !
  5. Once passed token validation you will get the logged in user details in your controllers ( aka JAX RS resources ) to deal with security further..
  6. If the token was not valid or not present , it would be trapped by failure end point which would return appropriate response ( 401 )

Refer Following Link To Understand How Stateless Spring Security is configured.., https://github.com/philipsorst/angular-rest-springsecurity/blob/master/src/main/resources/context.xml

See how a user is validated for the first time and a token is generated.. https://github.com/philipsorst/angular-rest-springsecurity/blob/master/src/main/java/net/dontdrinkandroot/example/angularrestspringsecurity/rest/resources/UserResource.java

Here is the class where programmatic login is performed on every request after token check.. https://github.com/philipsorst/angular-rest-springsecurity/blob/master/src/main/java/net/dontdrinkandroot/example/angularrestspringsecurity/rest/AuthenticationTokenProcessingFilter.java

Share:
23,862
daydreamer
Author by

daydreamer

Hello Viewer, Some of the places to see my work are BonsaiiLabs My Website

Updated on March 11, 2020

Comments

  • daydreamer
    daydreamer about 4 years

    I am using JBoss AS and JAX-RS for creating REST endpoints.

    Lets say my class looks like

    @Path("/users")
    public class UserResource {
    
    
      @GET
      public Response getAccount() {
        return "hello";
      }
    }
    

    Now getAccount is not authenticated at the moment

    Wanted
    - I would like to add authentication so that when code hits getAccount the user is authenticated
    - I would like the authentication to be driven by annotations instead of XML configurations, if at all possible
    - I would like to do the database comparison to see if the user is valid

    Problem
    - I have never done that so I have no idea how to implement it
    - I have googled around a lot and found Jersey examples

    UPDATE
    - I would like to send authentication credentials with each request and not creating any session

    Please guide me with one simple working example and I would try to extend from there

  • virgo47
    virgo47 almost 10 years
    This helped me as well. As I needed to check a few details in different manner, I ended up with "just another demo". While the basics are very similar (can't deny the inspiration started here), I dropped UI and JPA/DB and focused on Spring Security more. Result is here, it's commented, Gradle-based, contains test.sh based on curl. And I wrote a blog post about this topic as well with couple of sequence diagrams. Should be helpful.
  • Amit
    Amit about 9 years
    Hey rakesh, I have checked the angular-rest-springsecurity project on github, i have one question, though all the security related issues are taken care with authorization in picture, but when i refresh the browser once the user is authenticated the control seems to be redirected to the login page, even when i just login and click refresh.... do u have any idea about this..?