tag:blogger.com,1999:blog-4498889353428710313.post3302661785752665104..comments2024-03-13T14:22:32.519-07:00Comments on Arjan Tijms' Weblog: Simplified custom authorization rules in Java EEArjan Tijmshttp://www.blogger.com/profile/08548593340781885396noreply@blogger.comBlogger8125tag:blogger.com,1999:blog-4498889353428710313.post-6957882954267760962018-05-09T03:26:36.607-07:002018-05-09T03:26:36.607-07:00Thank you for the example, it is working quite wel...Thank you for the example, it is working quite well.<br /><br />I have a special case. I use an abstraction layer in a bean to provide a generic api method. The method is secured by the role "PerformUseCase"<br />but specific logic needs to be done using isCallerInRole.<br /><br />Something like:<br /><br /><br />@Stateless<br />@RolesAllowed("PerformUseCase")<br />public class UseCaseBean {<br /><br /> @Resource<br /> private SessionContext sessionContext;<br /><br /> public performUserAction(UserAction userAction) {<br /> if (!sessionContext.isCallerInRole(userAction.getUseCase())) {<br /> throw new Exception();<br /> }<br /><br /> if ("DeleteUseCase".equals(userAction.getUseCase())) {<br /> delete();<br /> }<br /> if ("EditUseCase".equals(userAction.getUseCase())) {<br /> edit();<br /> }<br /> }<br />}<br /><br /><br />Because there is no RolesAllowed annotation for "DeleteUseCase" and "EditUseCase" the custom jacc provider is not aware of roles "DeleteUseCase" and "EditUseCase" ("securityConstraints.getPerRolePermissions()" does not contain the roles), but it is aware of the "PerformUseCase" role.<br /><br />This can be solved by using @DeclareRoles({"DeleteUseCase", "EditUseCase"}) which makes the call to isCallerInRole work because now the "securityConstraints.getPerRolePermissions()" contains the values.<br /><br />It can also be solved by writing my own logic in CustomAuthorizationMechanism postAuthenticatePreAuthorizeByRole, like 'if getRequiredRoles does not return a result check an additional list of roles for the caller.getCallerPrincipal()'<br /><br />The first approach keeps the CustomAuthorizationMechanism implementation clean, but requires you to define all possible roles on a bean using @DeclareRoles.<br /><br />The second approach makes the CustomAuthorizationMechanism even more application specific.<br /><br />Do you have any experience with such a situation? Any tip / opinion? Would it be 'valid' to use isCallerInRole if the role is not directly defined in the application and only in some database?Escayhttps://www.blogger.com/profile/05248623561140969898noreply@blogger.comtag:blogger.com,1999:blog-4498889353428710313.post-60453712309477020052018-02-11T02:10:55.326-08:002018-02-11T02:10:55.326-08:00That's a good observation really, and indeed s...That's a good observation really, and indeed something we should think about a little bit more. Especially when evaluation is brought closer to the application code this will get more important.<br /><br />For now it's an open question of how/when to continue. JACC, JASPIC and Java EE Security are all in the process of being transferred. When that's done and the Eclipse foundation gives the green signal I hope we can finally start with the revisions.<br /><br />For JASPIC at least a long overdue clarification is that a SAM is allowed to call a component like an EJB, request a datasource from JNDI and use the CDI bean manager. While those things already hold in practice, and JSR 375 requires this explicitly, JSR 196 is formally silent on this topic.<br /><br />Another open topic is giving JACC knowledge about JAX-RS, maybe introducing some WsResourcePermission or something like that.Arjan Tijmshttps://www.blogger.com/profile/08548593340781885396noreply@blogger.comtag:blogger.com,1999:blog-4498889353428710313.post-26070284931872331322018-02-10T23:57:03.494-08:002018-02-10T23:57:03.494-08:00Something I noticed while playing on Payara (4.1.2...Something I noticed while playing on Payara (4.1.2.174): During a policy's evaluation of an access request to an EJB, b0, suppose that it needs to call a (different) EJB, b1, itself. Calling the latter EJB causes a recursive invocation of the policy, wherein it has to self-grant the corresponding EJBMethodPermission. So far, so good. Upon returning from the b1 pre-dispatch authorization check and the actual b1 business method invocation, however, both the "javax.ejb.EnterpriseBean" and "javax.ejb.arguments" policy context handlers' values remain set to those corresponding to b1, rather than b0. While somewhat counter-intuitive, I doubt that this behaviour can be considered a bug, given that the spec makes no hard promises to providers interacting with application components, particularly components being subject to access control themselves. Perhaps this could be a minor item for clarification in a future JACC or Java EE Security spec iteration -- something along the lines of "during component invocations embedded within a pre-dispatch policy delegation, the container must either appropriately restore context after each such invocation has completed, or skip recursive policy delegation" (since the policy will have no option but to unconditionally self-grant anyway).Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-4498889353428710313.post-46172383223153206892018-02-02T02:37:41.988-08:002018-02-02T02:37:41.988-08:00Thank you for bringing this additional perspective...Thank you for bringing this additional perspective to my attention. Yes, from the standpoints of framework consolidation and standardization, your presented notion of a "security backbone" is certainly appealing.<br /><br />I think part of my struggles here stem from trying too hard (and failing) to use @RolesAllowed -- perhaps even JACC itself -- for "everything". It could additionally be due to lack of experience, and that I don't quite know at this point what exactly it is that I seek to accomplish. A bit of context on how my current authorization playground roughly looks like:<br />- The SAM directly (i.e., not via JASPIC callbacks) populates the client subject with arbitrary principals. It only distinguishes the one representing the caller, so as to satisfy JASPIC's requirement for AuthStatus.(SEND_)SUCCESS. It doesn't bother signaling group principal semantics to the container.<br />- The JACC policy delegate establishes different kinds of mappings, currently based on the underlying domain model, but meant to be "outsourceable", if need be:<br />-- app-principal_to_app-role, where<br />---- app-principals are principals that may imply the ones established by the SAM.<br />---- app-roles are not Java EE roles but rather roles in an RBAC sense, are modeled after Java SE permissions, and can imply other roles.<br />-- app-principal_to_app-permission, where app-permissions are the so-called authorization primitives being tested for by the app's business methods. Each app-permission, a, implies a WebRoleRef- or EJBRoleRefPermission, b, iff a.getName().equals(b.getActions()).<br />-- app-role_to_app-permission, likewise.<br />- Business methods are only supposed to use @RolesAllowed("app-permission-name").<br />- The authorization mechanism checks whether any principals imply the ones given for evaluation, and, if so, whether any of them is (via the aforementioned mappings) associated with an app-permission implying the given (Web|EJB)RoleRefPermission.<br /><br />So I was basically hoping to "embed" all authorization logic within a single Policy#implies call -- ideally one that the container undertakes on the app's behalf as part of its pre-dispatch decision or immediately afterwards, before method execution actually begins. And it does work. The lack of expressive power in @RolesAllowed and is(User|Caller)InRole is however the key limitation. The policy needs to know both the action (usually represented by a Java SE permission's actions) and "authorization object" (represented by its class and/or name) to effectively decide. With a Java EE role it is quite hard to embed both pieces of information within a string, in a manner both consistent and extensible. Hence I am currently evaluating some alternatives (there are in reality overwhelmingly many options):<br />- Query the policy directly with arbitrary app-/business-relevant permissions, either from business methods or interceptors. Strictly speaking though, it wouldn't be a "container-managed" solution anymore (whatever that implies).<br />- Invent some new kind of configuration for affecting the pre-dispatch decision, such that the policy "knows" that when checking, say, an EJBMethodPermission for method updateFoo(String id, String newBarValue), it must also<br />evaluate whether FooPermission(id, "update") is granted (in addition to the default container-provided configuration).<br />- Only query JACC for standard Java EE security constraints and leave "higher-order" logic to the application.<br />- Stop trying to come up with a universal authorization model. Query the policy when it practically makes sense, and prefer the domain model when it doesn't.<br /><br />In summary, I have yet "a bit" of experimentation left to carry out in order to arrive at a conclusion (which will probably be as definite as an "it depends" anyway, as is the case with most things in life :P).<br />Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-4498889353428710313.post-69145691336871597732018-02-01T08:33:29.891-08:002018-02-01T08:33:29.891-08:00That's a good question and one I've been a...That's a good question and one I've been asking myself as well.<br /><br />The answer is I think that, yes indeed, we can do something very close to this using interceptors or other mechanisms (Servlet filters), but where would these go to fetch their authorization logic from?<br /><br />If you embed them directly in those interceptors, they won't play ball very well with interceptors from other parties or with the default annotations like @RolesAllowed or security constraints in web.xml.<br /><br />So, it's IMHO not so much a matter of involving the container, but redirecting to a central repository which a universal interface / API, which many different components can query, and which many other different components can plug-in to.<br /><br />E.g. the JACC managed authorization repository can be queried by Servlet, JAX-RS, EJB, Java EE Security, our own security interceptors, and much more, and extensions to this authorisation repository can be provided by just as many components (a pure low-level JACC provider, but also CDI based extensions such as proposed in this article).<br /><br />Basically, it's a kind of "security backbone".<br /><br />Naturally a new kind of backbone could be designed, but JACC is already there, and has had a large number of rough edges polished over the many years. Now all we need (it's easier said then done, of course), is make it a little bit more practical by addressing some usability gaps in the current spec.<br /><br />Hope this helps and thanks for appreciating the article! Arjan Tijmshttps://www.blogger.com/profile/08548593340781885396noreply@blogger.comtag:blogger.com,1999:blog-4498889353428710313.post-80873932255600633872018-02-01T03:07:33.934-08:002018-02-01T03:07:33.934-08:00Thanks for another great article. But reading this...Thanks for another great article. But reading this left me with a somewhat open-ended question: From the average web-app's perspective, is there any tangible benefit in utilizing JACC this way? We can now redefine what a Servlet or EJB role (or even a Servlet user-data-constraint for that matter) actually means, or even dynamically add constraints not originally present, and it certainly sounds cool -- the question is why does it matter? I mean, we will still be authorizing clients based on our local domain model ("user can edit foo if user_roles table maps user to "manager", or foo_owner column references user") one way or another; why bother involving the container? We could still have interceptors or other mechanisms in place for isolating authorization from business logic without reliance on JACC. To me, the centralizing power of JACC only seems to "click" in a scenario where the app is inherently capable of utilizing some truly external, organization-wide or at least cross-app, policy decision point (e.g. a XACML policy) for its authorization needs, with as little mapping between foreign and local attributes as possible. What am I missing?Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-4498889353428710313.post-16668220957348972862017-01-27T14:31:35.416-08:002017-01-27T14:31:35.416-08:00I know it exists, but not tried it yet ;)I know it exists, but not tried it yet ;)Arjan Tijmshttps://www.blogger.com/profile/08548593340781885396noreply@blogger.comtag:blogger.com,1999:blog-4498889353428710313.post-13130316021698553222017-01-27T14:29:05.371-08:002017-01-27T14:29:05.371-08:00Arjam what about PAC4J? (http://www.pac4j.org/) Di...Arjam what about PAC4J? (http://www.pac4j.org/) Did you tried this security library?Anonymoushttps://www.blogger.com/profile/16946953278863391761noreply@blogger.com