209
CHAPTER 8
Security and Single
Sign-On
S
ECURITY AND
S
INGLE
Sign-On (SSO) are not unique to portlets, but when consid-
ering their implementation you must take into account some special advantages,
disadvantages, and responsibilities.
A portlet has some security advantages over a conventional application. You
do not have to concern yourself with obtaining a login from the user, for example—
this is the responsibility of the container.
You do still have some responsibilities; your portlet must manage access to
its resources. For example, a corporate address book should probably be accessible
only to employees of the company, whereas a private address book should in gen-
eral be accessible by only one person.
A portlet may obtain information from external resources, so you also need
to be aware of the options for passing security information around—possibly
over the network.
While the developer’s natural inclination is to “Keep It Simple, Stupid” (KISS),
it is no longer a safe assumption (if it ever was) that the network is secure by
default. Avoiding security vulnerabilities adds a regrettable but necessary level
of complexity to the design of any portlet acting as the gateway to sensitive
information.
This chapter discusses the standards, protocols, and APIs that are required to
implement secure portlets. The security mechanisms specified in the portlet API
are the most basic level of portlet security. We discuss SSO strategies for portals,
including authentication with Java Authentication and Authorization Services
(JAAS). We also demonstrate how to use the Java Generic Security Services
Application Program Interface (GSS-API) with Kerberos.
Before we embark on our analysis, let’s briefly consider a situation where all
of these tools might be required for a truly integrated solution. In the example
shown in Figure 8-1, we have users connecting to (and authenticating with) a por-
tal using their normal browser security. This contains a portlet e-mail application,
which uses the user’s credentials to log into and present a web mail application. This
in turn must access a legacy e-mail database, presenting the user’s credentials to
do so.
2840ch08.qxd 7/13/04 12:44 PM Page 209
Download at Boykma.Com
Chapter 8
210
E-mail is a very familiar environment for almost all users, and the need for
the protection of private messages is obvious. We suggest that you consider this
example as you encounter the security technologies available to you when build-
ing a portlet.
Portlet Security
Generally, a portlet passively receives user authentication and authorization infor-
mation from the container. It is often not necessary for your portlet to directly
establish the identity of the user. As a result, when designing a simple secured
portlet to be entirely portable, you need only concern yourself with the way that
your portlet interacts with its security environment.
This holds true only when a portal has its own access control for portlets, either
on a per-user or per-group basis. Some portals allow a user to add any installed
portlet to the user’s portal page. Most portal deployments require some kind of
security or access control for administrative portlets. This can be accomplished by
allowing only certain users or sets of users to show a portlet on their page, or by
having the portlet code check the user’s information to determine what they are
allowed to view.
Browser
Portlet
Web Mail
Application
Authentication
Server
Legacy E-mail
Database
Portal
(Portlet Container)
Figure 8-1. Portlet security interactions
2840ch08.qxd 7/13/04 12:44 PM Page 210
Download at Boykma.Com
Security and Single Sign-On
211
Similarities to Servlet Security
Since a portlet is generally contained within a servlet, it should come as no great
surprise to discover that a portlet behaves quite like a servlet in its provision of
security mechanisms.
The
HttpServletRequest
object provided with requests to a servlet is required
to offer the following four methods:
public String getAuthType()
public String getRemoteUser()
public boolean isUserInRole(String role)
public Principal getUserPrincipal()
The information provided by these four methods is in turn made available
directly to a portlet via the
PortletRequest
object. The same four methods are avail-
able from the request object during the action handling and during render handling.
Authentication Types
Portlets generally permit four types of authentication. Which of these has been
used can be determined by calling
getAuthType()
. This method allows a portlet to
determine the quality of the secure relationship and as a result to restrict the set
of information that it will permit the user to access.
In Basic authentication, the username and password are obtained from the
web client (browser), which manages the mechanism of obtaining them from the
user and submitting them to the server. The web browser sends the details as
plaintext, so they are vulnerable to “man-in-the-middle” attacks.
NOTE
Man-in-the-middle attacks are a form of security attack where some-
one sets up a proxy server between an unknowing client and an unknowing
server. The proxy server listens to requests from the user and records them. The
requests are passed to the server, and the server returns a response to the proxy
server. The proxy server also logs the response, and then passes the response
back to the client. The “man in the middle” now has all of the user’s requests
and responses. If the browser has sent any sensitive information as unen-
crypted text, it is now compromised. The attacker may also alter the user’s
requests and responses.
Client Certificate authentication requires the server and, optionally, the
client to authenticate each another with public key certificates. The exchange is
2840ch08.qxd 7/13/04 12:44 PM Page 211
Download at Boykma.Com
Chapter 8
212
carried out over Secure Sockets Layer (SSL) to guarantee that it cannot be read if
it is intercepted. Client Certificate authentication is managed by the web client.
Digest authentication is about halfway between Basic and Client Certificate
authentication. The username and password are not sent in plaintext; instead they
are sent as a message digest, which prevents the password from being retrieved.
However, as with basic authentication, the identity of the server is not verified
and the exchange is carried out over an unsecured connection so there is still some
degree of vulnerability.
NOTE
A message digest is an arbitrarily short representation of a message.
A “hash function” is applied to the original message to produce this short rep-
resentation. A trivial example of a hash would be one that counted the
number of words in the message.
A more typical example is the MD5 algorithm, which will reduce a message of
any length to 16 representative bytes. The chances of any two messages pro-
ducing the same digest are astronomically small, and it is effectively
impossible to reverse-engineer the original message from its MD5 hash.
This makes the MD5 hash perfect for confirming a password over a network.
The remote server will send the client a random “salt” text. This is added by
the client to the password, and the digest is computed. The client sends the
digest to the server, which will compute the digest independently and com-
pare it with the client’s digest. If they match, both machines must know the
password, but an eavesdropper cannot reproduce the digest independently
(without knowing the password).
The use of a salt prevents a third party from simply retransmitting the digest,
since it will be different for every salt value.
Form-based authentication is one of the most commonly used forms of authen-
tication, largely because it can be made secure and offers cosmetic advantages
over web client–managed mechanisms. The username and password are sub-
mitted as plaintext in a form request. If the POST mechanism is used and the
connection is over HTTPS (SSL) rather than HTTP, this cannot easily be inter-
cepted. The
PortletRequest
class provides the constants that are used to identify
each authentication type.
It is also possible that no authentication will have been carried out, in which
case
getAuthType()
will return null.
Identifying the User
The
getRemoteUser()
method provides the username of the current user of the
portal. The username is generally not considered to be a sensitive piece of infor-
2840ch08.qxd 7/13/04 12:44 PM Page 212
Download at Boykma.Com
Security and Single Sign-On
213
mation; on the contrary, it is normal to use the username extensively as an identifier
of objects and in tables. However, you should bear in mind that the username
may not be a simple direct representation of the user’s name. It may, for example,
include the details of the authentication domain that this user is associated with.
While you can reasonably expect the username in this form to be unique, confu-
sion can arise. Consider for example:
In these two cases, what one colloquially thinks of as the username is “dave”,
but in fact two distinct users are identified—one associated with the example.com
domain; the other with paperstack.com.
We will not belabor the point, but it is wise to retain the full string returned
by
getRemoteUser()
to avoid ambiguities.
Obtaining a Principal
The principal represents a user (or service, or server) whose identity has been
confirmed by the portal. It is distinct from a username, because there is no prin-
cipal for an unauthenticated user. Note that in practice
getRemoteUser()
is likely
to return null for unauthenticated users anyway, because the authentication process
is often the mechanism by which the user is established.
The
getUserPrincipal()
method therefore returns the
Principal
object asso-
ciated with the current logged-in user, or null if the user has not been logged in.
You may not immediately see the need for a separate object to represent this—
surely one could use a combination of the username and an
isAuthenticated()
method? However, the principal serves an important purpose when you wish to
indicate to another service that our service is entitled to act on behalf of the user
in question.
NOTE
This sort of situation arises often with portals, because they can aggre-
gate quite distinct systems into a common interface. Take as an example an
investment bank’s systems. There may be distinct systems for bond and equi-
ties trading, and these systems in turn talk to a set of back-end databases.
When using a portal to unify the systems, users must first present their cre-
dentials to the portal, which in turn establishes a Principal, which is passed
to the bond system and the equities system. These in turn use it to gain access
to the back-end databases. By using the end user’s credentials all the way
through the system, a secure audit trail can be maintained, albeit with a per-
formance penalty.
2840ch08.qxd 7/13/04 12:44 PM Page 213
Download at Boykma.Com
Chapter 8
214
The principal is an instance of the
java.security.Principal
interface. You can
call the
getName()
method on it, and in general this will return the same string
that you would retrieve from a call to
getRemoteUser()
, although it is not required.
In the example given in the previous section, the string returned might be
“” or just “dave”.
Using Roles
Portlet roles work in exactly the same way as servlet roles. Roles are represented
by strings, and any given user can be assigned to a specific role, or a group of
roles.
The idea is that a role name should represent the rights and duties of a user
rather than being the privileges assigned. So for instance, Manager is a good name
for a role, whereas ListSalaries is not.
To determine if a user falls within a given role, call the
isUserInRole()
method
and pass in the name of the role. The method will return
true
or
false
appropri-
ately. If the current user is null (i.e., not logged in), this method will always return
false
.
Since the mappings of the native security system may not correspond naturally
to those of the portlet application (or indeed to those of a servlet application),
a facility is provided to allow a security role to be mapped to an additional name,
in effect allowing the developer or deployer to assign aliases to roles.
As is normal with servlets, an entry can be placed in the portlet application’s
web.xml deployment descriptor file to specify a
<security-role-ref>
element for
an existing role name. The format is
<security-role-ref>
<role-name>ForumModerator</role-name>
<role-link>Administrator</role-link>
</security-role-ref>
In this example, the native role of Administrator is mapped to the applica-
tion role of ForumModerator.
Working with portlets you may also specify a mapping in the same form within
the
<portlet>
element of the portlet.xml file.
When
isUserInRole()
is called, the system checks each file in turn, so if no
suitable role name is listed in the portlet.xml, the system checks the web.xml. If
that in turn contains no suitable role name entries, the native security system will
be tested for the appropriate principal’s role memberships.
2840ch08.qxd 7/13/04 12:44 PM Page 214
Download at Boykma.Com
Security and Single Sign-On
215
Single Sign-On Strategies
SSO is essentially a technical solution to a usability problem. Users are not good
at remembering several different passwords, and they dislike being made to enter
a password numerous times.
For example, the authors have worked for various companies where this is
a problem. Dave used to work for a company where there was a separate login to
the workstation, to the e-mail system, to the timekeeping system, to the database,
and to each of the six different systems that he was developing interfaces for.
The situation is common on the Internet. Your bank, auction site, web mail
account, and so on are likely to have distinct usernames and passwords. Some
services have sprung up to try to unify logins between sites. Microsoft Passport
and the Liberty Alliance are competing standards in this domain; they are SSO
solutions at the interorganizational level.
When building an SSO solution for services accessed via portlets, you have
slightly different considerations, and indeed, SSO does not refer to a single
technology, or even a single strategy for solving the problem. There are distinct
approaches, which we will now discuss in the context of portlets.
Using True SSO
True SSO is the term we will adopt for the “perfect” solution. In this scenario, your
user enters a username and password only once—when logging in to the portal.
Problems with this approach arise when legacy systems are involved. Most
of our examples will discuss using Kerberos to manage authentication between
the portals and external services, but this is a relatively new protocol. Older sys-
tems can be difficult or expensive to update to accommodate Kerberos or
another standard SSO technology.
CAUTION
Our examples use the Kerberos v5 software from MIT, as this is the
reference implementation of the standard. The example code would require
changes to work with Microsoft Active Directory.
Using Proxy SSO
Proxy SSO, as the name suggests, uses a proxy system to carry out sign-ons for us.
Users log into the portal with their username and password, and this in turn
unlocks a store of usernames and passwords for external systems.
The advantage of this system is that, as presented, it offers the same user
experience as True SSO. However, it is something of a compromise and this can
cause administrative problems.
2840ch08.qxd 7/13/04 12:44 PM Page 215
Download at Boykma.Com
Chapter 8
216
The approach necessitates management of the passwords for the systems.
Different legacy systems may require password changes at different times. Users
will still have to remember (or, dangerously, write down) the individual passwords
so that they can change them when they expire, or alternatively the passwords will
need to be set not to expire at all, which is in itself a security risk. For seamless
integration, the proxy SSO server would need to manage the life cycle for each
username and password pair. If the proxy SSO server had rules for each legacy
system that dictated the password expiration, the range of valid password values,
and the ability to change passwords, this could all be managed for the user. The
integration development costs for a project like this would be very high.
Because the passwords must be retrieved in order to present them to the
legacy systems, they must be stored by the proxy SSO solution in an encrypted
form that decrypts to plaintext. This is generally considered undesirable. More
desirable would be a solution that stores a message digest or hash of the password,
so the original password cannot be reconstructed.
Using a Common Registry
The common registry approach is something of a compromise between the
true and proxy SSO solutions. While it does not require full implementation of
a GSS-API–compliant system, it does require some changes to any legacy systems
involved.
The idea is that a central system is used to carry out all authentication, but
that users are prompted for usernames and passwords each time they access
a different system. However, subsequent access to the same systems within the
login session does not require reauthentication.
Perhaps the term “Single” Sign-On is a misnomer here, since of course the
user is making multiple login efforts, but because a single username and pass-
word combination is required, far less is required of the user. In practice this is
often a satisfactory solution, and it has the advantage that it is compatible with
a migration to the True SSO solution as the legacy systems are retired.
In a portlet environment, the attraction of this approach is less obvious, since
it is possible that users would be initially presented with a great number of portlets
on their home page, each and every one of which could initially demand a user-
name and password before they can be used!
Authenticating with JAAS
We have encountered a small part of the Java Authentication and Authorization
Services (JAAS) in our coverage of the
Principal
object returned by the
getUserPrincipal()
method of the
PortletRequest
object.
2840ch08.qxd 7/13/04 12:44 PM Page 216
Download at Boykma.Com
Security and Single Sign-On
217
The portlet generally obtains a principal in this manner, so you can get by
without knowing how to do this manually. However, it is enlightening to see the
mechanism used in practice, and in some SSO scenarios—especially the proxy
scenario—it can be necessary.
At the point that you conduct a login, some details of the login mechanism must
be known. You cannot generally log in to a Unix system using NTLM (Microsoft)
authentication, and most authentication systems provide no discovery mechanism
to determine the protocol in use.
JAAS is therefore based on an API called Pluggable Authentication Modules
(PAM), which allows you to try a login on a system or systems using a variety of
different protocols. As a result, you can conduct a JAAS login, at the end of which
one or more systems may have vouched for your credentials.
The protocols to be used are generally specified using a configuration file.
This can contain individual or multiple entries.
// Kerberos.config
ClientAuthentication
{
com.sun.security.auth.module.Krb5LoginModule required;
};
ServerAuthentication
{
com.sun.security.auth.module.Krb5LoginModule required storeKey=true;
};
Here we have specified two distinct configurations. One is for our client, and
the other for a server that we will be demonstrating later in the chapter. For the
client authentication, a
LoginModule
has been specified, and we have indicated
that a login using this module is required in order to consider the authentication
successful. Additional parameters may be provided (as shown in the server exam-
ple, where the
storeKey
parameter is specified), but are not necessary for our
login example.
Login modules are objects that know how to talk the appropriate protocol to
establish a login to a particular type of authentication server—in this case a Kerberos
v5 server.
NOTE
Kerberos v5 is a well-respected enterprise-grade security system from
MIT. Using brief exchanges of information, Kerberos can determine the iden-
tity of users without ever needing to see their password. Kerberos can also
supply participants with security keys, allowing them to set up a secure chan-
nel of communication between participants with a minimal overhead.
Kerberos forms the core of the authentication system in Microsoft Active
Directory, and implementations exist for most platforms.
2840ch08.qxd 7/13/04 12:44 PM Page 217
Download at Boykma.Com
Chapter 8
218
A small set of modules are provided with the Java 2 SDK, and others are avail-
able either for free or commercially. For example at
/>index.jsp
a set is available that will permit you to authenticate against Windows NT
servers using the NTLM protocol, to authenticate using credentials stored in
a text file, or to authenticate against credentials stored in a database table.
The login modules in the Java 2 Standard Edition 1.4.2 SDK are contained in the
com.sun.security.auth.module
package. These modules include the Kerberos login
module we are using, an NT login module, a Unix login module, and a Java Naming
and Directory Interface (JNDI) login module.
The example application to conduct a JAAS login in Kerberos follows:
import javax.security.auth.*;
import javax.security.auth.callback.*;
import javax.security.auth.login.*;
public class Authentication {
public static class KerberosCallbackHandler implements CallbackHandler {
public KerberosCallbackHandler(String principal, String password) {
this.principal = principal;
this.password = password;
}
public void handle(Callback[] callbacks) {
for (int i = 0; i < callbacks.length; i++) {
Callback callback = callbacks[i];
if (callback instanceof NameCallback) {
((NameCallback) callback).setName(principal);
} else if (callback instanceof PasswordCallback) {
((PasswordCallback) callback).setPassword(
password.toCharArray());
}
}
}
private String principal;
private String password;
}
public static void setKerberosSystemProperties() {
System.setProperty(
"java.security.auth.login.config",
"./Kerberos.config");
2840ch08.qxd 7/13/04 12:44 PM Page 218
Download at Boykma.Com
Security and Single Sign-On
219
System.setProperty("java.security.krb5.realm", "JETSPEED");
System.setProperty("java.security.krb5.kdc", "jetspeed");
System.setProperty("sun.security.krb5.debug", "false");
}
public static Subject jaasLogin(
String context,
String principalName,
String password)
throws LoginException {
System.out.println("Acquiring context");
LoginContext lc =
new LoginContext(
context,
new KerberosCallbackHandler(principalName, password));
System.out.println("Logging in...");
try {
lc.login();
System.out.println("OK, Logged in.");
System.out.println(
"Retrieving and returning the Subject from the login context.");
return lc.getSubject();
} catch (Exception e) {
throw new LoginException("Login failed: " + e);
}
}
public static void main(String[] argv) {
String principalName = "dave";
String password = "MyPassword";
setKerberosSystemProperties();
System.out.println("Attempting jaasLogin");
try {
Subject subject =
jaasLogin("ClientAuthentication", principalName, password);
System.out.println("Logged in " + subject);
} catch (Exception e) {
System.out.println("JaasLogin Failed: " + e);
e.printStackTrace();
}
2840ch08.qxd 7/13/04 12:44 PM Page 219
Download at Boykma.Com
Chapter 8
220
System.out.println("OK, Done.");
}
}
In the main method, we provide a principal name (username) and password.
We then invoke
setKerberosSystemProperties()
to specify Kerberos configuration
values. These could equally well be provided on the command line or extracted
from a properties file, but for the sake of clarity we’re setting them explicitly in
the code. First, we specify the location of the configuration file to use:
System.setProperty(
"java.security.auth.login.config",
"./Kerberos.config");
Then we assign the name of the Kerberos realm that the user should be
logged in to:
System.setProperty("java.security.krb5.realm", "JETSPEED");
This specifies the network name of the Kerberos server that the user should
use to log in to (this does not have to have the same name as the realm, but it does
need to be a master or slave controller for the realm):
System.setProperty("java.security.krb5.kdc", "jetspeed");
Kerberos Terminology
Kerberos distinguishes between the realm and the controller that a user logs
in to. The controller is a physical machine, identified by a name—for example,
the Internet name example.com would be a suitable identifier for a controller.
Alternatively an IP address such as 192.168.0.1 could be used. The proper name
for such a controller is a Key Distribution Center (KDC). You can have any
number of KDCs on a network.
The realm is the logical group that the users log in to. For example, a small
company might easily use its domain name, so users would log in to the exam-
ple.com domain. This name does not have to have a DNS style name, however,
so “example” is an equally valid realm name.
In a larger organization, realms are likely to be organized in a way that reflects
the company’s hierarchy, so one set of users might log in to the ACCOUNTS
realm while another logs in to the HUMANRESOURCES realm. A user “bob”
who has an account in the HUMANRESOURCES realm is always represented as
bob@HUMANRESOURCES even if the physical machine he uses to carry out
a login is hr.example.com.
2840ch08.qxd 7/13/04 12:44 PM Page 220
Download at Boykma.Com