Note: Wherever the term LDAP is used below, an LDAP-compliant directory service is what is actually being referred to.
1. How should a JEE app restrict users for doing some things with the help of a LDAP?
The Java EE security model remains, with respect to authorization, (predominantly) role-based (not to be confused with RBAC); at the end of the day the runtime will still authorize your users (callers in general) based on their application-level roles, regardless of where (LDAP, relational DB, SAML IdP, XML file, whatever) and how (i.e., as which SQL types, LDAP attribute types, etc.) those are persisted. In fact, some applications may not externally store their callers' role memberships at all, but calculate them during authentication instead, based on other attributes of the respective caller; an authentication mechanism might, as a contrived example, "see" that caller uid=jdoe, dc=users, dc=some, dc=org
has a hireDate
attribute that refers to a date more than 3 years in the past, and a jobTitle
attribute of developer, thereby inferring that jdoe
is a senior developer, assigning that as an actual role.
2. Where do I store the permissions? in LDAP or in my application database?
3. where do i the mapping between groups and permissions? (ldap or application)
First of all, your notion of a permission is not a good fit for the Java EE security model, thus my suggestion would be to drop permissions altogether and use corresponding roles directly. The benefit of doing so should be obvious: you can move from programmatic to purely declarative authorization, as the runtime would now be enabled to handle all authorization checks for you. Note that you are in no way mandated to think of roles solely as an equivalent to user groups; while they can indeed express something as coarse-grained as "editor" and "can-view-stats-panel", they can also express something as fine-grained as "can-access-method-void-getBonus(BigDecimal)-of-instance-123-of-EJB-BonusGranter-with-arg-not-greater-than-100$-during-working-hours-every-13th-of-every-January-between-08:00:10Z-and-08:01:09Z-if-hardworking-and-weather's-sunny-and-manager's-in-a-good-mood" (you would obviously have to come up with a good convention to be able to express all that both compactly and intuitively, but you get the idea).
There is also a spec called JACC which your Java EE product may or may not support. If you absolutely require more flexibility than what roles can offer, you could theoretically take advantage of it, as it essentially would allow you to use the Java SE Policy
in order to determine--on the basis of Principal
-assigned low-level, seemingly infinitely flexible java.security.Permission
s--whether a caller indeed has a role. Regardless, the goal remains the same: separation of authorization-related code from business logic.
As for your actual two questions--and that should not only hold true for your permissions (if you wish to retain them), but for most of your persistent data--my simplistic answer would be that if the data in question is needed (or the probability of it being depended on in the foreseeable future is high) by other applications, and it can "fit" into a directory information tree (not necessarily the case), then it may be stored in LDAP. Otherwise, it should be stored "closer" to the application, e.g. in the application's "dedicated" DB, as you suggested. Also keep in mind that, at least traditionally, LDAP is (was) considered to be a poor choice of repository for storage of data with a low read-to-write ratio. I do not know to what extent--if at all--that performance consideration remains valid at present, but I would still not use LDAP for persisting highly dynamic data, like a web service's response time or availability percentage.
4. Do I need to use JAAS when using LDAP with my Java EE Application?
You do and should not have to (directly) rely on JAAS either for authentication or authorization in Java EE. The subject has been extensively discussed elsewhere, hence I will not elaborate it here. In order to leverage container-managed authorization, as addressed earlier, you still have to use container-managed authentication, the main purpose of which is to establish the identity (caller and group (role) Principal
s) of your callers with the runtime. Now, ideally you would just declare something like the following
<login-config>
<auth-method>FORM</auth-method>
<LDAP-identity-store>
<base-DN>dc=users, dc=some, dc=org</base-DN>
<bind-DN>uid=admin</bind-DN>
<bind-credential>
<credential-alias ref="admin_LDAP_pass"/>
</bind-credential>
<base-search-DN>dc=users, dc=some, dc=org</base-search-DN>
<search-filter>(uid={username_HTTP_param})</search-filter>
</LDAP-identity-store>
</login-config>
in your web.xml
and authentication would just work. Unfortunately that is not the case for Java EE (at least as of version 7, as some much-promising changes in this area are expected to be included in the platform's next release). Assuming that you still want to use container-managed authentication, you have two options:
a) Author a portable authentication mechanism using JASPIC. Your javax.security.auth.message.module.ServerAuthModule
would basically:
- connect to and authenticate your caller (i.e. its form-
POST
ed username) against the LDAP, and if successful,
- retrieve (and/or compute) the caller's roles (called groups at that point),
- instantiate a
Principal
representation of the authenticated caller,
- instantiate a
String[]
of group names (off of which the runtime will construct corresponding group Principal
s), and finally
- communicate the outcome of the previous two steps to the runtime via JASPIC-specific
javax.security.Callback
s.
Advantages: Supported on all Full Java EE Profile implementations as well as on Jetty and Tomcat (since 9.0.0.M4).
Drawbacks: Requires a bit of effort and is not always optimally supported.
b) Author a vendor-specific authentication extension, JAAS-based or otherwise, essentially completing the same steps, although via proprietary APIs.
Advantages: Often zero new code (and certainly less boilerplate) needs to be written.
Drawbacks: Non-portable approach.
Further reading:
- If you feel intimidated by LDAP (I know I used to!), fear not, things eventually get better. :) In case you don't feel like reading 10+ RFCs on day 1 (you should though, eventually), there are countless of great resources online. Here are just a few (non-Active Directory-specific ones) which helped me in the past:
- JACC:
- On JAAS in Java EE (many more SO posts on the matter, just search for questions tagged
jaas
+ java-ee
)
- JASPIC (more SO posts, search for jaspic)