In the past I always implemented authorization with some very proprietary code having an @ApplicationScoped
bean with methods like isUserInAnyOfTheseRoles(String... roles)
, which executes appropriate database queries. I always had to call these methods at the start of a protected EJB method/REST resource, making an if-statement and possibly throwing a "NotAuthorized"-exception.
For the future I consider using JakartaEE's security mechanisms so I am reading into it. I have a problem understanding the use of the @javax.annotation.security.DeclareRoles
annotation.
Amongst others I read SO answer to ejb Security questions regarding Roles and Authentication. There it is said that
The @DeclareRoles annotation on the other hand is merely used to declare a list of roles; [...]. 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.
If I understand it right I need to declare the roles I use programmatically with javax.security.enterprise.SecurityContext#isCallerInRole(String)
. So my class might look like the following.
@DeclareRoles({"ADD_ENTITY", "DELETE_ENTITY", "UPDATE_ENTITY", "SEE_ENTITY", "SEE_ENTITY_DETAILS", "SEE_RESTRICTED_DATA", "MERGE_ENTITY", "ATTACH_METADATA"})
public class PersonService {
@Inject SecurityContext ctx;
@RolesAllowed({"SEE_ENTITY"})
public Person getPerson(long id) {
if(ctx.isCallerInRole("SEE_ENTITY_DETAILS") {...}
else if(ctx.isCallerInRole("SEE_RESTRICTED_DATA") {...}
else {...}
}
...
}
1st question: Now if I have another class, do I need to declare all the roles again?
@DeclareRoles({"ADD_ENTITY", "DELETE_ENTITY", "UPDATE_ENTITY", "SEE_ENTITY", "SEE_ENTITY_DETAILS", "SEE_RESTRICTED_DATA", "MERGE_ENTITY", "ATTACH_METADATA"})
public class CompanyService {
@Inject SecurityContext ctx;
@RolesAllowed({"SEE_ENTITY"})
public Company geCompany(long id) {
if(ctx.isCallerInRole("SEE_ENTITY_DETAILS") {...}
else {...}
}
...
}
In the mentioned answer the EJB spec is quoted with
The DeclareRoles annotation is specified on a bean class, where it serves to declare roles that may be tested by calling isCallerInRole [...]
2nd question: Is it correct that this declaration is only used by the programmatically access and not for the declarative part? So that I do not need to declare any roles if I only use the annotation @RolesAllowed
.
3rd question: What is the reason for this "duplication"? For me it is just annoying to declare the roles (by the way I do have plenty of roles in my application) twice. I do not see the point in doing so, after all it is just a string. I need to write a custom javax.security.enterprise.identitystore.IdentityStore
to map roles to a user. Aligning these roles in every EJB seems to be unnecessary.
4th question: In a comment to a similar question (Define @DeclareRoles annotation programmatically) I interpret that @DeclareRoles might by a ancient relic and is no longer needed if an IdentityStore is used. If that would be true, it would make things a little bit clearer to me.
Sorry for the four questions in one post, but it all tangled together somehow. Basically it is question 3 that haunts me the most.