Search code examples
java-ee-6user-roles

No mapping available for role reference with sessionContext.isCallerInRole()


I have a method that can be called if the person has a specific role and they are associated with a particular group in JIRA. Since the groups in JIRA are dynamic, I can't have a role per JIRA group.

@DeclareRoles({
  FileServerRoles.FILE_ADDER,
  FileServerRoles.FILE_ADDER_ALL,
  FileServerRoles.FILE_VIEWER,
  FileServerRoles.FILE_VIEWER_ALL})
public final class FileServerRoles {

  /**
   * A user that can add files to the system.
   */
  public static final String FILE_ADDER = "file-adder";
  /**
   * A user that can add any files to the system.
   */
  public static final String FILE_ADDER_ALL = "file-adder-all";
  /**
   * A user that can view files in the system.
   */
  public static final String FILE_VIEWER = "file-viewer";
  /**
   * A user that can view all files in the system.
   */
  public static final String FILE_VIEWER_ALL = "file-viewer-all";
}

I am declaring all of the roles using @DeclareRoles.

@Decorator
public class FileServerServiceProjectAuthorizationDecorator implements FileServerService {

  private static Logger LOGGER = LoggerFactory.getLogger(FileServerServiceProjectAuthorizationDecorator.class);
  @Inject
  @Delegate
  @Any
  FileServerService delagate;
  @Inject
  @CurrentUser
  Set<JiraProjectReference> currentUserProjectReferences;
  @Resource
  SessionContext sessionContext;

  void verifyProjectKey(final String projectKey) {
    for (final JiraProjectReference projectReference : currentUserProjectReferences) {
      if (projectReference.getKey().equalsIgnoreCase(projectKey)) {
        return;
      }
    }
    throw new IllegalArgumentException("user not in the project");
  }

  @RolesAllowed({FileServerRoles.FILE_ADDER, FileServerRoles.FILE_ADDER_ALL})
  @Override
  public FileAddStatus addFileToRepository(final String projectKey, final String issueKey, final String fileName, final String mimeType, final File file) {
    if (!sessionContext.isCallerInRole(FileServerRoles.FILE_ADDER_ALL)) {
      verifyProjectKey(projectKey);
    }
    return delagate.addFileToRepository(projectKey, issueKey, fileName, mimeType, file);
  }

  @RolesAllowed({FileServerRoles.FILE_VIEWER, FileServerRoles.FILE_VIEWER_ALL})
  @Override
  public FileDescriptor retrieveFileFromRepository(final String projectKey, final String issueKey, final UUID uuid, final String fileName) {
    if (!sessionContext.isCallerInRole(FileServerRoles.FILE_VIEWER_ALL)) {
      verifyProjectKey(projectKey);
    }

    return delagate.retrieveFileFromRepository(projectKey, issueKey, uuid, fileName);
  }
}

!sessionContext.isCallerInRole(FileServerRoles.FILE_VIEWER_ALL) always throws IllegalStateException:

Caused by: java.lang.IllegalStateException: No mapping available for role reference file-viewer-all
        at com.sun.ejb.containers.EJBContextImpl.isCallerInRole(EJBContextImpl.java:458)
        at edu.wvu.esd.swordfish.web.service.FileServerServiceProjectAuthorizationDecorator.retrieveFileFromRepository(FileServerServiceProjectAuthorizationDecorator.java:59)
        ... 89 more

I have had no problem with any of the roles when that are referenced in @RolesAllowed. I have also tried moving the roles declaration into web.xml. There aren't many references to the error on google.

Has anyone seen this? What was your solution?


Solution

  • I was receiving the same "No mapping available for role reference" error when calling the isCallerInRole(roleName) method within an EJB in GlassFish 3.1. What fixed it for me was adding the appropriate @DeclareRoles annotation to my EJB. If the role name passed to isCallerInRole is not in @DeclareRoles, an IllegalStateException gets thrown. I'm not sure how security works within a decorator but @DeclareRoles was the key for me.

    Here is a simple example:

    @Stateless
    @LocalBean
    @DeclareRoles({"user", "admin"})
    public class ExampleEJB {
        @Resource
        private SessionContext sessionContext;
    
        public boolean isUserInRole(String roleName) {
            return sessionContext.isCallerInRole(roleName);
        }
    }