In my application I use form-based authentication with a LDAP-Realm. For Authorization I use a database. As I understand this works as follows
App --> (user,
You could customize it using Spring Security, authenticating against LDAP and configuring the authentication manager/authentication-provider:
<security:authentication-manager>
<security:authentication-provider user-service-ref="userDetailsService">
<security:jdbc-user-service data-source-ref="dataSource"
authorities-by-username-query="select AUTHORITIES.AUTHORITIES_AUTH from AUTHORITIES, USERS where AUTHORITIES.AUTHORITIES_USER_ID = USERS.USERS_ID and ..."/>
TL;DR: Have a look at this and that for a sample solution.
What you ask for depends on the degree of flexibility offered by the vendor-specific feature you use; your product may or may not allow you to extend the behaviour of that/these LoginModule
/ Realm
/ IdentityStore
/ whatever-it's/they're-called proprietary class(es), or maybe even to just type an SQL query into some administrative UI's input field. The bottom line is that it's non-standard functionality.
On the standard Java EE side of the spectrum there are the JASPIC (user / message authentication) and JACC (authorization) SPIs. Both can be used to retrieve security-related information pertaining to your users from some external store. What JASPIC cannot do is change a user's roles after authentication; that is, for the duration of an authenticated request 1 the user's roles are fixed. JASPIC can also not attach meaning to those roles; for it they're just plain String
s that the AS will in some proprietary manner derive group Principal
s from. JACC, on the other hand can do those things, as it establishes a "rulebase" (think Policy) which precisely associates roles, principals and Permissions and can be queried on each and every user-system interaction. JACC can also override or alter the interpretation of the Java EE security constraints expressed via deployment descriptors and annotations.
I will include a JASPIC-based solution in this post and disregard JACC for the most part, because:
Some remarks on what follows:
login.conf
entry is provided.foo-web.xml
and/or further use of deployment / administrative tools). You will additionally not have the SAM implementing the ServerAuthContext interface and will have to load the accompanying Properties
from within the SAM. Your AS will then instantiate the missing classes for you, possibly reusing a "global" AuthConfigProvider
and/or ServerAuthConfig
it has pre-configured for all applications and message layers. Note that, depending on whether it reuses its instantiated ServerAuthConfig
and ServerAuthContext
across requests (hardly ever the case especially with the latter), the lifecycle of your SAM may be affected.provided
) javaee-api
7.0 (plus your JDBC driver, unless already present on the AS class path).AuthConfigProvider
. Save as /<project>/src/main/java/org/my/foosoft/authn/BigJaspicFactoryRegistrar.java
./<project>/src/main/java/org/my/foosoft/authn/BigJaspicFactory.java
./<project>/src/main/java/org/my/foosoft/authn/LittleJaspicServerFactory.java
./<project>/src/main/java/org/my/foosoft/authn/HttpServletSam.java
./<project>/src/main/java/org/my/foosoft/authn/StandaloneLdapSam.java
./<project>/src/main/java/org/my/foosoft/authn/JaasDelegatingLdapSam.java
./<project>/src/main/java/org/my/foosoft/authn/JaspicMischief.java
./<project>/src/main/resources/org/my/foosoft/authn/jaspic-provider.properties
./<project>/src/main/java/org/my/foosoft/presentation/UserUtils.java
(optional - for demonstration purposes: JSF backing bean)/<project>/src/main/webapp/index.xhtml
(optional - for demonstration purposes: unprotected index page)/<project>/src/main/webapp/login.xhtml
(optional - for demonstration purposes: login page)/<project>/src/main/webapp/restricted/info.xhtml
(optional - for demonstration purposes: protected index page for users in role access_restricted_pages
)/<project>/src/main/webapp/WEB-INF/web.xml
(optional - for demonstration purposes and for the sake of completness: web module DD)Further reading:
1 JASPIC is very a generic SPI, in theory able to authenticate JMS, SAML-over-SOAP and any other kind of message, when plugged into a capable message processing runtime. Even its predominantly used Servlet Container Profile does not overly constrain it.
JASPIC's low-level, flexible nature entails unawareness of protocol-specific functionality, such as the HTTP session. Consequently, ServerAuthContext
s / SAMs are triggered by the runtime to perform authentication on every request.
The spec however makes a provision about this potential shortcoming by allowing SAMs to request initiation of a container authentication session by the runtime, via a MessageInfo
Callback Property. When asked to authenticate subsequent requests of the same client, SAMs can avoid repeating the entire process, by asking the runtime to reuse the previously established AS authentication session, hence the user identity (caller and/or group Principal
(s)). That is accomplished via execution of the "do-nothing-/leave-authentication-state-as-is-protocol" shown in the HttpServletSam
of the sample code.
It should lastly be noted that neither the JASPIC nor the Servlet spec clearly defines what a container authentication session is. For a SAM-authenticated user I would, for all practical purposes, consider the AS authentication session to be the equivalent of the HTTP session, as long as a) authentication pertains to a single application context and b) the SAM, as explained above, signals reuse of the AS authentication session on each request.