PicketLink part2

This is introduction part2 of PicketLink. previous article is here.
I will introduce picketlink-authentication-form at this time.
This example shows PicketLink with JSF.
This example exists here.

Execution environment
PicketLink 2.7.0.Final
WildFly 8.2.0.Final

Condition
CDI
JSF 2.0

Copyright

JBoss, Home of Professional Open Source
Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual
contributors by the @authors tag. See the copyright.txt in the 
distribution for a full listing of individual contributors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,  
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

picketlink-authentication-form.war
A war file is as follows.
warFile

/WEB-INF/beans.xml

<!-- 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>

beans.xml is same previous article.

/WEB-INF/faces-config.xml

<?xml version="1.0"?>
<!-- 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>

This is a JSF configuration file. This file is empty at this example.

SecurityInitializer.java

package org.jboss.as.quickstarts.picketlink.authentication.form;

import org.picketlink.idm.IdentityManager;
import org.picketlink.idm.PartitionManager;
import org.picketlink.idm.credential.Password;
import org.picketlink.idm.model.basic.User;

import javax.annotation.PostConstruct;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.inject.Inject;

/**
 ** This startup bean creates a default user account when the application is started. Since we are not
 ** providing an IDM configuration in this example, PicketLink will default to using a file-based identity
 ** store to persist user and other identity state.
 **
 **
 ** @author Shane Bryzak
 **/
@Singleton
@Startup
public class SecurityInitializer {

    @Inject
    private PartitionManager partitionManager;

    @PostConstruct
    public void create() {
        IdentityManager identityManager = this.partitionManager.createIdentityManager();

        User user = new User("jane");

        user.setEmail("jane@doe.com");
        user.setFirstName("Jane");
        user.setLastName("Doe");

        identityManager.add(user);
        identityManager.updateCredential(user, new Password("abcd1234"));
    }
}

This class sets user jane and password abcd1234.

HttpSecurityConfiguration.java

package org.jboss.as.quickstarts.picketlink.authentication.form;

import org.picketlink.config.SecurityConfigurationBuilder;
import org.picketlink.event.SecurityConfigurationEvent;

import javax.enterprise.event.Observes;

/**
 * <p>A simple CDI observer for the {@link org.picketlink.event.SecurityConfigurationEvent}.</p>
 *
 * <p>The event is fired during application startup and allows you to provide any configuration to PicketLink
 * before it is initialized.</p>
 *
 * <p>All the configuration related with Http Security is provided from this bean.</p>
 *
 * @author Pedro Igor
 */
public class HttpSecurityConfiguration {

    public void onInit(@Observes SecurityConfigurationEvent event) {
        SecurityConfigurationBuilder builder = event.getBuilder();

        builder
            .http()
                .allPaths()
                    .authenticateWith()
                        .form()
                            .loginPage("/login.xhtml")
                            .errorPage("/error.xhtml")
                .forPath("/logout")
                    .logout()
                    .redirectTo("/index.html");
    }

}

A allPaths method configures for all paths.
A authenticateWith method is used in order to configure authentication.
A form method is used in order to configure FORM authentication.
A loginPage method is used in order to configure login page. When no authenticated user accessed any path, the user is rediredted to the page configured here. Here, /login.xhtml is configured.
A errorPage method is used in order to configure redirected page when a user failed login. Here, /error.xhtml is configured.
A forPath method is used in order to configure path. Here, configured about /logout.
A logout method is used in order to logout. Here, when a user requested /logout, logout is executed.
A redirectTo method is used in order to configure redirected page after process completeted. Here, configured a user is redirected to /index.html after logout.

/index.html

<html>
<head>
    <meta http-equiv="Refresh" content="0; URL=home.jsf"/>
</head>
</html>

When a user accessed /index.html at first, /login.xhtml is called because protedted /index.html, too.

/login.xhtml

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:ui="http://java.sun.com/jsf/facelets">
<body>
<form method="POST" action="j_security_check">
 <input type="text" name="j_username"/>
 <input type="password" name="j_password"/>
 <input type="submit" name="login" value="Login"/>
</form>
<p>
Tip: you can login with a username/password of jane/abcd1234.
</p>

</body>
</html>

login
Here a user inputs username jane and password abcd1234.
When a user successed login, moves context path(/) at default.
In this example, after moved /index.html, /home.xhtml is called because <meta http-equiv=”Refresh” content=”0; URL=home.jsf”/> exists at /index.html.
When a user failed login, shows /error.xhtml.

/home.xhtml

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:ui="http://java.sun.com/jsf/facelets">
<body>
    <ui:fragment rendered="#{identity.loggedIn}">
        <meta http-equiv="Refresh" content="0; URL=protected/private.jsf"/>
    </ui:fragment>

    <ui:fragment rendered="#{not identity.loggedIn}">
        <h:form>
            <p>
                This is a public resource.
            </p>
            <p>
                Click <h:outputLink value="protected/private.jsf">here</h:outputLink> here to access the protected resources.
            </p>

            Tip: you can login with a username/password of jane/abcd1234.
        </h:form>
    </ui:fragment>
</body>
</html>

After a user logged in, #{identity.loggedIn} at line 5 become true and shows /protected/private.xhtml.

/protected/private.xhtml

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:ui="http://java.sun.com/jsf/facelets">
<body>
    <p>Hi <b>#{identity.account.loginName}</b>, this resource is protected. If you reach this page is because you're authenticated.</p>
    <p>Click here to <a href="#{request.contextPath}/logout">Logout</a></p>
</body>
</html>

private
Line 5, #{identity.account.loginName} is inserted login name jane.
When a user clicked /logout link, logout will execute and redirect to /index.html because configured by HttpSecurityConfiguration.java.
In this example, after logout, redirects to /index.html and furthermore moves /login.xhtml because protected /index.html.

/error.xhtml

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:ui="http://java.sun.com/jsf/facelets">
<body>
    Sorry, there was an error!
</body>
</html>

error
When a user failed login, this page will show.

2 Comments

  1. Fari

    Hi,
    when working with CDI 1.1 the SecurityConfigurationEvent will not be fired while starting up wildfly.
    Did you have any idea how to handle this problem.
    Ciao Fari

    • hoshi

      Hi.
      When you use CDI 1.1, you will have to write bean-discovery-mode=”all” at beans.xml.
      <?xml version=”1.0″ encoding=”UTF-8″?>
      <beans xmlns=”http://xmlns.jcp.org/xml/ns/javaee” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
      xsi:schemaLocation=”http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd
      bean-discovery-mode=”all”>
      </beans>

Comments are closed.