SeamFramework.orgCommunity Documentation
Identity Management is a feature that allows you to manage the users, groups and roles in your application. The Identity Management features in Seam Security are provided by PicketLink IDM. The best place to find more information about PicketLink IDM is the reference documentation, available here.
PicketLink provides two identity store implementations to allow you to use Hibernate or LDAP to store identity-related data (please refer
to the PicketLink IDM documentation for details on configuring these). Seam Security provides an additional implementation called
JpaIdentityStore
, which allows you to store your identity data using JPA.
In a Seam-based application it probably makes more sense to use the standards-based JpaIdentityStore
rather than
HibernateIdentityStore
, as you will most likely be running in an Java EE container that supports JPA.
JpaIdentityStore
is an implementation of the PicketLink IdentityStore
interface, provided by Seam Security.
This identity store allows you to store your identity model inside a relational database, accessible via JPA. It provides an immense
amount of flexibility in the way you define your identity model, and in most cases should be compatible with existing database schemas.
See the idmconsole example application (included in the Seam distribution) for a demonstration of Seam's Identity Management features.
Like all authentication providers in Seam, Identity Management is supported via a concrete Authenticator
implementation called IdmAuthenticator
. To use Identity Management in your own application, you don't
need to do anything! Simply don't configure any authenticator, and as long as you have an identity store
configured (see the next section), the Identity Management API will be used to authenticate automatically.
While JpaIdentityStore
should be compatible with a large variety of database schemas, the following diagram displays
the recommended database schema to use:
Seam Security provides two annotations for configuring your entity beans for use with JpaIdentityStore
.
The first, @IdentityEntity
is a class annotation used to mark an entity bean so that
JpaIdentityStore
knows it contains identity-related data. It has a single member of type EntityType
,
that tells JpaIdentityStore
what type of identity data it contains. Possible values are:
The second one, IdentityProperty
, is a field or method annotation which is used to configure which
properties of the bean contain identity values. This annotation declares two values, value
and attributeName
:
package org.jboss.seam.security.annotations.management;
public @interface IdentityProperty {
PropertyType value();
String attributeName() default "";
}
The value()
member is of type PropertyType
, which is an enum that defines the following values:
public enum PropertyType {
NAME, TYPE, VALUE, RELATIONSHIP_FROM, RELATIONSHIP_TO, CREDENTIAL,
CREDENTIAL_TYPE, ATTRIBUTE }
By placing the IdentityProperty
annotation on various fields of your entity beans, JpaIdentityStore
can determine how identity-related data must be stored within your database tables.
In the following sections we'll look at how each of the main entities are configured.
Let's start by looking at identity object. In the recommended database schema, the IDENTITY_OBJECT
table
is responsible for storing objects such as users and groups. This table may be represented by the following entity
bean:
@Entity
@IdentityEntity(IDENTITY_OBJECT)
public class IdentityObject implements Serializable {
@Id @GeneratedValue private Long id;
@IdentityProperty(PropertyType.NAME)
private String name;
@ManyToOne @IdentityProperty(PropertyType.TYPE)
@JoinColumn(name = "IDENTITY_OBJECT_TYPE_ID")
private IdentityObjectType type;
// snip getter and setter methods
}
In the above code both the name
and type
fields are annotated with @IdentityProperty
.
This tells JpaIdentityStore
that these two fields are significant in terms of identity management-related
state. By annotating the name
field with @IdentityProperty(PropertyType.NAME)
, JpaIdentityStore
knows that this field is used to store the name of the identity object. Likewise, the
@IdentityProperty(PropertyType.TYPE)
annotation on the type
field indicates that the value of this
field is used to represent the type of identity object.
The IdentityObjectType
entity is simply a lookup table containing the names of the valid identity types. The
field representing the actual name of the type itself should be annotated with @IdentityProperty(PropertyType.NAME)
:
@Entity
public class IdentityObjectType implements Serializable {
@Id @GeneratedValue private Long id;
@IdentityProperty(PropertyType.NAME) private String name;
// snip getter and setter methods
}
The credentials table is used to store user credentials, such as passwords. Here's an example of an entity bean configured to store identity object credentials:
@Entity
@IdentityEntity(IDENTITY_CREDENTIAL)
public class IdentityObjectCredential implements Serializable {
@Id @GeneratedValue private Long id;
@ManyToOne @JoinColumn(name = "IDENTITY_OBJECT_ID")
private IdentityObject identityObject;
@ManyToOne @IdentityProperty(PropertyType.TYPE)
@JoinColumn(name = "CREDENTIAL_TYPE_ID")
private IdentityObjectCredentialType type;
@IdentityProperty(PropertyType.VALUE)
private String value;
// snip getter and setter methods
}
The IdentityObjectCredentialType
entity is used to store a list of valid credential types. Like
IdentityObjectType
, it is a simple lookup table with the field representing the credential type
name annotated with @IdentityProperty(PropertyType.NAME)
:
@Entity
public class IdentityObjectCredentialType implements Serializable
{
@Id @GeneratedValue private Long id;
@IdentityProperty(PropertyType.NAME)
private String name;
// snip getter and setter methods
}
The relationship table stores associations between identity objects. Here's an example of an entity bean that has been configured to store identity object relationships:
@Entity
@IdentityEntity(IDENTITY_RELATIONSHIP)
public class IdentityObjectRelationship implements Serializable
{
@Id @GeneratedValue private Long id;
@IdentityProperty(PropertyType.NAME)
private String name;
@ManyToOne @IdentityProperty(PropertyType.TYPE) @JoinColumn(name = "RELATIONSHIP_TYPE_ID")
private IdentityObjectRelationshipType relationshipType;
@ManyToOne @IdentityProperty(PropertyType.RELATIONSHIP_FROM) @JoinColumn(name = "FROM_IDENTITY_ID")
private IdentityObject from;
@ManyToOne @IdentityProperty(PropertyType.RELATIONSHIP_TO) @JoinColumn(name = "TO_IDENTITY_ID")
private IdentityObject to;
// snip getter and setter methods
}
The name
property is annotated with @IdentityProperty(PropertyType.NAME)
to indicate that this
field contains the name value for named relationships. An example of a named relationship is a role, which uses the
name
property to store the role type name.
The relationshipType
property is annotated with @IdentityProperty(PropertyType.TYPE)
to indicate
that this field represents the type of relationship. This is typically a value in a lookup table.
The from
property is annotated with @IdentityProperty(PropertyType.RELATIONSHIP_FROM)
to indicate
that this field represents the IdentityObject
on the from side of the relationship.
The to
property is annotated with @IdentityProperty(PropertyType.RELATIONSHIP_TO)
to indicate
that this field represents the IdentityObject
on the to side of the relationship.
The IdentityObjectRelationshipType
entity is a lookup table containing the valid relationship types. The
@IdentityProperty(PropertyType.NAME)
annotation is used to indicate the field containing the relationship
type names:
@Entity
public class IdentityObjectRelationshipType implements Serializable {
@Id @GeneratedValue private Long id;
@IdentityProperty(PropertyType.NAME)
private String name;
// snip getter and setter methods
}
The attribute table is used to store any additional information that is to be associated with identity objects. Here's an example of an entity bean used to store attributes:
@Entity
@IdentityEntity(IDENTITY_ATTRIBUTE)
public class IdentityObjectAttribute implements Serializable {
@Id @GeneratedValue private Integer attributeId;
@ManyToOne
@JoinColumn(name = "IDENTITY_OBJECT_ID")
private IdentityObject identityObject;
@IdentityProperty(PropertyType.NAME)
private String name;
@IdentityProperty(PropertyType.VALUE)
private String value;
// snip getter and setter methods
}
The name
field is annotated with @IdentityProperty(PropertyType.NAME)
to indicate that this field
contains the attribute name. The value
field is annotated with @IdentityProperty(PropertyType.VALUE)
to indicate that this field contains the attribute value.
The Identity Management features are provided by a number of manager objects, which can be access from an
IdentitySession
. The IdentitySession
may be injected directly into your beans
like so:
import org.picketlink.idm.api.IdentitySession;
public @Model class IdentityAction {
@Inject IdentitySession identitySession;
// code goes here...
}
Once you have the IdentitySession
object, you can use it to perform various identity management
operations. You should refer to the PicketLink documentation for a complete description of the available features,
however the following sections contain a brief overview.
Users and groups are managed by a PersistenceManager
, which can be obtained by calling
getPersistenceManager()
on the IdentitySession
object:
PersistenceManager pm = identitySession.getPersistenceManager();
Once you have the PersistenceManager
object, you can create User
objects with the
createUser()
method:
User user = pm.createUser("john");
Similarly, you can create Group
objects with the createGroup()
method:
Group headOffice = pm.createGroup("Head Office", "OFFICE");
You can also remove users and groups by calling the removeUser()
or removeGroup()
method.
Relationships are used to associate User
objects with Group
objects. Relationships can
be managed with the RelationshipManager
object, which can be obtained by calling
getRelationshipManager()
on the IdentitySession
:
RelationshipManager rm = identitySession.getRelationshipManager();
Relationships are created by invoking the associateUser()
method, and passing in the group and user
objects that should be associated:
rm.associateUser(headOffice, user);
Roles are managed via the RoleManager
object, which can be obtained by invoke the
getRoleManager()
method on the IdentitySession
object:
RoleManager roleManager = identitySession.getRoleManager();
Roles are an association between a user and a group, however they are slightly more complex than a simple
group membership as the association also has a role type. The role type is generally
used to describe a particular function of the user within the group. Role types are represented by the
RoleType
object, and can be created with the createRoleType()
method:
RoleType manager = roleManager.createRoleType("manager");
Roles can be assigned to users by invoking the createRole()
method, and passing in the
RoleType
, User
and Group
:
Role r = roleManager.createRole(manager, user, headOffice);