ernirulez
ernirulez

Reputation: 751

REST authorization with Jersey and session management

I have a RESTful Java backend with Jersey. The thing is that I don´t know how to implement authorization for the methods. I mean how do I check a user is authorized to use a given method of my REST API?

Of course if I look for "Jersey authorization", I have those nice annotations like @RolesAllowed, @PermitAll and @DenyAll. However those annotations act against the server realm, with the users of the server, nothing to do with your application users that you store in the database.

So for the sake authorization, what should I do? I define a filter that checks if the user is logged in in my application? I have to apply the filter to the REST endpoints that need authentication?

This seems a bit "like the old days", that´s why I´m asking the better way to do it.

Upvotes: 0

Views: 3487

Answers (2)

ernirulez
ernirulez

Reputation: 751

After reading A LOT, I found a really good (and cool solution) here:

Jersey Request Filter only on certain URI

So, in order to check authorization only for those methods annotated with your custom annotation (your authorization ContainerRequestFilter only filters the annotated methods of your REST API). I named it @AuthorizationRequired

Upvotes: 1

Atais
Atais

Reputation: 11275

So for the sake authorization, what should I do? I define a filter that checks if the user is logged in my application? I have to apply the filter to the REST endpoints that need authentication?

Well... i guess you will not be happy but that is basically what you need to do.

Some code advice;

public class Application extends ResourceConfig {

    public Application() {
        super();
        register(RolesAllowedDynamicFeature.class);  // this is for @RolesAllowed 
        register(AuthenticationRequestFilter.class); // your auth filter
    }    
}

Then, for basic auth I do:

@PreMatching
public class AuthenticationRequestFilter implements ContainerRequestFilter {

@Override
public void filter(ContainerRequestContext request) throws IOException {
    String authorization = request.getHeaderString("Authorization"); // get BasicAuth header

    if (StringUtils.isNotEmpty(authorization) && StringUtils.startsWith(authorization, "Basic")) {
        ... do the password check... you have base64 encrypted string here

        request.setSecurityContext(new SecurityContext(){
                                            ...implementation... 
        });
    }}}

But well, most of the work you need to do by yourself.


EDIT For the @RolesAllowed to work properly you need to set a SecurityContext in your authentication filter. And if the user is authenticated you need to set a proper context (like i do in the above code snipet).

This context actually allows you to do whatever logic you like to check for roles, username etc. with its methods; for example my implementation is:

public class AuthorizedContext implements SecurityContext {

    private final InternalUserBean user;

    public AuthorizedContext(InternalUserBean user) {
        this.user = user;
    }

    @Override
    public Principal getUserPrincipal() {
        return () -> getUser().getUsername();
    }

    @Override
    public boolean isUserInRole(String s) {
        // this does the proper check for @RolesAllowed annotation.
        return StringUtils.equals(s, getUser().getRole()); 
    }

    @Override
    public boolean isSecure() {
        return false;
    }

    @Override
    public String getAuthenticationScheme() {
        return "YourRealmName";
    }

    public InternalUserBean getUser() {
        return user;
    }
}

Upvotes: 3

Related Questions