Help

Archive

If you’re looking for a simple way to secure your Java EE application’s classes and methods, then PicketLink in conjunction with DeltaSpike provides an elegant and flexible solution thanks to DeltaSpike’s support for typesafe security annotations. This powerful combination means you can easily apply security to your application in three simple steps, which we’ll be examining in more detail in this article.

Before we get started though, let’s take a closer look at each of these individual projects.

PicketLink

PicketLink (http://www.picketlink.org) is an application security framework for Java EE. It provides features such as Identity Management (IDM), credential management, authentication API, permissions and permission management, plus much more. At the time of writing, the latest available version of PicketLink is 2.6.0.Final.

Apache DeltaSpike

Apache DeltaSpike (http://deltaspike.apache.org) is a collection of portable extensions for Java EE, built on top of the CDI (Contexts and Dependency Injection) standard. It enhances the Java EE platform by providing a set of useful features for application developers. The latest release of Deltaspike is 1.0.

Setting up the Maven Dependencies

This step is required to add the PicketLink libraries to your application. Start by defining a property value for the version of PicketLink that you’ll be using - the latest version at time of writing is 2.6.0.Final. Add the following property declaration to the <properties> section of your project’s pom.xml:

  <properties>
    <!-- PicketLink dependency versions -->
    <version.picketlink.javaee.bom>2.6.0.Final</version.picketlink.javaee.bom>
  </properties>

Then add the PicketLink BOM to the <dependencyManagement> section:

  <dependencyManagement>
    <dependencies>
      <!-- Dependency Management for PicketLink and Apache Deltaspike. -->
      <dependency>
        <groupId>org.picketlink</groupId>
        <artifactId>picketlink-javaee-6.0</artifactId>
        <version>${version.picketlink.javaee.bom}</version>
        <scope>import</scope>
        <type>pom</type>
      </dependency>
    </dependencies>
  </dependencyManagement>

Finally, add the PicketLink dependency to the <dependencies> section:

    <dependency>
      <groupId>org.picketlink</groupId>
      <artifactId>picketlink</artifactId>
      <scope>compile</scope>
    </dependency>

We’re done! The next step is to enable the DeltaSpike security interceptor.

Enabling the Security Interceptor

For the security interceptor to perform authorization checks for the classes or methods that we wish to secure with our security binding annotations, we must first enable it in our application’s beans.xml file. In a web application this file can be found in the WEB-INF directory. Add the <interceptors> section as shown in the following example:

<beans xmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="
      http://java.sun.com/xml/ns/javaee 
      http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
    <interceptors>
        <class>org.apache.deltaspike.security.impl.extension.SecurityInterceptor</class>
    </interceptors>
</beans>

Step 1: Create the Security Annotation

This first step is extremely simple - all we need to do is create an annotation and meta-annotate it with @SecurityBindingType. As an example let’s create a security annotation that we can use to restrict access only to users that are currently logged in:

@Retention(value = RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@SecurityBindingType
public @interface LoggedIn { }

Make sure that the @Target is set to both TYPE and METHOD - this will ensure that the annotation can be used to secure either all the methods of a class (when applied to the class itself) or to secure individual methods. The @SecurityBindingType annotation can be found in the org.apache.deltaspike.security.api.authorization package.

Step 2: Create the Authorizer method

This step is where we’ll be implementing the business logic for our security annotation. Each security binding annotation requires a corresponding authorizer method. This method must match the security binding annotation and any of its member values (excluding those annotated with @NonBinding, mirroring the behaviour of CDI itself). There must be exactly one authorizer method per unique security binding annotation usage.

The authorizer method can be placed in a bean class of your choosing, and there are no restrictions on the scope of the bean (in the following example we’ll use an @ApplicationScoped bean). Besides the security binding annotations, the authorizer method must also be annotated with @Secures, to denote that the method is being used to secure that security binding type:

@ApplicationScoped
public class Authorizer {
    @Secures
    @LoggedIn
    public boolean isLoggedIn(InvocationContext invocationContext, Identity identity) {
        return identity.isLoggedIn();
    }
}

The parameters of the authorizer method are treated as injection points (except for parameters of type InvocationContext which may be used to inspect metadata pertaining to the method from which the security check is being invoked). In the above example, we inject the Identity bean which represents the currently authenticated user - the Identity bean provides a method called isLoggedIn() that allows us to check if the current user is logged in.

Step 3: Apply the annotation to your methods

By the time we reach this step all of the hard work has been already done. The only remaining task is to apply the new security binding annotation to the methods and/or classes that you wish to secure. Let’s start off with a really simple example:

@RequestScoped
public class PostController {
    @LoggedIn
    public void getNewPosts() {
        // business logic here
    }
}

In this code we’ve applied our @LoggedIn security binding annotation to the getNewPosts() method of a request-scoped bean called PostController. When the user invokes this method, the security interceptor will intercept the method call and invoke the authorizer method to determine if the currently authenticated user is logged in. If the authorizer method returns true then the method invocation will then proceed as normal, otherwise an AuthorizationException will be thrown. If we would like to apply the same security restriction to all of the methods of a bean, we can put the annotation on the bean class instead:

@LoggedIn
@RequestScoped
public class PostController {
    public void getNewPosts() {
        // business logic here
    }
}

A Complete Example

You can find a complete example of using PicketLink with DeltaSpike in the following quickstart project:

https://github.com/jboss-developer/jboss-picketlink-quickstarts/tree/master/picketlink-deltaspike-authorization

Summary

In this article we examined how we can get the most out of DeltaSpike’s security annotation feature by combining it with a powerful security framework such as PicketLink. By following three simple steps we learned how to define a new security annotation, implement its business logic and then apply it to the methods and classes which we wish to protect.

09. May 2014, 02:33 CET, by Shane Bryzak

Welcome to part 2 of the PicketLink Deep Dive series. In case you missed part 1, you can find it here. In part 1 you’ll also find links to helpful resources, such as the PicketLink documentation, distribution binaries, source code and more.

In this issue, we’re going to be taking a closer look at PicketLink’s support for partitions. Let’s start though by establishing what exactly partitions are in the scope of PicketLink and how they are used.

What is a Partition?

In the simplest definition, partitions in PicketLink are used to segregate identities (such as users, groups and roles) from each other. Why would you want to do this, you wonder? Well one common use case for such a feature would be for an application that serves multiple clients/companies, with each client having its own distinct set of user accounts. Another use case might be when you wish to use PicketLink as an IDP (Identity Provider) that services multiple applications, with each application having a distinct set of identities. Whenever you need to support the creation of distinct “sets” of users or other identity types, partitions are there to help you.

Do I need to use them?

If your application has simple security requirements, such as a single set of user accounts and maybe perhaps a few groups and roles, then you probably don’t need to use PicketLink’s extended support for partitions. The good news is that you don’t really need to do anything special - simply ignore the partition aspect of PicketLink and it shouldn’t ever bother you! (You can probably also skip the rest of this article if you like and just come back for part 3).

Partitions and the Identity Model

If you read part 1, you may remember how the identity model was described and how each identity object implements the IdentityType interface, as shown in this class diagram:

What we didn’t explain in part 1 was how every IdentityType object must belong to a Partition. This means that every user, group, role, agent, account (or any other identity type) always has a partition object, and its getPartition() method will always return this object (and never null). If you’ve worked with the PicketLink API already you may have noticed these overloaded methods on the PartitionManager interface:

    IdentityManager createIdentityManager() throws IdentityManagementException;
    IdentityManager createIdentityManager(Partition partition) throws IdentityManagementException;

At first glance it might seem that the first of these methods might return a “partitionless” IdentityManager instance, however behind the scenes PicketLink actually returns an IdentityManager for the default partition. We’ll examine this in more detail shortly, but first let’s look at how PicketLink supports different partition types.

Creating a custom partition type

Since the Partition interface cannot be instantiated itself, it is generally up to the developer to provide a concrete partition implementation. PicketLink provides two built-in partition types which you are free to use (see the next section for details), but otherwise it is very simple to create your own partition type. The AbstractPartition abstract base class makes this easy by doing most of the work for us, and may be easily extended to create a custom partition type. Let’s take a look at a really simple example:

@IdentityPartition(supportedTypes = {IdentityType.class})
public class Organization extends AbstractPartition {
    public Organization() {
        super(null);
    }
    public Organization(String name) {
        super(name);
    }
}

That’s all the code we need! We can use this new Organization partition type to create identities within separate Organizations. The only really significant feature worth a special mention in the above code is the @IdentityPartition annotation. This annotation tells PicketLink that the class is a partition class, and also that it allows the storing of all IdentityType types (including any subclasses of IdentityType). If we only wanted to store User objects in the partition then we could instead annotate the class like this:

@IdentityPartition(supportedTypes = {User.class})

It’s also possible to “trim” support for certain identity classes off the hierarchy tree, by specifying them in the unsupportedTypes member. For example, let’s say that we wish to be able to store all identity types in an Organization, except for Roles. The annotation would now look like this:

@IdentityPartition(supportedTypes = {IdentityType.class}, unsupportedTypes = {Role.class})

Finally, since the Partition interface extends AttributedType, we know that it will have a unique identifier and that we are able to also assign it arbitrary attribute values, so with our new Organization partition we can do stuff like this:

Organization org = new Organization(“acme”);
org.setAttribute(new Attribute<String>(“description”, “Manufactures anvils and other failure-prone devices”);
partitionManager.add(org);
log.info(“Created new Organization partition with id: “ + org.getId());

Built In Partition Types

PicketLink provides two built-in, optional partition types - Realm and Tier. Both of these classes can be found in the org.picketlink.idm.model.basic package along with the other classes that form the basic identity model. Both of these partition types are provided for convenience only, there is absolutely no requirement that you use either of them. If you do wish to use these built-in partition types, then here are our guidelines (which you may choose to ignore if you wish):

Realm

The Realm partition type is analogous to the commonly accepted definition of a security realm and is recommended for use when you need to create a distinct set of users, groups and roles (or other identity types) for restricting access to an application. It supports all identity types.

Tier

A Tier is designed to be used in conjunction with a Realm and is intended for storing only roles or groups (or any other non-Account identity type, i.e. an identity type that isn’t capable of authenticating such as a User) while the Realm stores the Users. It is intended for storing tier-specific identities; for example if your application consists of multiple tiers, then each tier can define its own set of roles which in turn may be assigned certain tier-specific privileges. This way, a user in a separate Realm can be easily assigned one or more Tier-specific roles to give them access to the services provided by that tier.

The Default Partition

As mentioned above, Identity Management operations performed on an IdentityManager returned by the PartitionManager.createIdentityManager() method are actually done in the default partition. This default partition is actually a Realm object with a name of “DEFAULT”. If your PicketLink environment isn’t configured to support partitions then it doesn’t matter, PicketLink will transparently handle the support for the default partition without you having to do anything special.

Partitions and Relationships

So far we haven’t mentioned where identity relationships fit into the picture in regards to partitions. By their very nature, relationships differ from identities in that they don’t belong to a specific partition. If you think about this, it makes quite a lot of sense as a relationship is a typed association between two or more identities and those identities may not all exist within the same partition. For example, based on the description of the Realm and Tier partitions above we know that it is possible to have a Role that exists in a Tier, granted (via a Grant relationship) to a User in a Realm.

It is outside the scope of this article to go into detail about how PicketLink determines where to store relationship state, however this might be a good topic for a future deep dive.

Partitions and Multiple Configurations

PicketLink allows multiple configurations to be simultaneously declared, each with its own distinct name. A single configuration may have one or more identity stores configured for storing identity state. By supporting multiple configurations, PicketLink provides control over which backend identity store is used to store the identity state for each partition. This all might sound a little confusing, so let’s illustrate it with a diagram that describes a possible use case for a fictional paper company:

In this example our paper company has two configurations, “Public” and “Internal”. The “Public” configuration has been configured to use a JPA-based identity store which uses a database to store its identity state. The “Internal” configuration uses an LDAP-based identity store which is backed by a corporate LDAP directory. In addition to these two configurations, we also have two realm partitions - “Users” and “Employees”.

Let’s also assume that our paper company runs an ecommerce web site where anyone can log in and place an order for their products. The login page for public users might look something like this:

When logging in through this login form (which is easily found via a “Sign In” link on the main page of the site), authentication will be performed using the “Users” realm. The site may also provide an employee portal for managing orders and possibly performing other back-office tasks. Employees wishing to access this portal would use a different web address (or maybe an entirely different application, possibly even available only on the company private network) and would authenticate with an “employee-only” login form backed by the “Employees” realm. We can represent the distinct login pages and their associated realms using the following diagram:

An application may be modelled to support this multi-faceted application in a number of ways; it may be structured as a number of separate Tiers, with each tier providing a limited set of functions (possibly implemented as separate applications and/or services) and a set of tier-specific roles to control how privileges to access those functions are assigned; it could also be structured as a single monolithic application that “does everything” (™), restricting access to certain areas depending on the access level of the current user. In either case, application-wide privileges can be easily assigned to individual users from either realm. For example, if the privilege takes the form of a role or group membership, it’s possible for that role or group to exist in one realm and a user to which it is assigned exist in another realm.

Let’s say for example that an “admin” role for our paper company’s web portal is defined in the “Users” realm, and that this role is required to access the “Review Orders” page of the site:

As we can see, it doesn’t matter that the user to which this role is assigned exists in a different realm, because as we mentioned previously, relationships by their very nature are “cross-partitioned” and so can be used to assign privileges between distinct realms.

Partition Management API

PicketLink provides a simple PartitionManager API for managing partitions. It can be easily injected into your application like so:

import org.picketlink.idm.PartitionManager;
import javax.inject.Inject;

public class AdminService {
    @Inject PartitionManager partitionManager;
}

Once you have the PartitionManager instance, you can retrieve an existing Partition like so:

    Realm default = partitionManager.<Realm>getPartition(Realm.class, “default”);

Or you can retrieve all partitions of a certain type:

    List<Realm> realms = partitionManager.<Realm>getPartitions(Realm.class);

Creating a new Partition is also simple:

    Tier orderServices = new Tier(“orderServices”);
    partitionManager.add(orderServices);

As is removing a Partition:

    Realm tempUsers = partitionManager.<Realm>getPartition(Realm.class, “temp”);
    partitionManager.remove(tempUsers);

To create users and other identity objects within a Partition, get a reference to its IdentityManager via the createIdentityManager() method:

    Realm default = partitionManager.<Realm>getPartition(Realm.class, “default”);
    IdentityManager im = partitionManager.createIdentityManager(default);

    User jsmith = new User(“jsmith”);
    im.add(jsmith);

To grant permissions to users within a Partition, get a reference to its PermissionManager via the createPermissionManager() method:

    Realm default = partitionManager.<Realm>getPartition(Realm.class, “default”);
    User jsmith = new User(“jsmith”);
    im.add(jsmith);

    PermissionManager pm = partitionManager.createPermissionManager(default);
    pm.grantPermission(jsmith, Order.class, “CREATE”);

To create relationships, get a reference to a partitionless RelationshipManager via the createRelationshipManager():

    RelationshipManager rm = partitionManager.createRelationshipManager();

Once you have the RelationshipManager you can use it to create relationships either between identities in the same partition, like so:

    Realm default = partitionManager.<Realm>getPartition(Realm.class, “default”);
    IdentityManager im = partitionManager.createIdentityManager(default);
    User jsmith = new User(“jsmith”);
    im.add(jsmith);
    Role admin = new Role(“admin”);
    im.add(admin);

    rm.add(new Grant(jsmith, admin));

Or between relationships in different partitions:

    Realm default = partitionManager.<Realm>getPartition(Realm.class, “default”);
    IdentityManager im = partitionManager.createIdentityManager(default);
    User jsmith = new User(“jsmith”);
    im.add(jsmith);

    Tier serviceTier = partitionManager.<Tier>getPartition(Tier.class, “service”);
    IdentityManager tim = partitionManager.createIdentityManager(serviceTier);
    Role admin = new Role(“admin”);
    tim.add(admin);

    rm.add(new Grant(jsmith, admin));

Summary

PicketLink’s advanced support for partitions allows us to create security architectures suitable for simple, single-purpose applications ranging through to complex, multi-tier enterprise platforms. In this article we examined how partitions can be used to create distinct sets of identities, and we explored how to manage partitions using the PartitionManager API.

Once again, thanks for reading!

I had the privilege today of receiving some expert tutelage on Forge Addon development in Eclipse from the Forge Team’s George Gastaldi, and I was so impressed by how easy it was that I’m going to describe the process step by step so that you too can experience the pleasure of writing a Forge addon! This guide is written from the perspective of a complete Forge noob, so you can rest assured that it has made a very strong attempt to capture all the little important details. Also, while the addon itself won’t actually do that much, we’ll try to cover all the basics which will hopefully provide the solid foundation you need to be able to implement more complex features.

Setting up your environment

I strongly recommend that you work with the latest trunk of Forge, so fire up your terminal window and start by cloning the following repositories from GitHub:

https://github.com/forge/furnace

https://github.com/forge/furnace-cdi

https://github.com/forge/forge-core

https://github.com/jbosstools/jbosstools-forge

Once you have them all build each of them using Maven, making sure to skip the tests. You’ll need Maven 3.1 or higher for this step:

cd furnace
mvn clean install -Dmaven.test.skip=true

If all goes well you’ll get a BUILD SUCCESS message at the end:

Continue by building the other three projects (furnace-cdi, forge-code and jbosstools-forge) in order using the same Maven command.

Installing Forge

Once everything has built successfully, it’s time to install Forge. Open the forge-core/dist/target directory where you’ll find some zip files containing the Forge distribution:

You have a choice here, you can either use the (smaller) distribution zip which doesn’t come pre-packaged with all of the core addons, or you can use the larger offline distribution which has the addons packaged also. For now, I recommend you use the offline distribution, so extract it to its own folder somewhere. I generally like to install tools like this into a dedicated apps folder, and if you’re on a *nix based OS I recommend creating a symbolic link also:

Once that’s done, you need to create a FORGE_HOME environment variable pointing to this directory, and add the $FORGE_HOME/bin directory to your path (this will allow you to execute the forge shell from anywhere). This is an OS-specific step so it’s up to you to complete this by yourself. When that’s done, run the forge command from a command prompt.

(Note: If you didn’t install the offline distribution, you’ll be prompted to install the core addons. When you start forge, it will attempt to install the latest released versions, however in our case we want to install the artifacts that we just built ourselves, so to do that we must first run forge -i core,2.0.1-SNAPSHOT - alternatively just use the offline distribution and save yourself a lot of trouble.)

Forge will download a bunch of stuff and then prompt you to confirm the installation, so select Y and press Enter again.

Eventually the installation will complete and you’ll be sitting at the Forge command prompt:

From here you can press the tab key to see the available commands:

We’ve successfully set up the Forge shell! Let’s quit out for now by typing exit then pressing enter and we’ll go through the steps to install the JBoss Tools Forge plugin in Eclipse.

Installing the Forge Eclipse Plugin

At the time of writing I’m using the latest release version of Eclipse, Kepler SR1. If you are using an older version of Eclipse then I recommend that you update to the latest, otherwise results might be unpredictable. The first step in installing the Eclipse plugin is to start up Eclipse, then go to the Help -> Install New Software… menu option:

Then click the Add button, then in the popup window click Archive:

Browse to the jbosstools-forge/site/target directory, select the forge.site.XXX zip file and click OK:

Click OK again in the Add Repository window, then select the checkbox next to JBoss Tools Forge Nightly Build Update Site, then click the Next button:

You’ll be prompted to review the install details, so click the Next button again. You’ll be asked to review and accept the terms of the license agreement, so after accepting them click the Finish button and Eclipse will go ahead and install the plugin. If you get a security warning about unsigned content don’t panic; it’s just a warning and it's fine to click OK here. Once finished, Eclipse will inform you that it needs to be restarted so go ahead and click the Yes button. After Eclipse has restarted you can confirm that the Forge plugin has been successfully installed by pressing Ctrl + 5, which will present you with the following popup window:

If you can see the Forge command window after pressing Ctrl + 5, then congratulations on making it this far! Next we’ll go ahead and create our Forge Addon project.

Creating a Forge Addon Project

Forge does a great job of doing the heavy lifting when it comes to creating a new Addon. Let’s create the initial project structure for our addon by opening the Forge command window in Eclipse with Ctrl + 5, then scrolling down until we find the Project/Generation - Project: New option:

Clicking on the Project: New option gives us a dialog window that lets us enter some basic details for our addon project. Fill in the details for the project name, top level package, version, final name and project location. Select Forge Addon for the project type and leave the Build system default of Maven, then click Next.

On the next screen, click the checkbox next to Create API, Impl, SPI, Tests and Addon modules and select the following addons from the addon list:

org.jboss.forge.addon:projects

org.jboss.forge.addon:ui

org.jboss.forge.furnace.container:cdi

After you’ve selected these addons, click the Finish button to generate the new project.

After grinding away for a few seconds you should see the following new projects in the Eclipse project explorer:

Our new addon project is created! Next we’ll start adding some basic functionality.

Making the Addon do something

This is where we get into the exciting stuff. Let’s start off by creating a new class in the impl project, under the com.acme.helloworld.ui package called HelloWorldUICommand. Once you’ve created this class, edit its code and make it extend AbstractUICommand:

package com.acme.helloworld.ui;

import org.jboss.forge.addon.ui.command.AbstractUICommand;

public class HelloWorldUICommand extends AbstractUICommand {

}

Once that’s done, tell Eclipse to add the unimplemented methods:

package com.acme.helloworld.ui;

import org.jboss.forge.addon.ui.command.AbstractUICommand;
import org.jboss.forge.addon.ui.context.UIBuilder;
import org.jboss.forge.addon.ui.context.UIExecutionContext;
import org.jboss.forge.addon.ui.result.Result;

public class HelloWorldUICommand extends AbstractUICommand {

    @Override
    public void initializeUI(UIBuilder builder) throws Exception {
        // TODO Auto-generated method stub
        
    }

    @Override
    public Result execute(UIExecutionContext context) throws Exception {
        // TODO Auto-generated method stub

    }

}

Let’s write a bare minimum amount of code so that we can install our plugin and try it out. Implement the execute() method by adding the following code:

package com.acme.helloworld.ui;

import org.jboss.forge.addon.ui.command.AbstractUICommand;
import org.jboss.forge.addon.ui.context.UIBuilder;
import org.jboss.forge.addon.ui.context.UIExecutionContext;
import org.jboss.forge.addon.ui.result.Result;
import org.jboss.forge.addon.ui.result.Results;

public class HelloWorldUICommand extends AbstractUICommand {

    @Override
    public void initializeUI(UIBuilder builder) throws Exception {
        // TODO Auto-generated method stub
        
    }

    @Override
    public Result execute(UIExecutionContext context) throws Exception {
        return Results.success("Hello World");
    }

}

Once that’s done, save the class and build the project by running mvn clean install in the parent folder of your addon project:

Then in Eclipse, select the helloworld-addon project (or whatever you have called it), press Ctrl + 5 to display the Forge command window and select the Addon/Manage - Install an Addon command:

Leave the default values in the Install an Addon window unchanged and click the Finish button:

If everything has gone to plan, you should notice a little popup window in the bottom right corner of the screen confirming that the addon was successfully installed. We can test our new addon immediately by pressing Ctrl + 5 and scrolling down until we find our new command:

Clicking on the command should give us another popup window that displays our hello world message:

Creating User Interface Elements

The next step is to create some user interface elements that prompt the user for input. We’ll start simple by injecting a simple text input control and adding it to the dialog screen for our addon - here’s a complete code listing:

package com.acme.helloworld.ui;

import javax.inject.Inject;

import org.jboss.forge.addon.ui.command.AbstractUICommand;
import org.jboss.forge.addon.ui.context.UIBuilder;
import org.jboss.forge.addon.ui.context.UIExecutionContext;
import org.jboss.forge.addon.ui.input.UIInput;
import org.jboss.forge.addon.ui.result.Result;
import org.jboss.forge.addon.ui.result.Results;

public class HelloWorldUICommand extends AbstractUICommand {

    @Inject UIInput<String> input;
    
    @Override
    public void initializeUI(UIBuilder builder) throws Exception {
        builder.add(input);
    }

    @Override
    public Result execute(UIExecutionContext context) throws Exception {
        return Results.success("Hello World");
    }

}

Rebuild the project the same way as before, and reinstall the addon from the Forge command screen (Ctrl + 5 and select Addon/Manage : Install an Addon). Press Ctrl + 5 again and select HelloWorldUICommand, and you should now see the following dialog window:

We can customize our input control further by adding a @WithAttributes annotation - add the following import:

import org.jboss.forge.addon.ui.metadata.WithAttributes;

Then add the @WithAttributes annotation to the UIInput:

@Inject @WithAttributes(label = "Name", required = true, description = "Enter your name")  
    UIInput<String> input;

The control can be customized by setting the various member values:

label - The label for the input

required - Make the input a required field

description - The description when you mouse over the field.

Save your class, then build and reinstall the addon following the same steps as before. Execute the addon command using Ctrl + 5 and you should now see this:

We can now begin to see how simple it is to build a user interface for our addon. Let’s extend it further by adding a select control that allows you to select a Maven dependency. In this example I’ll use the PicketLink project as our guinea pig. We’ll need to @Inject a DependencyResolver to locate the dependencies that we’re interested in, and a UISelectOne control to allow the user to select one of the dependencies. Add this code to your class:

@Inject DependencyResolver dependencyResolver;    
    
@Inject @WithAttributes(label = "Version", required = true, description = "Select the version of PicketLink") 
private UISelectOne<Coordinate> version;    
    
@Override
public void initializeUI(UIBuilder builder) throws Exception {
    builder.add(input);
        
    DependencyQuery query = DependencyQueryBuilder
            .create("org.picketlink:picketlink-api")
            .setFilter(new NonSnapshotDependencyFilter());

    List<Coordinate> coordinates = dependencyResolver.resolveVersions(query);
    version.setValueChoices(coordinates);
    builder.add(version);        
}

The DependencyQuery is used to to declare the criteria that we’ll use to locate the dependencies we want, and the NonSnapshotDependencyFilter parameter tells the query that we’re only interested in non SNAPSHOT releases. The Coordinate class is used to represent a specific Maven dependency and contains property values for the dependency’s groupId, artifactId and so forth. We populate the select control with our list of Coordinates and finally add the control to the form via the builder.add() method. Once you’re done the complete code listing should look like this:

package com.acme.helloworld.ui;

import java.util.List;

import javax.inject.Inject;

import org.jboss.forge.addon.dependencies.Coordinate;
import org.jboss.forge.addon.dependencies.DependencyQuery;
import org.jboss.forge.addon.dependencies.DependencyResolver;
import org.jboss.forge.addon.dependencies.builder.DependencyQueryBuilder;
import org.jboss.forge.addon.dependencies.util.NonSnapshotDependencyFilter;
import org.jboss.forge.addon.ui.command.AbstractUICommand;
import org.jboss.forge.addon.ui.context.UIBuilder;
import org.jboss.forge.addon.ui.context.UIExecutionContext;
import org.jboss.forge.addon.ui.input.UIInput;
import org.jboss.forge.addon.ui.input.UISelectOne;
import org.jboss.forge.addon.ui.metadata.WithAttributes;
import org.jboss.forge.addon.ui.result.Result;
import org.jboss.forge.addon.ui.result.Results;

public class HelloWorldUICommand extends AbstractUICommand {
    @Inject @WithAttributes(label = "Name", required = true, description = "Enter your name")  
    UIInput<String> input;

    @Inject DependencyResolver dependencyResolver;    
    
    @Inject @WithAttributes(label = "Version", required = true, description = "Select the version of PicketLink") 
    private UISelectOne<Coordinate> version;    
    
    @Override
    public void initializeUI(UIBuilder builder) throws Exception {
        builder.add(input);
        
        DependencyQuery query = DependencyQueryBuilder
                .create("org.picketlink:picketlink-api")
                .setFilter(new NonSnapshotDependencyFilter());

        List<Coordinate> coordinates = dependencyResolver.resolveVersions(query);
        version.setValueChoices(coordinates);
        builder.add(version);        
    }

    @Override
    public Result execute(UIExecutionContext context) throws Exception {
        return Results.success("Hello World");
    }
}

Rebuild and reinstall the addon, then invoke it from the Forge command window - you should see something that looks like this:

We can use these newfound powers to make changes to an actual project. Let’s start by modifying our addon class so that it extends AbstractProjectCommand instead of AbstractUICommand:

public class HelloWorldUICommand extends AbstractProjectCommand {

This will cause Eclipse to complain about unimplemented methods, so use Eclipse to generate them:

    @Override
    protected boolean isProjectRequired() {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    protected ProjectFactory getProjectFactory() {
        // TODO Auto-generated method stub
        return null;
    }

The isProjectRequired() method is used to determine whether this addon requires a project to execute. Since this is what we actually want, we’re going to return a value of true here:

    @Override
    protected boolean isProjectRequired() {
        return true;
    }

The getProjectFactory() method provides a reference to the currently selected project. To implement this method we first need to @Inject a ProjectFactory object into our addon class:

@Inject ProjectFactory projectFactory;

Then we simply return this value in the method body:

    @Override
    protected ProjectFactory getProjectFactory() {
        return projectFactory;
    }

So far so good! Now, since our goal is to add some dependencies to our project we need to somehow take the selected Coordinate value from our UISelectOne control and use it to add a dependency to the current project. Lucky for us Forge provides all of the tools to make this happen - first of all we’re going to inject a DependencyInstaller into our class:

@Inject DependencyInstaller dependencyInstaller;

Then, in the execute() method we’re going to use a DependencyBuilder to create a reference to the Dependency based on the Coordinate value contained in the UISelectOne control, after which we’ll tell the DependencyInstaller to install that Dependency into the selected project:

DependencyBuilder builder = DependencyBuilder.create();
builder.setCoordinate(version.getValue());

dependencyInstaller.install(getSelectedProject(context), builder);

The complete code listing should now look like this:

package com.acme.helloworld.ui;

import java.util.List;

import javax.inject.Inject;

import org.jboss.forge.addon.dependencies.Coordinate;
import org.jboss.forge.addon.dependencies.DependencyQuery;
import org.jboss.forge.addon.dependencies.DependencyResolver;
import org.jboss.forge.addon.dependencies.builder.DependencyBuilder;
import org.jboss.forge.addon.dependencies.builder.DependencyQueryBuilder;
import org.jboss.forge.addon.dependencies.util.NonSnapshotDependencyFilter;
import org.jboss.forge.addon.projects.ProjectFactory;
import org.jboss.forge.addon.projects.dependencies.DependencyInstaller;
import org.jboss.forge.addon.projects.ui.AbstractProjectCommand;
import org.jboss.forge.addon.ui.context.UIBuilder;
import org.jboss.forge.addon.ui.context.UIExecutionContext;
import org.jboss.forge.addon.ui.input.UIInput;
import org.jboss.forge.addon.ui.input.UISelectOne;
import org.jboss.forge.addon.ui.metadata.WithAttributes;
import org.jboss.forge.addon.ui.result.Result;
import org.jboss.forge.addon.ui.result.Results;

public class HelloWorldUICommand extends AbstractProjectCommand {
    
    @Inject ProjectFactory projectFactory;

    @Inject @WithAttributes(label = "Name", required = true, description = "Enter your name")  
    UIInput<String> input;
    
    @Inject DependencyInstaller dependencyInstaller;

    @Inject DependencyResolver dependencyResolver;    
    
    @Inject @WithAttributes(label = "Version", required = true, description = "Select the version of PicketLink") 
    private UISelectOne<Coordinate> version;    
    
    @Override
    public void initializeUI(UIBuilder builder) throws Exception {
        builder.add(input);
        
        DependencyQuery query = DependencyQueryBuilder
                .create("org.picketlink:picketlink-api")
                .setFilter(new NonSnapshotDependencyFilter());

        List<Coordinate> coordinates = dependencyResolver.resolveVersions(query);
        version.setValueChoices(coordinates);
        builder.add(version);        
    }

    @Override
    public Result execute(UIExecutionContext context) throws Exception {
        DependencyBuilder builder = DependencyBuilder.create();
        builder.setCoordinate(version.getValue());

        dependencyInstaller.install(getSelectedProject(context), builder);
        
        return Results.success("Hello World");
    }

    @Override
    protected boolean isProjectRequired() {
        return true;
    }

    @Override
    protected ProjectFactory getProjectFactory() {
        return projectFactory;
    }
}

Rebuild and reinstall your addon, then select a project in Eclipse and invoke our addon from the Forge command window. Keep in mind that we’ll be adding some new dependencies to the project you select so make sure it’s not something too important! I suggest you use the addon project itself as it is quite easy to remove the dependencies afterwards. Enter any value for the Name field (since we’ve marked it as required we’re forced to at least enter something) and select one of the dependencies from the Version control:

Click the Finish button and you should see the Hello World popup window appear briefly confirming that our addon ran successfully. To check it actually did something, open the project’s pom.xml in an editor and you should notice that Forge has added the selected dependency by declaring it in the <dependencyManagement> section:

And also adding the dependency itself to the <dependencies> section:

Congratulations, you’ve made it to the end! You’ve now created your first useful Forge addon that can add dependencies to an existing project. Hopefully this guide has helped by providing a high level overview of the Forge Addon architecture and a beginner’s primer on creating a new Forge Addon.

Summary

In this guide we went through the steps to build and install both the Forge Shell and Forge Eclipse Plugin, then learned how to create a new Forge Addon project. We also learned how to build and install our Addon, create custom dialog windows and have our Addon make changes to an existing project. If you’d like to learn more about Forge, then the following resources are available:

Forge web site: http://forge.jboss.org/

Documentation: http://forge.jboss.org/docs/index.html

Source code: https://github.com/forge

Thanks for reading!

13. Nov 2013, 02:48 CET, by Shane Bryzak

In this series we’ll be taking a magnifying glass to PicketLink, a security framework for Java EE. Each article in the series will examine a single aspect or feature of PicketLink in detail and also illuminate some of the design decisions made during the feature’s development.

Hopefully by the end of the series we’ll have helped you to gain a greater understanding of PicketLink, and how best to use it to address the security requirements of your own Java EE application.

Resources

At the time of writing the latest stable version of PicketLink is 2.5.2.Final. The latest version of both the PicketLink Reference Documentation and API Documentation can always be found at http://docs.jboss.org/picketlink/2/latest/.

The PicketLink binary distribution can be downloaded from the following page:

http://www.jboss.org/picketlink/downloads.html

If your build is Maven-based then please refer to the PicketLink Reference Documentation for information about how to include the PicketLink dependencies in your project.

You can find the latest version of the PicketLink source code at GitHub:

https://github.com/picketlink/picketlink

Identity Model

In this issue we’ll be looking at PicketLink’s Identity Model feature, a fundamental part of the PicketLink IDM (Identity Management) submodule that forms the foundation on which the majority of PicketLink’s other features are built.

During the design process for PicketLink IDM the development team spent a lot of time trying to work out the best way for modelling common security concepts such as roles and groups, etc. Faced with challenges relating to the lack of a common (or even de facto) standard for these core concepts it was decided that PicketLink required a certain level of abstraction to allow it to be customized per-deployment depending on the application’s security needs. Striking a balance between usability (for those that just wished to use PicketLink out of the box) and customizability (for applications that had more complex, or non-standard security requirements) posed a challenge that required an elegant solution.

The answer was the Identity Model - a set of interfaces and classes that provide a basic implementation so that PicketLink would just work(™), built on top of an abstraction layer that allows for a completely custom implementation.

The Identity Model defines the identity objects (such as Users and Roles) for your project, and the relationships between those objects. This is one of the major differences between PicketLink and other security frameworks - PicketLink supports a dynamic Identity Model, which means that there isn’t a hard-coded set of User, Role or Group classes that you are forced to use in your own application (PicketLink actually does provide these classes but you may choose not to use them). Why is it so important that PicketLink supports such a high level of customization? There are actually quite a number of reasons, so let’s take the time to explore a few of them in more detail.

Region Specific Attributes

Depending on where your project is being deployed, you may have specific requirements in relation to User state based on the region that your application may be servicing. For example, an application in the United States might require a User to have an SSN property, while an application in Russia might require a property to store a user’s patronym. In western culture a person may typically have a title, first name, middle name/s and last name, however this is certainly not the rule in many other cultures. It may be argued that these property values may be simply stored as arbitrary attribute values, like so:

user.setAttribute(new Attribute(“joinDate”, new Date()));

However storing these property values as ad-hoc attributes means we give up on important stuff like type safety and bean validation. If the property value is one that’s required for all of your users, then It’s much more desirable to be able to define these as first class properties of your bean, like so:

user.setJoinDate(new Date());

Custom Security Requirements

Security requirements may change drastically between applications, and a security architecture that may be sufficient for one application might be unsuitable for another. Let’s take roles for example - depending on who you ask, a role within an application might mean any number of things.

In some cases, a role equates to a simple, application-wide privilege that may be assigned directly to users. In Java EE5 for example the @RolesAllowed annotation may be used to restrict access to a class or method, allowing only the users that have been granted that specific role invocation rights:

@RolesAllowed(“admin”)
public void setBaseInterestRate(float value);

In other cases, a role might be something that may only be assigned to a group or mapped to a principal. Or it might only be valid within the context of a group (i.e. user jsmith has the logistics_support role for the retail_sales group). Or there may even be no such thing as roles at all, with all application privileges perhaps modeled as group memberships or using some alternative design. The point is there’s no single correct way to do security.

Because of the fact that everyone has different ideas of what constitutes a Security API, it is important that PicketLink provides the flexibility to allow custom scenarios to be supported.

Backend Identity Store Compatibility

In some environments your application may be required to conform to a pre existing security model. For example a corporate LDAP directory with heavily customised user attributes or a central SSO provider over which you have no direct control, or a legacy database containing user records. In these scenarios it's important that PicketLink is able to work within the bounds of an existing security architecture, and be able to accurately model its security objects.

Identity Model Building Blocks

Let’s get more technical now about what actually constitutes an Identity Model. A core set of interfaces from the org.picketlink.idm.model package define the foundation on which an Identity Model is built. Let’s take a look at these in the following class diagram:

We’ll be covering partitions in a future article so we can ignore the Partition interface for now. That leaves us with the following four core interfaces:

AttributedType - This is the root interface of the Identity Model. It basically provides methods for defining only two simple pieces of state - a globally unique identifier value assigned by PicketLink when an identity object is created, and a set of arbitrary attribute values. This means that every identity object (including users, roles, groups, and any other identity types you might create) at the very least has a unique identifier value, and is capable of storing a custom set of named attribute values of any Serializable type.

IdentityType - This is the parent interface for all identity types. In addition to the identifier and attribute properties inherited from the AttributedType interface, it also defines properties that reflect whether the identity object is enabled or not, the partition that it belongs to and the created date and optional expiration date for the identity.

Account - This is a special marker interface, which represents an identity type that is capable of authenticating. It is typically used as the superinterface for user identity types, or identity types that represent a third party process or agent that may interact with your application. Identity types such as roles or groups do not implement the Account interface as these types are not capable of authentication (i.e. they cannot log in), instead they implement the IdentityType interface directly.

Relationship - This is the super-interface for all relationship implementations. Like the Account interface it is also a marker interface, with no additional state (beyond that declared by its parent interface IdentityType) required by its contract.

There are a couple more important ingredients that we must know about besides the core interfaces described above when creating an identity model - the @AttributeProperty annotation and the @Unique annotation. We’ll cover these in more detail in the next section.

What does an actual Identity Model look like?

Good question! To answer this, we’ll take a look at the basic Identity Model provided out of the box by PicketLink. This model defines a number of commonly used identity objects and relationships, and in many cases may be sufficient for the security requirements of many typical applications. It can be easily extended or even copied to allow for convenient customization if desired.

Agent

The Agent class represents an external non-human identity that is capable of authenticating, hence it implements the Account interface. It defines getter and setter methods for a loginName property, which is used during authentication to identify the Account. Let’s take a look at the source code for this class (for the purpose of brevity some non-essential code has been trimmed):

public class Agent extends AbstractIdentityType implements Account {
    private String loginName;

    @AttributeProperty
    @Unique
    public String getLoginName() {
        return loginName;
    }

    public void setLoginName(String loginName) {
        this.loginName = loginName;
    }
}

There’s a few significant things to note about the above code. First of all, we can see that the Agent class extends AbstractIdentityType. This abstract class provides default implementations for all the methods of the parent IdentityType interface, allowing us to concentrate on the specific business logic for this identity class. If you wish to implement your own Identity Model then this can be a great time-saver.

Secondly, the @AttributeProperty annotation indicates that this is a property of the identity object that should be automatically mapped to the backend identity store. Each identity property that must be persisted should be annotated with @AttributeProperty. An example of a property that might not be annotated would be one with a calculated value, for instance a getFullName() method that simply concatenates the user’s first and last name together, yet doesn’t persist the calculated value itself in the backend identity store.

Thirdly, the @Unique annotation is used to indicate to PicketLink that the property must contain unique values. In this example it is used to ensure that the loginName property is unique (it should be obvious why it’s important that more than one account does not have the same login name).

Finally, we can observe that creating identity properties is as simple as defining a getter and setter method, following the JavaBean standard. Property values may be any serializable type.

User

The User class extends Agent to add some human-specific properties, such as first name, last name and so forth.

public class User extends Agent {
    @AttributeProperty
    private String firstName;

    @AttributeProperty
    private String lastName;

    @AttributeProperty
    private String email;

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getEmail() {
        return this.email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

In the above code, you may notice that the @AttributeProperty annotation is on the actual field declaration itself, instead of the getter method. PicketLink allows the annotation on either the field or the getter method, similar in fashion to JPA and its annotations.

Group

The Group class is an identity type that may be used for modelling basic group-related identity privileges, such as group membership and group roles. It is intended to be used in a hierarchical structure, with each group capable of having multiple subgroups and so forth. The Group class defines three property values - the name property represents the group’s unique name within the same branch of its hierarchical structure, the parentGroup property is an optional property which may be used to specify the group’s parent group (or null if the group has no parent, i.e. it is a root group), and path which represents the fully qualified path of the group, i.e. the complete hierarchical group name structure starting from the root, delimited by a separator.

public class Group extends AbstractIdentityType {
    public static final String PATH_SEPARATOR = "/";

    private String name;
    private Group parentGroup;
    private String path;

    @AttributeProperty
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @AttributeProperty
    @Unique
    public String getPath() {
        this.path = buildPath(this);
        return this.path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    @AttributeProperty
    public Group getParentGroup() {
        return this.parentGroup;
    }

    @AttributeProperty
    public void setParentGroup(Group group) {
        this.parentGroup = group;
    }

    private String buildPath(Group group) {
        String name = PATH_SEPARATOR + group.getName();

        if (group.getParentGroup() != null) {
            name = buildPath(group.getParentGroup()) + name;
        }

        return name;
    }
}

You may notice in the above code that the parentGroup property has a type of Group. This is possible because PicketLink allows identity definitions to themselves directly reference other identities via their properties. We can also notice that the getPath() method is annotated with @Unique - this is to ensure that group names are unique within their same group branch (i.e. no other group with the same parent group may have the same name).

Role

The Role class is quite similar to the Group class except that it doesn’t support a hierarchical structure, therefore its code is significantly more simple:

public class Role extends AbstractIdentityType {
    private String name;

    @AttributeProperty
    @Unique
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Relationships

Relationships are the constructs that help us to define the privileges for our identity objects by defining how they relate to each other. Relationships are typed associations between two or more identity objects.

A relationship class must implement the Relationship interface, which itself extends AttributedType - this means that every concrete relationship instance is assigned a unique identifier value, and is also capable of storing an arbitrary set of attribute values.

The basic identity model defines only three relationship types - Grant, which associates an identity with a role; GroupMembership, which similarly associates an identity with a group; and lastly GroupRole, which is used to assign a group-specific role to an identity. Let’s take a look at them in closer detail:

Grant

The Grant relationship is a simple association between a role and an assignee, and is generally used to assign coarse-grained application-wide privileges to a set of users.

public class Grant extends AbstractAttributedType implements Relationship {
    
    private IdentityType assignee;
    private Role role;

    public IdentityType getAssignee() {
        return assignee;
    }

    public void setAssignee(IdentityType assignee) {
        this.assignee = assignee;
    }

    public Role getRole() {
        return role;
    }

    public void setRole(Role role) {
        this.role = role;
    }
}

You may notice that there is nothing special about the above code - the Grant class extends AbstractAttributedType to provide the basic framework methods, however the implementation of the relationship itself is simple a couple of fields with getter/setter methods. This simplicity is intentional - as long as your property values implement the IdentityType interface then PicketLink is perfectly capable of working with your relationship class without any further effort required. This makes it extremely easy to define new custom relationship types yourself.

If you do wish to define a non-identity attribute property for your relationship, then you may do so by annotating the property with @AttributeProperty, the same way as is done when creating an identity type. For example, let’s say we would like to store the grant date for the above relationship - we could simply add a property like this:

    private Date grantDate;

    @AttributeProperty
    public Date getGrantDate() {
        return grantDate;
    }

    public void setGrantDate(Date grantDate) {
        this.grantDate = grantDate;
    }

Then we would be able to use it like so:

Grant grant = new Grant();
grant.setGrantDate(new Date());

Alternatively, you could of course just set an arbitrary attribute value:

Grant grant = new Grant();
grant.setAttribute(new Attribute(“grantDate”, new Date()));

Which option you would choose is totally up to you.

GroupMembership

The GroupMembership relationship is very similar to Grant, except that it is used to associate an account with a Group.

public class GroupMembership extends AbstractAttributedType implements Relationship {
    private Account member;
    private Group group;

    public Account getMember() {
        return member;
    }

    public void setMember(Account member) {
        this.member = member;
    }

    public Group getGroup() {
        return group;
    }

    public void setGroup(Group group) {
        this.group = group;
    }
}

Once again, there is absolutely nothing special about this implementation - it simply defines two property values with getter/setter methods.

GroupRole

The GroupRole relationship is used to represent a group-specific role, similar to Grant however restricted to the scope of a single group. To simplify the implementation of this relationship it extends the Grant relationship (which already provides the assignee and role properties), and just adds a group property:

public class GroupRole extends Grant implements Relationship {
    private Group group;

    public Group getGroup() {
        return group;
    }

    public void setGroup(Group group) {
        this.group = group;
    }
}

Like the above examples, the implementation is extremely simple - a single property with getter/setter methods.

Summary

Hopefully this article has been helpful in explaining how to work with PicketLink’s identity model, both in using the provided basic model and in describing how to create your own custom model, complete with identity and relationship classes.

If you have any questions or comments please post them below, and if you have any special requests for future PicketLink Deep Dive topics please let us know also.

Thanks for reading!

I'm pleased to announce the release of PicketLink 2.5.0.Beta3. This release is actually the successor to 3.0.0.Beta2 - we've changed the version number to help avoid confusion going forward, if you want the nitty gritty details about this decision then you can find out more below.

In case you don't know what it is, PicketLink is a security framework for Java EE applications. If you are already familiar with Seam Security, then you might consider PicketLink to be its spiritual successor. For more info about its features check out this overview.

As always, here's the direct links to the various resources for this release:

PicketLink 2.5.0.Beta3 Distribution Zip

Reference Documentation

API Documentation

Source on GitHub

Report Issues

Mailing List

Mailing List Archives

Forums

For those of you that use Maven, we've made a slight change to the artifact ids - from now on a typical application will only need to declare the following dependencies:

<dependency>
  <groupId>org.picketlink</groupId>
  <artifactId>picketlink-api</artifactId>
  <version>2.5.0.Beta3</version>
</dependency>

<dependency>
  <groupId>org.picketlink</groupId>
  <artifactId>picketlink-impl</artifactId>
  <version>2.5.0.Beta3</version>
  <scope>runtime</scope>
</dependency>

<!-- Optional database schema when using Identity Management with JPA based Identity Store -->
<dependency>
  <groupId>org.picketlink</groupId>
  <artifactId>picketlink-idm-schema</artifactId>
  <version>2.5.0.Beta3</version>
  <scope>runtime</scope>
</dependency>

For this release, the reference documentation has received some special attention and so should be significantly more informative than previous betas. With that being said, the team is constantly improving the docs and will continue to add more content right up to the final release. There are also numerous quickstarts planned to help you get up and running quickly with the many security features provided by PicketLink - I'll be posting some more info about some of these shortly so keep an eye on this space.

There have also been a substantial number of bug fixes, new features and improvements made since the last beta release, the details of which you'll find in the release notes below.

As always, the PicketLink team is available to chat with at various times of the day on the #picketlink IRC channel at freenode.net; also feel free to drop them a line at the PicketLink Forums if you need help using PicketLink in your own application.

Version Change

If you've been following any PicketLink-related news lately, you'll know that the PicketLink team has been working hard towards releasing PicketLink 3 in the very near future. It has recently come to the team's attention though that there is some confusion surrounding the versioning of PicketLink, which is due to a couple of reasons; firstly, there is an existing committment to support PicketLink Federation 2.1 in EAP (the supported version of JBoss Application Server, recently renamed to WildFly). Secondly, there was never an actual 2.x release of PicketLink IDM (it was only ever officially released as version 1.x). Because of this, and since the PicketLink Federation that was planned to be released as 3.0 is actually backwards compatible with 2.1, the team has decided to rename the 3.0 release to 2.5. So what does this mean exactly? Well, besides the change in version number, not much at all really - PicketLink 2.5 will still include all of the next generation security features that the PicketLink team have been working on over the past months. We apologise for any inconvenience that this change might have caused, however the team felt it was best to resolve this confusion now, before the final release.

Release Notes

Bug

  • PLINK-116 - Change scope for JBoss Logging dependency in picketlink-common module to provided
  • PLINK-119 - DefaultIdentity is considering the User.id when comparing with the DefaultLoginCredentials.userId
  • PLINK-131 - Signed logout request does not contain the "Destination" attribute
  • PLINK-132 - PicketLink based SP's need to support different login and logout URLs
  • PLINK-136 - The IDM subsystem is always initialized even when a custom Authenticator is provided
  • PLINK-137 - Change the scope for CDI dependencies in picketlink-api and picketlink-impl to provided

Enhancement

  • PLINK-126 - Introduce individual annotations for JPA schema entities and properties
  • PLINK-135 - Add type parameters to CredentialHandler

Feature Request

  • PLINK-113 - Users should be able to use a IdentityManager for any of the configured realms.
  • PLINK-117 - The API documentation should aggregate the javadocs for the modules
  • PLINK-118 - Update documentation with the File and LDAP stores configuration
  • PLINK-120 - Login logic is not considering when the user is disabled/locked
  • PLINK-121 - Throw a specific exception when the user tries to authenticate twice using the same credentials
  • PLINK-124 - Add credential storage retrieval methods to IdentityManager
  • PLINK-127 - CredentialHandler implementations should check if the Agent is disabled
  • PLINK-128 - Refactor the Configuration API to provide a Fluent API using the build pattern
  • PLINK-142 - Provide more examples about how to mix identity stores

Task

  • PLINK-92 - Container Bindings Project
  • PLINK-122 - Provide test cases for the base module
  • PLINK-125 - Umbrella task for 2.5.0.Beta3 documentation issues
  • PLINK-129 - Import the container bindings modules from PicketLink v2
  • PLINK-133 - Use getAgent() instead of getUser() throughout authentication API
  • PLINK-138 - Change project version from 3.0.0 to 2.5.0
Showing 1 to 5 of 34 blog entries