3.5. Creating a Custom Identity Model
A custom identity model typically consists of two types of objects - the identity objects which define the security constructs of an application, and the relationships which define how the identity objects interract with each other to establish a meaningful security policy. PicketLink treats both types of object in an abstract manner, so it is up to the developer to create meaning for these objects and their relationships within the context of their own application. This section will describe how to create new identity objects and customize their properties and attributes, while the following section will complete the picture by describing how custom relationships are created.
Let's start by looking at the source for some of the identity objects in the basic model, starting with the
Agent
and User
objects:
@IdentityStereotype(USER) public class Agent extends AbstractIdentityType implements Account { private String loginName; public Agent() { } public Agent(String loginName) { this.loginName = loginName; } @AttributeProperty @StereotypeProperty(IDENTITY_USER_NAME) @Unique public String getLoginName() { return loginName; } public void setLoginName(String loginName) { this.loginName = loginName; } }
@IdentityStereotype(USER) public class User extends Agent { private String firstName; private String lastName; private String email; public User() { } public User(String loginName) { super(loginName); } @AttributeProperty public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } @AttributeProperty public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } @AttributeProperty public String getEmail() { return this.email; } public void setEmail(String email) { this.email = email; } }
The
Agent
class is intended to represent a third party entity that may authenticate against an application, whether human (a user) or non-human (an external or remote process). Because Agent
implements the Account
marker interface, it is making a declaration that this identity object is capable of authenticating. To support the typical username/password authentication method, the Agent
class defines a loginName
property, however since the Account
interface enforces no particular method of authentication (instead of a using username for authentication your application may require a certificate or fingerprint) this property is arbitrary.
The
User
class represents a human user and extends Agent
to add the human-specific properties firstName, lastName and email. Since human users are also capable of authenticating it will also inherit the loginName
property from the Agent
.
3.5.1. The @AttributeProperty
Annotation
In the code above we can see that the getter methods of the identity objects are annotated with
@AttributeProperty
. This annotation (from the org.picketlink.idm.model.annotation
package) is used to indicate that the property of the identity object should be persisted by the configured identity store when creating or updating the identity object. If this annotation was missing, then the property value would be null
when loading the identity object from the identity store.
In this example, the annotation is placed on the getter method however it is also valid to place it on the corresponding field.
This annotation also allows you to set a specific propery of a type as a managed attribute. Managed attributes are very useful to build custom identity models with minimal changes to the underlying identity stores. However, in order to support it, your configuration must also support attribute management. For more details about managed attributes, please take a look at Section 6.4, “Managed attributes”.
To set a property as a managed attribute, just use the
AttributeProperty
annotation as follows:
@AttributeProperty(managed=true) private int failedLoginAttempts;