31 User Management on the Delivery System

WebCenter Sites provides authentication functionality through the USER tags, user profile management through the DIR tags, and enforces security on database tables and rendered pages through access control lists (ACLs). You use these user management and security mechanisms to manage users and control visitor access on your distribution system and on your WebCenter Sites development and management systems.

This chapter contains the following sections:

31.1 The Directory Services API

The Directory Services API enables your WebCenter Sites system to connect to directory servers that contain authentication information, user information, and so on.

WebCenter Sites delivers three directory services plug-ins, one of which was installed when your WebCenter Sites systems were installed:

  • The WebCenter Sites directory services plug-in, which uses the native WebCenter Sites user management tables; that is, the SystemUsers and SystemUserAttrs tables

  • The LDAP plug-in, which actually supports any JNDI server

  • The NT plug-in, which retrieves user credentials and login name from the NT directory but gets all other user information from the SystemUserAttrs table

The plug-in is installed during the installation of your WebCenter Sites systems and it is configured by setting properties in the dir.ini file. For information about configuring your user management setup, see the Oracle Fusion Middleware WebCenter Sites Administrator's Guide.

This section contains the following topics:

31.1.1 Entries

A directory entry is a named object with assigned attributes, in particular, user and group type entries:

  • A user type object has a distinguished name and a set of attributes such as commonname, username, password and email.

  • A group type object, similar to a WebCenter Sites ACL, also has a distinguished name and a set of attributes.

Names reflect the hierarchy in which they are associated; to ensure portability across directory implementations, names should be treated as opaque strings.

31.1.2 Hierarchies

Some directory databases organize entries using a hierarchical structure. With WebCenter Sites's directory services API, an entry's attributes and its place in the hierarchy are distinct. As a result, retrieving an entry's attributes does not yield information about its children.

Support for hierarchies depends on the underlying directory implementation; for example, LDAP directories support a hierarchical structure, while WebCenter Sites's native directory database does not support a hierarchical structure.

To ensure portability across directory implementations, your code should not assume support for hierarchical data.

Group hierarchies do not affect internal WebCenter Sites permissions.

31.1.3 Groups

WebCenter Sites's directory services API does not enforce referential integrity. When you delete a user with the directory tags, your application must ensure that group memberships are also deleted, by first removing the user from the groups that he is associated with.

When a member is added to a group, the JNDI implementation always builds a fully distinguished name for the value of the uniquemember attribute, regardless of the name passed into the addmember tag.

31.1.4 Directory Services Tags

WebCenter Sites delivers the DIR tag family, with both XML and JSP versions, that you can use to invoke the Directory Services API.

The DIR tags are as follows:

Tag Description

DIR.ADDATTRS

dir:addattrs

Adds attributes to an existing entry (which can be either a user or a group).

DIR.ADDGROUPMEMBER

dir:addgroupmember

Adds a member to a group (usually a user).

DIR.CHILDREN

dir:children

Retrieves the child entries for a specified parent in a list variable.

DIR.CREATE

dir:create

Creates a directory entry.

DIR.DELETE

dir:delete

Deletes a directory entry.

DIR.GETATTRS

dir:getattrs

Gets the attribute values for a specified entry in a list variable.

DIR.GROUPMEMBERS

dir:groupmembers

Lists the members of a specified group.

DIR.GROUPMEMBERSHIPS

dir:groupmemberships

Lists all the groups that an entry (either a group or a user) belongs to.

DIR.LISTUSERS

dir:listusers

Returns a list of all the users in the directory.

DIR.REMOVEATTRS

dir:removeattrs

Deletes an attribute value for an entry.

DIR.REMOVEGROUPMEMBER

dir:removegroupmember

Removes an entry from a group.

DIR.REPLACEATTRS

dir.replaceattrs

Replaces the value of an attribute for an entry (either a user or a group).

DIR.SEARCH

dir:search

Searches the directory for entries who match the specified search criteria.


Regardless of whether the directory is implemented with LDAP, WebCenter Sites only, or any other directory server, the code you write with the DIR tags is very similar.

For more information about these tags, see the Oracle Fusion Middleware WebCenter Sites Tag Reference. For code samples, see Section 31.1.5.4, "Directory Services Code Samples."

31.1.5 Directory Operations

Some of the WebCenter Sites Directory Services tags write information to the database. If your database administrators will be handling all of the website's write operations, such as adding user information to the database, restrict use of the directory tags to
read-only operations. This policy avoids synchronization issues with third-party directory administration tools.

The read-only operations are presented in this section. Operations are performed using the credentials and read permissions of the currently authenticated user.

31.1.5.1 Searching

Due to limitations in some directory servers, search is not allowed from the top organizational level. To avoid portability issues, always specify the context attribute on the DIR.SEARCH tag.

31.1.5.2 Lookup

Looking up a user generally involves two steps:

  1. Call DIR.SEARCH on the userid to get the entry name.

  2. Call DIR.GETATTRS to get the attributes of the user in question.

31.1.5.3 Listing Users

It is recommended that you use one of the following three methods to list users:

  • For small user databases, use the DIR.LISTUSERS tag, which recursively lists all users under the peopleParent property. This tag is inefficient on large user databases.

  • For large user databases, use the DIR.CHILDREN tag to walk the hierarchy. The DIR.CHILDREN tag is best used for group types and not for user types.

  • For user databases with a flat hierarchy, narrow results with a search

31.1.5.4 Directory Services Code Samples

The following JSP code sample illustrates some possible directory operations:

<%
String sMainTestUserName = "ContentServer";
String sMainTestUserPW="FutureTense";

String sPeopleParent = ics.GetProperty("peopleparent", "dir.ini", true);
String sGroupParent = ics.GetProperty("groupparent", "dir.ini", true);
String sUsername = ics.GetProperty("username", "dir.ini", true);
String sCommonName = ics.GetProperty("cn", "dir.ini", true);
IList mylist;
%>

<user:su username='<%=sMainTestUserName%>' password='<%=sMainTestUserPW%>'>

<H2>List All Users</H2>

<ics:clearerrno/>
<dir:listusers list='mylist'/>
<br>
<b>dir:listusers errno: <ics:getvar name='errno'/></b>
<ics:listloop listname='mylist'>
<br><ics:listget listname='mylist' fieldname='NAME'/>
</ics:listloop>

<H2>Look Up the ContentServer User by Username</H2>

<ics:clearerrno/>
<dir:search list='mylist' context='<%=sPeopleParent%>'>
<dir:argument name='<%=sUsername%>' value='ContentServer'/>
</dir:search>
<br><b>dir:search errno: <ics:getvar name='errno'/></b>

<%
mylist = ics.GetList("mylist");
if(mylist.numRows() != 1) {
        out.print("<br>Error finding entry.");
}
mylist.moveTo(1);
ics.SetVar("ContentServerDn", mylist.getValue("NAME"));
%>

<H2>Show ContentServer Attributes</H2>

<ics:clearerrno/>
<dir:getattrs list='mylist' 
name='<%=ics.GetVar("ContentServerDn")%>'/>
<br><b>dir:getattrs errno: <ics:getvar name='errno'/></b>
<ics:listloop listname='mylist'>
<br>
<ics:listget listname='mylist' fieldname='NAME'/>=
<ics:listget listname='mylist' fieldname='VALUE'/>
</ics:listloop>

<H2>Show Group Memberships for ContentServer</H2>

<ics:clearerrno/>
<dir:groupmemberships name='<%=ics.GetVar("ContentServerDn")%>'
list='mylist'/>
<br><b>dir:groupmemberships errno: <ics:getvar name='errno'/></b>
<ics:listloop listname='mylist'>
<br>
<ics:listget listname='mylist' fieldname='NAME'/>
</ics:listloop>

<H2>Lookup the SiteGod Group by CommonName</H2>

<ics:clearerrno/>
<dir:search list='mylist' context='<%=sGroupParent%>'>
<dir:argument name='<%=sCommonName%>' value='SiteGod'/>
</dir:search>
<br><b>dir:search errno: <ics:getvar name='errno'/></b>

<%
mylist = ics.GetList("mylist");
if(mylist.numRows() != 1) {
        out.print("<br>Error finding entry.");
}
mylist.moveTo(1);
ics.SetVar("SiteGodDn", mylist.getValue("NAME"));
%>

<H2>Show SiteGod Attributes</H2>

<ics:clearerrno/>
<dir:getattrs list='mylist' name='<%=ics.GetVar("SiteGodDn")%>'/>
<br>
<b>dir:getattrs errno: <ics:getvar name='errno'/></b>
<ics:listloop listname='mylist'>
<br>
<ics:listget listname='mylist' fieldname='NAME'/>=
<ics:listget listname='mylist' fieldname='VALUE'/>
</ics:listloop>

<H2>Show SiteGod Group Members</H2>

<ics:clearerrno/>
<dir:groupmembers name='<%=ics.GetVar("SiteGodDn")%>' list='mylist2'/>
<br>
<b>dir:groupmembers errno: <ics:getvar name='errno'/></b>
<ics:listloop listname='mylist2'>
<br>
<ics:listget listname='mylist2' fieldname='NAME'/>
</ics:listloop>

<H2>Children of groupparent </H2>

<ics:clearerrno/>
<dir:children name='<%=sGroupParent%>' list='mylist'/>
<br>
<b>dir:children errno: <ics:getvar name='errno'/></b>
<ics:listloop listname='mylist'>
<br>
<ics:listget listname='mylist' fieldname='NAME'/>
</ics:listloop>

</user:su>

31.1.6 Error Handling

Any of the directory tags can cause a range of directory errors to be set. See the Oracle Fusion Middleware WebCenter Sites Tag Reference for a comprehensive list of directory services error messages.

Your directory services code should handle every one of the error codes listed for a given tag call. This is necessary to support the J2EE JNDI interface.

31.1.7 Troubleshooting Directory Services Applications

The first step in troubleshooting directory services applications is to check the error log (in the WebCenter Sites log file).

You enable directory services logging by setting the log.filterLevel property (found in the logging.ini property file). There are seven levels of error messages that you can view:

  • fatal, which logs fatal level messages

  • severe, which logs severe and fatal level messages

  • error, which logs error and fatal level messages

  • warning, which logs warning and fatal level messages

  • info, which logs warning, error, severe, and fatal level messages

  • trace, which logs trace messages

  • detail, which logs all types of messages

During troubleshooting, trace is the most verbose setting, and as a result, has the highest performance impact.

Directory services log entries use the following format:

[<timestamp>][Directory-<severity>-<errno>]
[<class>:<method>][<message>][<session id>]

For example:

[Jan 17, 2002 1:49:44 PM][Directory-T]
[BaseFactory:instantiateImplementation(ICS,String,Class[],
Object[])][Instantiating:com.openmarket.directory.common.Factory]
[PEccxyF1Ueh7zYvjNgg4D6bqZzf0llfWMaiBimIN9H1Z9KomDcPy]

The previous message is a trace (T), and thus has no associated errno value.

For information about error logging, see Chapter 10, "Error Logging and Debugging."

A common problem for LDAP implementations is incorrectly specified permissions on the directory server. If the error log indicates a permission problem, ensure that the authenticated user has permissions to execute the requested operation by checking the permission settings on the directory server. Try logging into the directory server directly (outside of WebCenter Sites) and performing the same action to ensure that permissions are correctly set. After checking the log and permissions, you can often resolve a configuration error by examining the property files.

For property descriptions and values, see the Oracle Fusion Middleware WebCenter Sites Property Files Reference.

31.2 Controlling Visitor Access to Your Online Sites

WebCenter Sites manages users through access control lists (ACLs). By using ACLs, you can restrict access to tables in the WebCenter Sites database and the rendered pages served on your sites by WebCenter Sites.

If you design an online site where visitors log in with user names and passwords, you can associate registered visitors with one or more ACLs.

When a visitor first visits a site, WebCenter Sites creates a session and implicitly logs in the visitor as the standard default user, DefaultReader. The identity of a visitor is updated (and any associated ACLs go into effect) when a USER.LOGIN command is used and the visitor is authenticated against a password.

This section contains the following topics:

31.2.1 ACL Tags

WebCenter Sites provides a set of access control list tags (both XML and JSP versions) that you can use to create ACLs. You can use either the WebCenter Sites interface on the delivery system or the WebCenter Sites ACL tags to create the ACLs that you need for your visitor accounts on your delivery system.

The following table lists the ACL tags:

Tag Description

ACL.CREATE

acl:create

Creates an ACL

ACL.DELETE

acl:delete

Deletes an ACL

ACL.GATHER

acl:delete

Gathers fields into an ACL

ACL.GET

acl:get

Copies a field from an ACL

ACL.LIST

acl:list

Retrieves a list of ACLs

ACL.LOAD

acl:load

Loads an ACL

ACL.SAVE

acl:save

Saves an ACL

ACL.SCATTER

acl:scatter

Scatters a field from an ACL

ACL.SET

acl:set

Sets a field in an ACL


For more information:

31.2.2 User Tags

WebCenter Sites also provides the following USER tags (both XML and JSP versions) that you use on pages that log users in and out.

The USER tags are as follows:

Tag Description

USER.LOGIN

user:login

Logs a user in.

USER.LOGOUT

user:logout

Logs a user out.

USER.SU

user:su

Logs the user in as a specific user in order to perform an operation such as creating an account or edit a user profile.


For more information about these tags, see the Oracle Fusion Middleware WebCenter Sites Tag Reference.

31.2.3 WebCenter Sites and Encryption

WebCenter Sites includes a default key for encrypting passwords and other sensitive information. You can specify your own encryption key by using the Utilities class encryptString method. See the Oracle Fusion Middleware WebCenter Sites Java API Reference for information about Java methods that deal with encryption.

WebCenter Sites also supports Secure Sockets Layer (SSL), which allows encryption of information going to and from your web servers. For more information about WebCenter Sites and SSL, see the Oracle Fusion Middleware WebCenter Sites Administrator's Guide.

31.3 Creating Login Forms

This section provides simple code samples that illustrate how to code login forms that prompt a visitor to log in and then authenticate the user name and password.

This example presents code from the following elements:

  • PromptForLogin: XML element that displays a form that requests a username and password

  • Login: XML element that authenticates the username and password combination passed to it from the PromptForLogin element

This section contains the following topics:

31.3.1 Prompt for Login (PromptForLogin.xml)

The PromptForLogin element displays a form that asks a visitor to enter two pieces of information: username and password.

The code that creates the form follows:

<DIV ALIGN="center">
<FORM ACTION="ContentServer" METHOD="post">
<INPUT TYPE="hidden" NAME="pagename" VALUE="CSGuide/Security/Login"/>

<TABLE CELLPADDING="5" CELLSPACING="5">

<TR>
<TH ALIGN="right">Name</TH>
<TD><INPUT TYPE="text" NAME="username" SIZE="16"/></TD>
</TR>

<TR>
<TH ALIGN="right">Password</TH>
<TD><INPUT TYPE="password" NAME="password" SIZE="16"/></TD>
</TR>

<TR>
<TD>&nbsp;</TD>
<TD ALIGN="center"><INPUT TYPE="submit" NAME="doit" VALUE="Login"/></TD>
</TR>

</TABLE>

</FORM>
</DIV>

The visitor fills in the form and clicks the Submit button. The information gathered in the form and the page name of the Login page (see the first input type statement, above) is sent to the browser. The browser sends the page name to WebCenter Sites, WebCenter Sites looks it up in the SiteCatalog table and then invokes that page entry's root element.

31.3.2 Root Element for the Login Page

There can only be one root element for a WebCenter Sites page (that is, an entry in the SiteCatalog table). The root element for the Login page is the Login.xml element.

The Login element attempts to log the visitor in and then to authenticate the visitor by using the USERISMEMBER tag to determine whether the visitor has any of the required ACLs.

This element does the following:

  • Logs the visitor in with the USER.LOGIN tag and checks to see if there was an error.

  • Sets a variable list that holds a list of ACLs to compare the visitor's credentials against.

  • Checks the visitor's ACLs assignments against the list variable with the USERISMEMBER tag

The following sample code authenticates the visitor:

<SETVAR NAME="errno" VALUE="0"/>

<USER.LOGIN USERNAME="Variables.username" PASSWORD="Variables.password"/>

<IF COND="Variables.errno=0">
                <THEN>
                <H3>Welcome <CSVAR NAME="Variables.username"/></H3>

<!-- Next, create a variable named aclToCheck and set it to hold the ACLs that the visitor needs to progress any further on the site. This variable can be set to one ACL or to a comma-separated list of ACLs, as in this example-->

<SETVAR NAME="aclToCheck" VALUE="ContentCustomer,SiteGod"/>
<SETVAR NAME="errno" VALUE="0"/>

<USERISMEMBER GROUP="Variables.aclToCheck"/>
<IF COND="Variables.errno=1">
        <THEN>
        <P>You are a member of the at least one of the following acls:       
        <CSVAR NAME="Variables.aclToCheck"/></P>
        </THEN>
    <ELSE>
                        <P>Sorry, you are not a member of any of the following acls:
                        <CSVAR NAME="Variables.aclToCheck"/></P>
    </ELSE>
    </IF>

</THEN>
<ELSE>

    <H3>Sorry, can't find your credentials.</H3>

</ELSE>
</IF>

31.4 Creating User Account Creation Forms

This section provides simple code samples that illustrate how to code forms that prompt a visitor to register (obtain a user account) and then create a user account for that visitor.

This example presents code from the following elements:

  • PromptForNew Account: XML element that displays a form that requests the visitor to enter the user name and password that he or she would like to use

  • CreateAccount: JSP element that creates the new account

This section contains the following topics:

31.4.1 PromptForNewAccount

The PromptForNewAccount element displays a form that prompts the visitor to enter a user name and password and to re-enter the password to confirm it.

Here's the code that creates the form:

<div align="center">
<h3>Create a New Account</h3>
<FORM ACTION="ContentServer" METHOD="post">
<input type="hidden" name="pagename" value="CSGuide/Security/CreateAccount"/>

<table cellpadding="5" cellspacing="5">

<tr>
<th align="right">Pick a username</th>
<td><input type="text" name="username" size="16"/></td>
</tr>

<tr>
<th align="right">Pick a password</th>
<td><input type="password" name="password" size="16"/></td>
</tr>

<tr>
<th align="right">Confirm your new password</th>
<td><input type="password" name="confirm_password" size="16"/></td>
</tr>

<tr>
<td>&nbsp;</td>
<td><input type="submit" name="doit" value="Create Account"/></td>
</tr>
</table>

</FORM>
</div>

The visitor fills in the form and clicks the Submit button. The information gathered in the form and the page name of the CreateAccount page (see the first input type statement, above) is sent to the browser.

The browser sends the page name to WebCenter Sites, WebCenter Sites looks it up in the SiteCatalog table and then invokes that page entry's root element.

31.4.2 Root Element for the CreateAccount Page

There can only be one root element for a WebCenter Sites page (that is, an entry in the SiteCatalog table). The root element for the CreateAccount page is the CreateAccount.jsp element.

Only someone with SiteGod or ContentEditor ACLs can create a new user account. Because of this restriction, the CreateAccount element does the following:

  • Logs the visitor in as a privileged user, without the knowledge of the visitor.

  • Creates the account.

  • Assigns the new user the appropriate ACLs (every user must belong to at least one ACL)

Here's the code that creates the new user account:

<SETVAR NAME="errno" VALUE="0"/>

<!-- switch temporarily to a privileged user -->
<!-- The username and password for the privileged user should be encrypted in a property file. You should obtain them from the property file, decrypt them, then pass them it. For this example, they are hard-coded. -->

<USER.SU USERNAME="jumpstart" PASSWORD="jumpstart">

<USERISMEMBER GROUP="UserEditor"/>
<IF COND="Variables.errno!=1">
<THEN>
        <h3>An error has occurred creating the account (no UserEditor
        privs).  Contact the webmaster</h3>
</THEN>
<ELSE>
    <IF COND="Variables.password!=Variables.confirm_password">
        <THEN>
        <h3>Your passwords do not match. Click the Back button and 
        try again.</h3>
        </THEN>
        <ELSE>

<!-- Get the parameters from the property file -->

                <ics.getproperty name="username" file="dir.ini"
                output="unameattr"/>
                <ics.getproperty name="password" file="dir.ini"
                output="passattr"/>

<!-- create the user's name in the right format for the dir tags -->

                <ics.getproperty name="peopleparent" file="dir.ini"
                output="namebase"/>
                <name.makechild context="Variables.namebase" output="iname">
                        <name.argument name="Variables.unameattr"
                        value="Variables.username"/>
                </name.makechild>
        
<!-- create the user -->

                <dir.create name="Variables.iname">
                <dir.argument name="Variables.unameattr"
                value="Variables.username"/>
                <dir.argument name="Variables.passattr"
                value="Variables.password"/>

<!-- additional parameters can be added here but for the example we won't -->
<!-- In particular, if you are using LDAP, you will have to spin through and set the values of the properties in the property requiredPeopleAttrs in dir.ini. -->

        </dir.create>

        <IF COND="Variables.errno=0">
        <THEN>

<!-- give the new user an acl and format it correctly for dir.addgroupmember -->

                        <ics.getproperty name="groupparent" file="dir.ini"
                        output="groupparent"/>
                        <ics.getproperty name="cn" file="dir.ini" output="cn"/>
                        <name.makechild context="Variables.groupparent"
                        output="groupid">
                                <name.argument name="Variables.cn" value="Browser"/>
                        </name.makechild>

<!-- add the acl -->

                        <dir.addgroupmember name="Variables.groupid"
                        member="Variables.iname"/>

                        <IF COND="Variables.errno=0">
                                <THEN>
                <h3>Success!</h3>
                                </THEN>
                                <ELSE>
                                        <h3>User created but error adding user to group. 
                                        Contact the webmaster</h3>
                                </ELSE>
                        </IF>

                </THEN>
                <ELSE>
                        <h3>Error creating user!  Contact the webmaster.</h3>
                </ELSE>
        </IF> <!-- create success check -->

        </ELSE>
</IF> <!-- passwords match -->

</ELSE>
</IF> 

</USER.SU>

31.5 Visitor Access in the Burlington Financial Sample Site

The Burlington Financial sample site includes a membership component that uses elements to sign up new members and log in existing members.

These visitor registration elements are not robust enough for use on a real-world website, but can give you a starting point for your own designs. For example, Burlington Financial has sample visitor account screens, allowing visitors to register and set their own preferences, but does not use this information to restrict visitor access to certain web pages, or to make recommendations based on a member's profile.

This section contains the following topics:

31.5.1 Membership Table

Burlington Financial uses a table named bfmembers to implement the membership component. (This table is created for the sample site when it is installed. None of the WebCenter Sites modules or products use this table.) Although the membership elements add a row to the bfmembers database table for each new registered member's profile information, they do not add a row to the SystemUsers table.

31.5.2 Users and Passwords

There is one generic user, BFUser, for all Burlington Financial members. The name and password are the same (BFUser/BFUser) and should not be changed. The member login code in Burlington Financial sets a session variable for the visitor, which is then used to identify that visitor.

Because Burlington Financial is a sample site, members' passwords are stored in the bfmembers table as plain text. A real website would store passwords in encrypted format. Burlington also grants Visitor, BFMember, and Browser ACL privileges to entries added to the bfmembers table.

31.5.3 Member Accounts

There are currently no elements for managing the Burlington Financial accounts. If you want to try editing or deleting members' accounts, use Oracle WebCenter Sites Explorer to modify the bfmembers table.

31.5.4 Membership Processing Elements

There are several elements that handle processing requests for Burlington Financial members. If you have installed the Burlington Financial sample site, you can use Oracle WebCenter Sites Explorer to open and examine them. All but one is located here:

ElementCatalog/BurlingtonFinancial/Util/Account

The AccountAccessScript element is located here:

ElementCatalog/BurlingtonFinancial/Util

AccountAccess.xml

This is a page template that calls pagelet elements for the header, footer, navigation menu, and the account content.

AccountAccessScript.xml

This file contains three JavaScript routines (checkSignupForm, checkProfileForm, and checkLoginForm) that perform basic error checking on the HTML account forms. This is called from Login.xml, Profile.xml, and SignUp.xml elements.

Benefits.xml

This page calls the Block.xml article template to render an article of text about the Burlington Financial site. On a real website, the article would contain benefits information.

Login.xml

This page displays the login screen for registered members and calls LoginPost.xml to handle the login form input. It also calls Benefits.xml, and SignUp.xml for non-members.

LoginPost.xml

This pagelet element calls ProcessLogin.xml to display a login message.

Profile.xml

This page displays an editable profile form if the visitor is registered, or else calls SignUp.xml if the visitor is not registered.

ProcessLogin.xml

This pagelet element displays an appropriate login message, depending on whether the visitor who submitted the form is a registered member.

SignUp.xml

This page displays the sign-up screen for non-registered visitors and calls the catalogmanager to add a row to the bfmembers table for a new user, or to update the bfmembers table for an existing user.