au·then·tic adjective ə-ˈthen-tik,
: real or genuine : not copied or false

*http://www.merriam-webster.com/dictionary/authentic

User identities in IT applications serve many purposes. User experience can be personalized, information access restricted or feedback interaction enabled, to name a few. However, identities only become usable after two conditions are met. First an identity needs to be asserted, for example by a user entering its name. Next, the asserted identity needs to be confirmed as genuine. The second step is referred to as authentication.

Oracle Knowledge Management is an application that utilizes user identities to enhance its functionality and secure its content. It is provided with an internal authentication mechanism, as well as the possibility to connect to an external ldap user store. While both methods work well, they may not always satisfy the authentication requirements for any situation. One may need multiple authentication sources, or may want to separate access rights for different environments. Luckily the product comes with a third option, an interface for custom authentication: the IAuthenticator. This article provides some pointers for those adventurous enough to take the latter option. It is written to answer some common questions for technical consultants in the process of implementing an IAuthenticator. Basic Java programming experience is required.

The OKM custom authentication mechanism
First we need some background on the OKM authentication mechanism. If the application is configured to use custom authentication, the following sequence of steps takes place:

  1. Login credentials are provided to the InfoManager or InfoCenter application, either from the login page fields, or from http request headers when Single Sign On is used.
  2. These credentials are delegated to the Inquira Authenticator. This is not the IAuthenticator yet, but the non-customizable authentication class within the application.
  3. The InquiraAuthenticator will call the authenticate() method of your custom authenticator class. This method takes three parameters:
    – The first parameter is an array of com.inquira.infra.security.FieldValue objects. A FieldValue is essentially a key-value pair. The array passes the provided username, password, repository name for which the login was attempted, plus all http request headers of the login attempt (very nice!). The last part opens up possibilities for Single Sign On customization or other neat things of the sort.
    – The second parameter is a java.util.Map object, which in Oracle documentation is referred to as the roles2PermissionsMap. This Map contains all Role, View and Group reference keys that are defined in the repository for which a login is attempted. Roles are prefixed with R_, views with V_ and groups with G_. For example, if your repository contains a role with reference key TEST_ROLE, the roles2PermissionsMap will contain an entry by the name of R_TEST_ROLE.
    – The third parameter is a long integer type timestamp of the login attempt.
  4. The authenticate() method performs its magic. This is the logic you will write and customize to your own needs. Purpose of this code is to figure out if provided credentials are correct and what roles, views and groups your user is a member of in the external authentication store. If no user can be authenticated, a com.inquira.infra.security.InquiraAuthenticationException can be thrown to notify the InquiraAuthenticator of this fact.
  5. The authenticate() method returns an object of class com.inquira.infra.security.impl.RoleBasedUser (implements com.inquira.infra.IUser interface). The RoleBasedUser contains a number of properties like loginname, first name, last name, email address, roles, views and groups of the authenticated user.
  6. The RoleBasedUser object is picked up by the InquiraAuthenticator, which will read its properties, verify permissions and update the USERINFORMATION table in your IM database schema with the new information. From here the normal OKM IM authentication process takes over again.

 

Code example
An example often tells more than the most elaborate description. Therefore I created a very basic example of an authenticate() method.

    /**

     * Implementation of the IAuthenticator authenticate() method. Performs the

     * actual authentication steps. Returns an IUser if auth is successful. If

     * not, throws an InquiraAuthenticationException.

     */


    @Override

    public IUser authenticate(FieldValue[] userInfo,

            @SuppressWarnings(“rawtypes”) Map roles2PermissionsMap,

            long timestamp) throws InquiraAuthenticationException {

        String userId = null;

        String password = null;

        String repository = null;

        // Loop through the userInfo values to get username, password, and

        // repository name

        for (int i = 0; i < userInfo.length; i++) {
            FieldValue fieldValue = userInfo[i];

            // If this field is a FIELD_USER_ID (normal application username)

            // and not empty or null

            if (fieldValue.getName().equals(FIELD_USER_ID)) {

                userId = fieldValue.getValue();

            }

            // If this field is a FIELD_PASSWORD

            if (fieldValue.getName().equals(FIELD_PASSWORD)) {

                password = fieldValue.getValue();

            }

            // If this field is a FIELD_DOMAIN (repository name)

            if (fieldValue.getName().equals(FIELD_DOMAIN)) {

                repository = fieldValue.getValue();

            }

        }

        // For some reason our custom code does not like users by the name of

        // foo with password bar

        if (userId.equals(“foo”) && password.equals(“bar”)) {

            throw new InquiraAuthenticationException(

                    “this user is not allowed to authenticate”);

        }

        // This part is not used for IM applications but must not be null.

        // Therefore a dummy.

        Permissions permissions = new Permissions();

        permissions.add(new StandardPermission(“none”));

        // Set roles and views we “found” from our external authentication

        // store. In this example, two dummy values.

        // In your implementation, this is where you start digging in external

        // databases, ldap servers etc.

        HashSet rolesAndViews = new HashSet();

        rolesAndViews.add(“DUMMY_ROLE”);

        rolesAndViews.add(“DUMMY_VIEW”);

        // Create the RoleBasedUser

        RoleBasedUser rbUser = null;

        try {

            rbUser = new RoleBasedUser(userId, repository,

                    “Dummy first and last name”new SimplePrincipal(userId),

                    rolesAndViews, permissions, timestamp, null);

        } catch (InquiraSecurityException e) {

            e.printStackTrace();

        }

        // Set the user’s email address

        rbUser.setEmailAddress(“dummy@dummy.com”);

        // Give our authenticated user back

        return rbUser;

    }

 
 

Good luck and happy coding!

Arthur Vogels
Oracle Knowledge consultant at Ebicus.