I'm pleased to announce the availability of Seam Security 3.0.0 Alpha1. This release is a major rework of the security features from Seam 2.x, so I apologise in advance for the epic release notes. First the important stuff:
Distribution download:
Maven dependency:
<dependency> <groupId>org.jboss.seam.security</groupId> <artifactId>seam-security-impl</artifactId> <version>3.0.0.Alpha1</version> </dependency>
Alternatively, you can use the API at compile time and only include the implementation at runtime.
<dependency> <groupId>org.jboss.seam.security</groupId> <artifactId>seam-security-api</artifactId> <version>3.0.0.Alpha1</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.jboss.seam.security</groupId> <artifactId>seam-security-impl</artifactId> <version>3.0.0.Alpha1</version> <scope>runtime</scope> </dependency>
Note: You must configure the JBoss Community Repository in your settings.xml or project POM.
JIRA:
http://jira.jboss.org/jira/browse/SEAMSECURITY
I need to stress that this is an alpha release, and as such some features might be missing or incomplete, and there are sure to be some bugs. I'd like to invite everyone to make ample use of JIRA to report anything and everything that you find out of place or missing, this will greatly help us to prepare for the subsequent releases.
With that out of the way, it's time to buckle up and see what's changed.
Split between API and Implementation
Like many of the other Seam 3 modules, we have split the security module into API and IMPL sub-modules. This was a much requested feature for Seam Security to allow for alternate implementations to be used within unit tests, etc. Core components such as Identity, Credentials and others are now based on interfaces.
Basic Authentication
Authentication via a simple authentication method ala Seam 2 is quite similar in principle. Instead of having to configure an authenticator method in components.xml (which doesn't exist any more), you simply need to provide an implementation of the org.jboss.seam.security.Authenticator interface in your application. When calling Identity.login(), the security module will search for a bean implementing the Authenticator interface and if found use it to perform authentication. This interface declares a single method, authenticate():
public interface Authenticator { boolean authenticate(); }
Implementations may perform whatever logic necessary to authenticate the user, whether that be querying a database or reading user account info from a file. Credentials (containing the user's username and password) may be obtained by injecting the org.jboss.seam.security.Credentials bean directly into your Authenticator.
public class SimpleAuthenticator { @Inject Credentials credentials; public boolean authenticate() { // authentication logic here return true; // if authentication successful } }
PicketLink
One of the major changes in Seam Security is integration with PicketLink. Early on in the planning phase for Seam 3 we decided to look at ways we could unify our security efforts with the JBoss Security team. Seam already had identity management features, however it did not make sense to continue developing these features in parallel (and therefore competing) with the PicketLink IDM project, which had similar goals. With that in mind, we decided to drop the identity management features from Seam and adopt PicketLink IDM as our identity management provider.
PicketLink provides identity store implementations for storing identity-related information using either Hibernate or LDAP, however lacks a JPA implementation. Seam 3 bridges this gap by providing a JPA implementation called JpaIdentityStore, which was inspired by the JpaIdentityStore implementation in Seam 2. This is a total rewrite, and offers much more configuration flexibility when it comes to integrating with legacy db schemas which contain identity-related data. This identity store implementation may eventually make its way into the PicketLink project's code base.
To use JpaIdentityStore to provide identity management features for your own project, you need to configure it in your beans.xml (or seam-beans.xml) file (Seam-XML module is required). First you need to configure a namespace within the root element:
xmlns:plidm="urn:java:org.jboss.seam.security.management.picketlink"
Then you need to configure the entity classes which contain things such as your user accounts, credentials, roles, and relationships:
<plidm:JpaIdentityStoreConfiguration> <s:replaces/> <plidm:identityClass>org.jboss.seam.security.examples.idmconsole.model.IdentityObject</plidm:identityClass> <plidm:credentialClass>org.jboss.seam.security.examples.idmconsole.model.IdentityObjectCredential</plidm:credentialClass> <plidm:relationshipClass>org.jboss.seam.security.examples.idmconsole.model.IdentityObjectRelationship</plidm:relationshipClass> <plidm:roleTypeClass>org.jboss.seam.security.examples.idmconsole.model.IdentityRoleName</plidm:roleTypeClass> </plidm:JpaIdentityStoreConfiguration>
The above example is from the idmconsole demo application that is included within the Seam Security distribution. It is a simple but concise example that demonstrates how you might build an interface for managing users, roles and groups within your application.
Another important change to note is that the IdentityManager component is no longer part of Seam 3. Replacing it is a set of action beans, found in the org.jboss.seam.security.management.action package. These beans are designed to be used directly by the view layer (such as, but not limited to, JSF) to simplify the interaction between your application and the PicketLink IDM management API. If you want direct access to the API yourself, you can directly inject org.picketlink.idm.api.IdentitySession into your bean:
@Inject IdentitySession identitySession;
From the IdentitySession you can gain access to the PersistenceManager, RelationshipManager, RoleManager, etc for fine-grained control over all aspects of the identity management API. For more information, you can refer to the PicketLink documentation here:
API Changes, JAAS deprecation
With the move to PicketLink we have also adopted their Identity API, making use of the base PicketLink classes for User, Role and Group. As a result, we are no longer using the JAAS API within the Identity bean, and the original authentication mechanism (also based on JAAS) has been removed too. This has given us the advantage of first class support for Groups (previously in Seam 2.x, the concept of a group was to allow a grouping of roles). In Seam 3, a role is now a typed mapping between a user and a group. For example, "bob" (a user) may be a "manager" (role type) in "head office" (a group). This gives us more fine-grained control over privileges for groups of users.
Rule-based permissions
There have been a few minor changes to rule-based permissions in Seam 3. First of all, it's no longer required that you configure the rule file, as long as it's named security.drl and located in one of the standard locations for resources according to the Weld Extensions resource loader. Secondly, instead of asserting the Principal obtained from the Identity bean into the working memory, it now asserts a User object, and injects each of the Role and Group memberships assigned to the current user. As a result, you will need to modify the imports for your security rules file, here's an example:
import org.jboss.seam.security.permission.PermissionCheck; import org.picketlink.idm.api.Role; import org.picketlink.idm.api.Group;
Role checks performed in rules are slightly different also. Here's an example from the idmconsole demo:
rule CreateAccount no-loop activation-group "permissions" when check: PermissionCheck(resource == "seam.account", permission == "create", granted == false) Role(roleType.name == "admin") then check.grant(); end
Programmatic authorization
We have removed the @Restrict annotation from Seam 3, as this EL-based security mechanism didn't offer the kind of type safety that is encouraged by the CDI programming model. At this stage we don't have a typesafe annnotation-based replacement, however we may introduce one before the final release. For now, authorization can be performed programmatically by injecting the Identity bean into your application bean:
@Inject Identity identity;
Role checks can then be performed like this:
identity.checkRole("superuser", "Head Office", "GROUP");
If the user doesn't possess the required role, an AuthorizationException will be thrown. Simple group membership checks can be performed in a similar way:
identity.checkGroup("Head Office", "GROUP");
Permission checks are very similar to how they were in Seam 2.x, with a slight change in terminology. To align with PicketLink, we've renamed target
to resource
, and action
to permission
. The API for checking user permissions now looks like this:
void checkPermission(Object resource, String permission);
Once again, the resource parameter is used to specify the object upon which you wish to test if the current user has the necessary privileges to interact with, and the permission parameter is the name of the specific action that the user wishes to invoke on the resource. So for example, let's say we have an Account object which the current user wishes to delete. To check whether they have the necessary privileges to do this, we perform a permission check like so:
identity.checkPermission(account, "delete");
So what's next?
Here's a list of the things that didn't quite make it into the alpha, but are planned for the final release:
- External authentication module (due shortly in Alpha2)
- Persistent permissions (i.e. ACLs)
- Remember Me
- Unit Tests
- Documentation
- More examples