Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ejb Security questions regarding Roles and Authentication

I'd be very grateful is someone could assist me with the following questions:

  1. What are the differences between @RolesAllowed and @DeclareRoles annotations?
  2. I developed a login function to check username and password against information in the database. However, I'd like to ask how I can assign a role to an authenticated user to use with the above annotations.
like image 329
Mr.J4mes Avatar asked Aug 28 '11 05:08

Mr.J4mes


2 Answers

What are the differences between @RolesAllowed and @DeclareRoles annotations?

The @RolesAllowed annotation is used to specify the list of roles that are actually allowed to access the business method. The behavior of the EJB at runtime, is affected by the presence of this annotation, for the EJB container actively verifies that the caller is present in an allowed role. Also, this annotation can be defined on both TYPEs and METHODs allowing you to define the list of roles allowed at both the level of a class or a method. You can override the list of roles allowed for all methods of a class, at the level of an individual method.

The @DeclareRoles annotation on the other hand is merely used to declare a list of roles; it is the equivalent of the security-role-ref element in the ejb-jar.xml file. The EJB container does not require knowledge of these roles to enforce access control checks on business methods of an EJB; instead, the bean provider/developer may use these roles in isCallerInRole tests to ensure programmatic security.

The EJB 3.1 specification states the following about the @DeclareRoles annotation:

17.2.5.3 Declaration of Security Roles Referenced from the Bean’s Code

The Bean Provider is responsible for using the DeclareRoles annotation or the security-role-ref elements of the deployment descriptor to declare all the security role names used in the enterprise bean code. The DeclareRoles annotation is specified on a bean class, where it serves to declare roles that may be tested by calling isCallerInRole from within the methods of the annotated class. Declaring the security roles allows the Bean Provider, Application Assembler, or Deployer to link these security role names used in the code to the security roles defined for an assembled application. In the absence of this linking step, any security role name as used in the code will be assumed to correspond to a security role of the same name.

The second part of your question states:

I developed a login function to check username and password against information in the database. However, I'd like to ask how I can assign a role to an authenticated user to use with the above annotations.

In this event, a general point to be noted is that my preferred approach is to not use progammatic security unless your use cases actually require it. In most events if one can achieve the requirements with declarative security, it is preferable to use it, for progammatic security requires you to keep track of isCallerInRole method invocations, and the absence of such a call, may result in a security breach. Either way, in your case, you will need your container to first recognize the groups and principals in the database, as roles that maybe used for access control checks.

In simpler words, the EJB client (a Java SE application, or a servlet, or another EJB) must first authenticate itself against the container's security mechanisms, to establish the caller's Principal. Successful use of Declarative or Progammatic security therefore relies on a successful authentication process. In your case, you will need to configure your container to recognize the groups and users in your database and translate those into Principal objects that can be used to enforce access control in a declarative or programmatic manner. Most containers support one or more flavours of JAAS login modules for this purpose; Glassfish 3.1 for instance, allows this using a JDBCRealm, while JBoss 6.0 supports this with a DatabaseServerLoginModule. You will therefore need to determine whether your container supports such a login module, and configure it to use your database.

Note, that in some cases, the container provided login modules may prove to be insufficient in meeting your needs. In such a case, you'll need to write your own login module (and if required, against the container's interfaces).

Additionally, you'll also need to map the roles used by the application to the users and groups in the JAAS realm. For example, if your database used by the JAAS realm:

  • contains users U1, U2, U3, U4 and U5, and
  • contains groups G1, G2 and G3 containing U1, U2, U3 respectively,
  • and your EJB permits users in roles R1, R2 and R3 (defined through the @RolesAllowed annotation) to access it's methods,

then you'll need to map the roles to principals (users and groups) in the JAAS realm. The mapping must be done even in the case where the role names are the same as principal names; Glassfish simplifies this by supporting the default principal to role mapping that maps similarly named principals (users or groups) to roles directly. Also, the process of mapping is container specific and as you would have guessed, this mapping is performed in container specific deployment descriptors and not in the EJB deployment descriptor (ejb-jar.xml).

To complete the answer, you'll need to assign a role to every user that is created. For the sake of simplicity, you may create a single user-group that all users may belong to. When the user authenticates himself against a JAAS realm, the Principal object would contain this group. The group in your JAAS realm may then be mapped to an EJB role, and the role name may be specified in a @RolesAllowed annotation. Any user in the database that is not in this group, would be prevented from accessing the annotated method(s) by the EJB container.

like image 68
Vineet Reynolds Avatar answered Oct 15 '22 07:10

Vineet Reynolds


Perhaps my answer may not be correct and can be incomplete. But it can be found in this reference http://openejb.apache.org/3.0/security-annotations.html

DeclareRoles can only be used in class level You need to update the @DeclareRoles when referencing roles via isCallerInRole(roleName).

Basic idea

  • By default all methods of a business interface are accessible, logged in or not

  • The annotations go on the bean class, not the business interface

  • Security annotations can be applied to entire class and/or individual methods

  • The names of any security roles used must be declared via @DeclareRoles

@RolesAllowed Can be used both in class level and methods level to restrict the access level.

one example Mixing class and method level restrictions Security annotations can be used at the class level and method level at the same time. These rules do not stack, so marking 'submitPatch' overrides the default of "committers".

@Stateless
@DeclareRoles({"committer", "contributor"})
@RolesAllowed({"committer"})
public class OpenSourceProjectBean implements Project {

    public String svnCommit(String s) {
        return s;
    }

    public String svnCheckout(String s) {
        return s;
    }

    @RolesAllowed({"contributor"})
    public String submitPatch(String s) {
        return s;
    }
}

EDIT:

Here is the code snippet for SQLLoginModule. You can use this module to be the login module. In this way,you can follow the JAAS standard.

In commit , it will call this to add principals.

subject.getPrincipals().addAll(allPrincipals);

Also you can check here for more details http://openejb.apache.org/3.0/security.html.

It lists other options you can choose.

like image 32
Clark Bao Avatar answered Oct 15 '22 07:10

Clark Bao