Search code examples
javaweb-servicesjax-rsrestlet

Jax RS Authorization


I have an existing code at a class which is extended from javax.ws.rs.core.Application

...
Context childContext = component.getContext().createChildContext();
JaxRsApplication application = new JaxRsApplication(childContext);
application.add(this);
application.setStatusService(new ErrorStatusService());
childContext.getAttributes().put("My Server", this);
...

ChallengeAuthenticator challengeGuard = new ChallengeAuthenticator(null, ChallengeScheme.HTTP_BASIC, "REST API Realm");
//Create in-memory users with roles
MemoryRealm realm = new MemoryRealm();
User user = new User("user", "user");
realm.getUsers().add(user);
realm.map(user, Role.get(null, "user"));
User owner = new User("admin", "admin");
realm.getUsers().add(owner);
realm.map(owner, Role.get(null, "admin"));
//Attach verifier to check authentication and enroler to determine roles
challengeGuard.setVerifier(realm.getVerifier());
challengeGuard.setEnroler(realm.getEnroler());
challengeGuard.setNext(application);
// Attach the application with HTTP basic authentication security
component.getDefaultHost().attach(challengeGuard);

I don't have a web.xml at my code. I would like to add authorization to my code. This: https://restlet.com/technical-resources/restlet-framework/guide/2.3/core/security/authorization does not apply to me since I don't have restlet resources.

How can I implement jax rs authorization into my code?

EDIT 1: Existing code uses restlet JAX-RS extension: https://restlet.com/technical-resources/restlet-framework/guide/2.2/extensions/jaxrs

I've tried that at my jax-rs resource class:

@GET
@Path("/")
public String getStatus() {
  if (!securityContext.isUserInRole("admin")) {
    throw new WebApplicationException(Response.Status.FORBIDDEN);
  }
  ...
}

However, it throws 403 even I log in with admin user.

EDIT 2:

When I check here: https://restlet.com/technical-resources/restlet-framework/guide/2.2/extensions/jaxrs There is a piece of code:

this.setRoleChecker(...); // if needed

This may solve my issue but I don't know how to set a role checker.

PS: I use jersey 1.9 and restlet 2.2.3.


Solution

  • I could make it work like that:

    Application class:

    ...
    application.setRoles(getRoles(application));
    ... 
    public static List<Role> getRoles(JaxRsApplication application) {
      List<Role> roles = new ArrayList<>();
      for (AuthorizationRoleEnum authorizationRole : AuthorizationRoleEnum.values()) {
          roles.add(new Role(application, authorizationRole.toString()));
      }
      return roles;
    }
    ...
    

    Authorization enum:

    public enum AuthorizationRoleEnum {
      USER("user"),
      ADMIN("admin");
    
      private final String value;
    
      AuthorizationRoleEnum(String value) {
        this.value = value;
      }
    
      @Override
      public String toString() {
        return value;
      }
    
    }
    

    At my resource classes:

    ...
    @Context
    SecurityContext securityContext;
    ...
    allowOnlyAdmin(securityContext);
    ...
    public void allowOnlyAdmin(SecurityContext securityContext) {
      if (securityContext.getAuthenticationScheme() != null
        && !securityContext.isUserInRole(AuthorizationRoleEnum.ADMIN.toString())) {
        throw new WebApplicationException(Response.status(Response.Status.FORBIDDEN)
          .entity("User does not have required " + AuthorizationRoleEnum.ADMIN + " role!").build());
      }
    }
    ...