First PicketLink CDI Application
This guide will show you how to secure a very simple application using PicketLink. It will cover some core concepts and make it easier for you to understand how those concepts are applied in a project.
It will show you how to add the following capabilities to your application:
- Identity Management
- Authentication and Logout
System Requirements
Make sure your environment is properly configured as follows:
- Java 1.6 or Java 1.7
- Maven 3.0.0 or newer
- JBoss Enterprise Application Platform 6 or WildFly Servers.
Create a Maven Web Application Project
There are a lot of ways of doing this. One of them is by using a Maven Archetype to generate the project, as follows:
mvn archetype:generate -DgroupId=org.picketlink.tutorial -DartifactId=picketlink-app -DarchetypeArtifactId=maven-archetype-webapp
You can also use your favorite IDE to create the project. The important thing here is that you end up with a project with the following structure:
picketlink-app/ src/ main/ java/ webapp/ WEB-INF/ pom.xml
And your pom.xml should looks like this:
<project> <modelVersion>4.0.0</modelVersion> <groupId>org.picketlink.tutorial</groupId> <artifactId>picketlink-app</artifactId> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <name>First PicketLink CDI Application</name> <description>Tutorial about how to secure a simple application using PicketLink.</description> <build> <finalName>picketlink-app</finalName> </build> </project>
To check if your project is properly configured with Maven, execute the following command in the project's root folder:
mvn clean install
If everything is fine you should see following output from this command:
[INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------
You should also confirm that you have a WAR package at target/picketlink-app.war.
Configuring PicketLink Dependencies
Now that your project is created you can add the PicketLink Dependencies to it. For this we'll use the PicketLink Bill of Materials(BOM), which provides a simpler way to configure the dependencies of your project.
To configure the dependencies, add the following configuration to pom.xml:
<properties> <version.picketlink.javaee.bom>2.7.1.Final</version.picketlink.javaee.bom> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.picketlink</groupId> <artifactId>picketlink-javaee-6.0</artifactId> <type>pom</type> <scope>import</scope> <version>${version.picketlink.javaee.bom}</version> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.picketlink</groupId> <artifactId>picketlink</artifactId> <scope>compile</scope> </dependency> <dependency> <groupId>javax.enterprise</groupId> <artifactId>cdi-api</artifactId> <scope>provided</scope> </dependency> </dependencies>
The above configuration will make the PicketLink API libraries available to your project, so you can use them to build your classes later.
Configuring CDI and JSF
This application is CDI and JSF based. Given that, we need to enable both technologies for the project.
To enable CDI, you just need to add a src/main/webapp/WEB-INF/beans.xml marker file with the following content:
<!-- Marker file indicating CDI should be enabled --> <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"> </beans>
For JSF, you just need to add a src/main/webapp/WEB-INF/faces-config.xml marker file with the following content:
<!-- Marker file indicating JSF should be enabled --> <faces-config version="2.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xi="http://www.w3.org/2001/XInclude" 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/web-facesconfig_2_0.xsd"> </faces-config>
Creating the User Registration Bean
Now that CDI is properly configured, we can start creating some beans. The first bean we'll create is responsible for creating new users using the PicketLink Identity Management API.
@Named @RequestScoped public class UserRegistration { @Inject private IdentityManager identityManager; private String loginName; private String firstName; private String lastName; private String password; public String register() { User newUser = new User(this.loginName); newUser.setFirstName(this.firstName); newUser.setLastName(this.lastName); this.identityManager.add(newUser); Password password = new Password(this.password); this.identityManager.updateCredential(newUser, password); return "/signin.xhtml"; } // getters and setters }
Basically, this bean receives some input from a JSF page (which we'll create next) and stores a new user in an Identity Store. An Identity Store is a repository where all identity data is located, such as users, roles, groups, credentials, etc. When you don't provide any configuration for PicketLink IDM, it by default uses a File-based Identity Store. This is very handy for demos, during development and testing. But when doing things for real, you will probably prefer a LDAP or a Database as your Identity Store.
PicketLink supports differents identity stores, providing out-of-the-box implementations using LDAP and JPA. For more information about how to configure PicketLink IDM, please check our documentation.
Another important thing to consider in this bean is the usage of the IdentityManager
. This bean is used to manage identity objects within the scope of a partition. Some examples of identity objects are users, groups and roles, although PicketLink is not limited to just these. Besides providing the standard set of CRUD methods for managing and locating identity objects, the IdentityManager interface also defines methods for managing credentials and for creating identity queries which may be used to locate identities by their properties and attributes.
You may also notice that the bean also creates a credential for the user. In this case we're creating a Username/Password credential type, although PicketLink is not limited to just this. You can even provide your credential types and handlers. PicketLink also provides built-in support for other credential types such as DIGEST, Two-Factor Authentication and X509 Certificates.
For more information about PicketLink Identity Manager API, please check our documentation.
Creating the User Registration JSF Page
If you're familiar with JSF then there's no secrets here. We're just binding some form fields to the previously created UserRegistration
bean.
You need to add the following page at this location: src/main/webapp/signup.xhtml.
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"> <body> Please, enter your information:<br/><br/> <h:form> First Name: <h:inputText value="#{userRegistration.firstName}" required="true"/><br/> Last Name: <h:inputText value="#{userRegistration.lastName}" required="true"/><br/> Username: <h:inputText value="#{userRegistration.loginName}" required="true"/><br/> Password: <h:inputSecret value="#{userRegistration.password}" required="true"/><br/> <h:commandButton value="Finish" action="#{userRegistration.register}"/> </h:form> </body> </html>
Now that you have both page and backing bean created, you can try to create an user.
Deploying the Application
Deploying the application takes just a few simple steps. First, create a WAR package by running the following command in the project's root directory.
mvn clean package
This command will create a WAR package inside target/picketlink-app.war.
You can now start your server and copy this file to the ${JBOSS_HOME}/standalone/deployments directory to deploy the application. To check if the application is properly deployed you should be able to access it from your browser by entering the following URL:
User Authentication
Now that your application is registering new users you can authenticate them based on the information they provide on the registration page.
That said, let's create a login page. Add the following page at this location: src/main/webapp/signin.xhtml.
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"> <body> <ui:fragment rendered="#{not identity.loggedIn}"> Please, enter your credentials:<br/><br/> <h:form> Username: <h:inputText value="#{loginCredentials.userId}" required="true"/><br/> Password: <h:inputSecret value="#{loginCredentials.password}" required="true"/><br/> <h:commandButton value="Finish" action="#{identity.login}"/> </h:form> </ui:fragment> <ui:fragment rendered="#{identity.loggedIn}"> <h3>Welcome #{identity.account.firstName} !</h3> <h:form> <p>Click here to <h:commandLink action="#{identity.logout}">logout</h:commandLink>.</p> </h:form> </ui:fragment> </body> </html>
This is a very simple JSF page, divided into two fragments: one unprotected/public section and another section for authenticated users. Fragments are rendered depending on the return value of identity.loggedIn
, which returns true or false indicating whether the current user is authenticated or not.
PicketLink has a central component called the Identity
bean. The Identity
bean (which can be found in the org.picketlink package) is central to PicketLink's security API. This bean represents the authenticated user for the current session, and provides many useful methods for controlling the authentication process and querying the user's assigned privileges.
For more information about the Identity
bean, check our documentation.
This bean is able to be referenced directly from JSF pages using EL (@Named("identity")
) and also able to be injected into other CDI beans using the @Inject annotation. In our simple application, we don't need to create an authentication bean just to wrap the Identity
bean, we can just use it directly from the JSF page. The approach you decide to take depends on your requirements. If you want to perform some additional logic before and after authenticating users, you should create a bean and inject the Identity
bean in order to gain more control over the authentication process.
The credentials are provided by another PicketLink built-in component, the DefaultLoginCredentials
. Like the Identity
bean, it can also be referenced directly from JSF pages as well as being injected into other beans using the @Inject annotation. In the page above we are referencing the DefaultLoginCredentials
bean directly in order to bind both the userId and password values.
Username: <h:inputText value="#{loginCredentials.userId}" required="true"/><br/> Password: <h:inputSecret value="#{loginCredentials.password}" required="true"/><br/>
PicketLink allows you to use any type of credential you want, including your own custom credential types. The DefaultLoginCredentials
is just an out-of-the-box implementation of the Credentials
interface that supports a user ID and a credential value.
For more information about the DefaultLoginCredentials
bean, check our documentation.
Now that you know how to check if a user is authenticated and how to set their credentials and invoke the authentication process, let's take a look at how users are authenticated. The page above defines a login button which is configured to invoke the identity.login()
method. The login() method is the primary point of entry for the authentication process. Invoking this method will cause PicketLink to attempt to authenticate the user based on the credentials that they have provided.
When you invoke the identity.login()
method, the Identity
bean will invoke the methods of the active Authenticator
to perform user authentication using the credentials provided by the DefaultLoginCredentials
bean. So far we haven't seen any reference or configuration for the authenticator
, and this is fine. The reason is that PicketLink provides a built-in implementation that uses the PicketLink IDM API to retrieve users information and perform the authentication. Given that, we're ready to authenticate any user created by the previously created UserRegistration
bean, as it is using the PicketLink IDM API to store them.
You're not forced to use always the same Authenticator
, it is also possible to provide your own implementation and code the authentication process the way you want. For more details, take a look at our documentation. You can even support multiple authentication processes by providing multiple authenticators.
Another important Identity
bean method is the identity.logout()
. This method is responsible to logout users and invalidate their security context.
<p>Click here to <h:commandLink action="#{identity.logout}">logout</h:commandLink>.</p>
In a nutshell, PicketLink provides you complete control over the authentication process. You can provide your own credential types, use your own authenticators to better fit your authentication requirements, listen for specific authentication events such as when an user was authenticated, before and after the authentication begins, user already authenticated, locked account, authentication failed, logout, etc.
Check our documentation for more details.
Summary
Hopefully this guide helped you to understand some core concepts of PicketLink like the IdentityManager
and Identity
beans, how the authentication process works and the role of the PicketLink Identity Manager API.
We covered some important and basic concepts that will help you to deep dive into some more advanced concepts of PicketLink and create more advanced and complex usecases.
Most of the things we covered in this guide are also demonstrated by the quickstarts, from where you can get much more usage examples considering different usecases.
Fell free to contribute with your own guides and help us to improve PicketLink ! Enjoy it !