Reputation: 751
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
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
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