0

I am trying my hands on a simple jersey application for few simple RESTful APIs. I want to try role based securities over my API endpoints, but not sure how?

Should the annotation be declared over WebService class like below?

@Slf4j
@Path("/account")
@Autherization
@DeclareRoles("ADMIN", "STUDENT", "TEACHER")
public class AccountService extends SpringApplication {

    private static Logger logger = Logger.getLogger("AuthenticationService");

    @Path("/greet")
    @GET
    @Produces(MediaType.TEXT_PLAIN)
    @PermitAll
    public Response greet(){
        logger.info("Welcome to Tarkshala Scholar Account APIs");
        return getBean(AuthenticationServiceHandler.class).greet();
    }
}

or should it be declared on Filters?

Kuldeep Yadav
  • 1,664
  • 5
  • 23
  • 41
  • How are you doing _authentication_? – Paul Samsotha Feb 24 '20 at 05:26
  • @PaulSamsotha There is a filter which checks headers for sake of security. It finds session id and username in header and then fetches user details from DB to get the user role. This user role is compared against values stored into annotation `@RolesAllowed("ADMIN")` You can find it here https://bitbucket.org/snippets/kuldeepiitg/EbGLA4 – Kuldeep Yadav Feb 24 '20 at 12:51

1 Answers1

0

So Jersey already handles the authorization for you with its RolesAllowedDynamicFeature. Just register it in your Jersey ResourceConfig. There is no need for @DeclareRoles, as that is an EJB mechanism. Jersey has its own separate system for handling roles.

What happens under the hood is that there is a ContainerRequestFilter (annotated with @Priority(Priorities.AUTHORIZATION)) that checks your resource methods to see what roles are allowed, then it gets the SecurityContext from the ContainerRequestContext and called the SecurityContext#isUserInRole(String role) method for each role declared in the @RolesAllowed (should there be any). If the SecurityContext doesn't pass the check, Jersey throws a ForbiddenException.

So with that said, what you need to do for your authentication is create a ContainerRequestFilter (annotated with @Priority(Priorities.AUTHENTICATION), and in that filter do your authentication, then create a SecurityContext with all the roles for Jersey to check. This method separates the concerns; one filter for authentication (which we created) and one filter for authorization (which Jersey provides for us.

You can see an example of an authentication filter that uses Basic Authentication in this post.

Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
  • I am using digest based authentication, basically a dynamoDb table which have `usernames`, `role` and `passwordDigest` is used to check if the user is legitimate or not. How shall that be incorporated in tomcat based security realm? – Kuldeep Yadav Feb 25 '20 at 02:01
  • Also if I choose the filter, will I have to call is`UserInRole(role)` manually or it is auto invoked internally before every resource request? As of now, I am looking for values in the annotation @RolesAllowed and compare the roles in filter and then take decision if the user is to be given access of specific resource or not? – Kuldeep Yadav Feb 25 '20 at 02:04
  • You don't need to do anything but the authentication and set the SecurityContext. Take some time to review the code I linked to. You just need to register the RolesAllowedDynamicFeature. This will register an authorization filter that takes your SecurityContext and calls the isUserInRole for you. – Paul Samsotha Feb 25 '20 at 05:57