Scope:
Define the process and methods used to Authenticate and Authorize web
pages using JSP, PKI, LDAP and Sun web servers. Include 2
methods of Authentication with and without Authorization. Explain the
process used in the Iplanet server for authorization and handling of
X.509 certificates. Extrapolate into the Apache Server model a
similar development.
Methods:
- X.509 Certificate Authentication
- LDAP Authentication
- LDAP Authorization
Web
Server functions:
The Sun One (formerly Netscape/Iplanet) web servers have always
maintained support for X.509 certificate authentication. Apache
has provided similar support using Mod SSL. The heart of the
process is done using the web servers ability to protect a document or
portion of the web tree by requiring authentication. Each of the
server platforms can provide such a function and provide information
from the certificate of a successful authentication. The web
servers can validate the certificate, parse the certificate internals
for explicitly defined values which can be used to populate session
variables to be passed to other applications such as jsp back end
applications for additional processing. Once the user's presented
certificate is verified, values in the certificate can be used to
query a directory for additional information such as group membership
which can be used for authorization purposes.
- Sun One Requirements:
- Configure the server for JSP support as per MFG instructions
- Follow the MFG instructions for installing a certificate and
enabling SSL
- Configure the server for Client Authentication by turning on
this option.
- Modify certmap.conf to tell the server how to look up values in
LDAP (see example)
- Configure the FilterComps to filter the user presented
certificate values into ldap search values
- UTHSC-H example:
- certmap
UTH-1 CN=The University of Texas Health Science Center at Houston CA, OU
=Class 2 CA - OnSite
Individual Subscriber, OU=Terms of use at https://www.veris
ign.com/rpa (c)99,
OU=VeriSign Trust Network, O=The University of Texas System
UTH-1:DNComps
UTH-1:FilterComps
e
UTH-1:verifycert
on
UTHSC-Houston
JSP authentication:
Any
web page can be made to require authentication using this process. Web
server X.509 configuration, certificate authority installation and
support for Java Server Pages are required but once correctly
configured are not modified. JSPs must be stored in a directory
that has been configured to support them. Once a web page is
located in a JSP directory, a simple 3 line modification at the top of
the pages provides authentication and if required authorization.
Add the following lines to the top of the page you wish to protect.
<% request.setAttribute("authenticationMethod","certificate"); %>
<% request.setAttribute("authorizationGroup","oac_staff"); %>
<%@ include file="/jsp/auth/authentication.jsp" %>
The first line sets the type of authentication that
will be required to access the page. The second line defines an
LDAP group that whose membership is authorized to access the page (not
required). The third line sends the attribute set to the
authentication application that will provide that logic required for
access.
If the authentication method is certificate, the
application is directed to run check_certificate.jsp under a
certificate protected directory where the user is asked to present
his/her X.509 certificate for AuthN, the web server verifies the
certificate and if successful, returns the user's uid found in LDAP via
a search by the users email address from the certificate. The
user's information is queried from LDAP by the web server and stored in
a session variable by check_cert.jsp.
If the authentication method is login, the
application is directed to run login.jsp under an LDAP authentication
protected directory. The web server presents a standardized LDAP login
page where the user presents login credentials. The remote users
attribute is populated in the session variable and returned to
authentication.jsp for additional processing.
The JSPs return this information to
Authentication.jsp where it can be used to test if the user's DN value
is a unique member of the specified Authorization group if the second
line defines an LDAP authorization group.
Authentication.jsp
<%@ page
import="edu.tmc.uth.oac.ldap.*"%> //for ldap connections
<%@ page
import="edu.tmc.uth.oac.util.*"%> //may not be required
<%@ page
import="java.net.URLEncoder"%> //may not be
required
<%@ page
import="netscape.ldap.LDAPException"%> //error handling in ldap
<%
//
ldap_connection_monitor.jsp contains a class that implements
HttpSessionBindingListener
// This
class is used to make sure that the LDAP directory connection is closed
no matter
// how
the user navigates away from the page.
%>
<%@ include
file="/jsp/auth/ldap_connection_monitor.jsp" %>
<%
// Save the requested URL
( the calling page )
String setpage =
request.getScheme() + "://" + request.getServerName() +
request.getServletPath();
session.setAttribute("setpage", setpage);
if(request.getQueryString()!=null)
{
session.setAttribute("theRequestQueryString",request.getQueryString());
}
// Get LDAP directory
String authDirectory =
(String)request.getAttribute("authDirectory");
if(authDirectory==null)
authDirectory = (String)session.getAttribute("authDirectory");
if(authDirectory==null)
authDirectory = "ProdLDAP_SSL";
// Get Authentication
Method: from the calling jsp, sets the method to cert or ldap password
String
authenticationMethod =
(String)request.getAttribute("authenticationMethod");
if(authenticationMethod==null) authenticationMethod =
(String)session.getAttribute("authenticationMethod");
if(authenticationMethod==null) authenticationMethod = "password";
// Set Authentication
Page: if the authentication is cert, redirect to cert protected
directory else ldap protected directory
String authenticationPage;
String authError = null;
if(authenticationMethod.equals("certificate")) authenticationPage =
"/jspcert/auth/check_certificate.jsp";
else authenticationPage =
"/jsp/auth/login.jsp";
// Get Authorization
Method: If an authorization group is required, it is sent as a
parameter to this app from the calling jsp
String authorizationGroup
= (String)request.getAttribute("authorizationGroup");
String
authorizationGroupOwner =
(String)request.getAttribute("authorizationGroupOwner");
if(authorizationGroup!=null) request.setAttribute("authorizationGroup",
authorizationGroup);
if(authorizationGroupOwner!=null)
request.setAttribute("authorizationGroupOwner",
authorizationGroupOwner);
// Authenticate and
Authorize
if(request.getParameter("uid")!=null ||
session.getAttribute("certUid")!=null) { //CHANGED
String uid =
request.getParameter("uid");
if (uid==null)
{ uid = (String)session.getAttribute("certUid");} //ADDED
String
password = request.getParameter("userPassword");
if(password==null && session.getAttribute("certUid")==null) {
response.sendRedirect(authenticationPage);
return;
}
UTHLdap
uthLdap = null;
LDAPUser
ldapUser;
try {
// Bind to LDAP using credentials provided by user
if(authDirectory == "ProdLDAP") {
if(password != null) uthLdap =
new ProdLDAP(uid,password);
// or open anonymous LDAP
connection
else {
uid =
(String)session.getAttribute("certUid");
session.removeAttribute("certUid");
if (uid==null)
{
authError = URLEncoder.encode("Invalid Page
Navigation");
response.sendRedirect(authenticationPage + "?uid=" +
uid + "&error=" + authError);
return;
}
uthLdap = new
ProdLDAP(ProdLDAP.PROXY,uid);
}
}
else if(authDirectory == "ProdLDAP_SSL") {
if(password != null) uthLdap =
new ProdLDAP(uid,password,true);
else {
uid =
(String)session.getAttribute("certUid");
if (uid==null)
{ uid = (String)session.getAttribute("certUid");} //ADDED
session.removeAttribute("certUid");
if (uid==null)
{
authError = URLEncoder.encode("Invalid Page
Navigation");
response.sendRedirect(authenticationPage + "?uid=" +
uid + "&error=" + authError);
return;
}
uthLdap = new
ProdLDAP(ProdLDAP.PROXY_SSL,uid);
}
}
else if(authDirectory == "ProdDcLDAP") {
if(password != null) uthLdap =
new ProdDcLDAP(uid,password);
// or open anonymous LDAP
connection
else {
uid =
(String)session.getAttribute("certUid");
session.removeAttribute("certUid");
if (uid==null)
{
authError = URLEncoder.encode("Invalid Page
Navigation");
response.sendRedirect(authenticationPage + "?uid=" +
uid + "&error=" + authError);
return;
}
uthLdap = new
ProdDcLDAP(ProdDcLDAP.PROXY,uid);
}
}
else if(authDirectory == "VLDAP") {
if(password != null) uthLdap =
new VLDAP(uid,password);
// or open anonymous LDAP
connection
else {
uid =
(String)session.getAttribute("certUid");
session.removeAttribute("certUid");
if (uid==null)
{
authError = URLEncoder.encode("Invalid Page
Navigation");
response.sendRedirect(authenticationPage + "?uid=" +
uid + "&error=" + authError);
return;
}
uthLdap = new
ProdLDAP(ProdLDAP.PROXY,uid);
}
}
else if(authDirectory == "TestLDAP") {
if(password != null) uthLdap =
new TestLDAP(uid,password);
// or open anonymous LDAP
connection
else {
uid =
(String)session.getAttribute("certUid");
session.removeAttribute("certUid");
if (uid==null)
{
authError = URLEncoder.encode("Invalid Page
Navigation");
response.sendRedirect(authenticationPage + "?uid=" +
uid + "&error=" + authError);
return;
}
uthLdap = new
TestLDAP(TestLDAP.PROXY,uid);
}
}
else if(authDirectory == "TestDcLDAP") {
if(password != null) uthLdap =
new TestDcLDAP(uid,password);
// or open anonymous LDAP
connection
else {
uid =
(String)session.getAttribute("certUid");
session.removeAttribute("certUid");
if (uid==null)
{
authError = URLEncoder.encode("Invalid Page
Navigation");
response.sendRedirect(authenticationPage + "?uid=" +
uid + "&error=" + authError);
return;
}
uthLdap = new
TestDcLDAP(TestDcLDAP.PROXY,uid);
}
}
} catch
(LDAPException le) {
// If authentication fails return error message to
authentication page
authError = URLEncoder.encode("Invalid UID or
password");
response.sendRedirect(authenticationPage + "?uid=" +
uid + "&error=" + authError);
return;
} catch
(Exception e) {
// If authentication fails return error message to
authentication page
authError = URLEncoder.encode(e.toString());
response.sendRedirect(authenticationPage + "?uid=" +
uid + "&error=" + authError);
return;
}
// Check for
successful bind to LDAP or assume certificate authentication method is
being used
if
(uthLdap.isAuthenticated() ||
authenticationMethod.equals("certificate")) {
ldapUser = new LDAPUser(uid,uthLdap);
// Perform Group membership authorization if required
if(authorizationGroup != null) {
if(!ldapUser.isMemberOf(authorizationGroup)) {
uthLdap.close();
authError =
URLEncoder.encode("Group Authorization failure");
response.sendRedirect(authenticationPage + "?uid=" + uid +
"&error=" + authError);
return;
}
}
// Perform Group ownership authorization if required
if(authorizationGroupOwner != null) {
if(!ldapUser.isOwnerOf(authorizationGroupOwner)) {
uthLdap.close();
authError =
URLEncoder.encode("Owner Authorization failure");
response.sendRedirect(authenticationPage + "?uid=" + uid +
"&error=" + authError);
return;
}
}
session.setMaxInactiveInterval(300); // set default
session timeout - 5 minutes
// Set authorization method indicators
if(authorizationGroup==null)
session.removeAttribute("authorizationGroup");
else session.setAttribute("authorizationGroup",
authorizationGroup);
if(authorizationGroupOwner==null)
session.removeAttribute("authorizationGroupOwner");
else session.setAttribute("authorizationGroupOwner",
authorizationGroupOwner);
// Save user information in the session
session.setAttribute("uid",uid);
if (password != null)
session.setAttribute("userPassword",password);
if (ldapUser != null) {
session.setAttribute("thisUser",ldapUser);
session.setAttribute("lastName",ldapUser.sn);
session.setAttribute("firstName",ldapUser.givenname);
session.setAttribute("middleName",ldapUser.middlename);
session.setAttribute("cn",ldapUser.cn);
session.setAttribute("mail",ldapUser.mail);
}
session.setAttribute("remoteHost",request.getRemoteHost());
// Users IP Address
session.setAttribute("authenticationMethod",
authenticationMethod); // Method used to authenticate
session.setAttribute("authDirectory",
authDirectory); // Directory used to authenticate
// Save LDAP connection and create
HttpSessionBindingListener to make sure the connection gets closed
session.setAttribute("uthLdap",uthLdap);
LdapConnectionMonitor lcm = new
LdapConnectionMonitor();
lcm.setLogFileName("ldapconnection.log");
lcm.setSessionId(session.getId());
lcm.setLdapConnection(uthLdap);
session.setAttribute("lcm",lcm);
}
else {
uthLdap.close();
// If authentication fails return error message to
authentication page
authError = URLEncoder.encode("Invalid UID or
password");
response.sendRedirect(authenticationPage + "?uid=" +
uid + "&error=" + authError);
return;
}
}
// If the session uid
equals null the user has not been authenticated
if(session.getAttribute("uid")==null) {
response.sendRedirect(authenticationPage);
return;
}
// If the session
authentication method is null the user has not been authenticated
if(session.getAttribute("authenticationMethod")==null) {
response.sendRedirect(authenticationPage);
return;
}
// If the session
authentication method is different than the request authentication
method
// reauthentication is
required
if(!((String)session.getAttribute("authenticationMethod")).equals(authenticationMethod))
{
response.sendRedirect(authenticationPage);
return;
}
// If the session
authentication directory is different than the request authentication
directory
// reauthentication is
required
if(!((String)session.getAttribute("authDirectory")).equals(authDirectory))
{
response.sendRedirect(authenticationPage);
return;
}
// The request
authorization group must match the session authorization group
// If Group Membership
authorizaion is requested
if(authorizationGroup!=null)
if(session.getAttribute("authorizationGroup") == null) {
response.sendRedirect(authenticationPage);
return;
}
if(authorizationGroup!=null)
if(!((String)session.getAttribute("authorizationGroup")).equals(authorizationGroup))
{
response.sendRedirect(authenticationPage);
return;
}
// The request
authorization group must match the session authorization group
// If Group ownership
authorizaion is requested
if(authorizationGroupOwner!=null)
if(session.getAttribute("authorizationGroupOwner") == null) {
response.sendRedirect(authenticationPage);
return;
}
if(authorizationGroupOwner!=null)
if(!((String)session.getAttribute("authorizationGroupOwner")).equals(authorizationGroupOwner))
{
response.sendRedirect(authenticationPage);
return;
}
%>
Check_cert.jsp
<%
// Get users
uid from web server.
// This server
value is set once the user presents a valid certificate.
String uid =
request.getRemoteUser();
// Get error
message if one exists
String error =
(String) request.getParameter("error");
// Set return
page
String setpage
= (String) session.getAttribute("setpage");
// Set
'certUid' attribute to indicate that certificate authentication was
successful
session.setAttribute("certUid",uid);
String temp =
(String)session.getAttribute("theRequestQueryString");
if(temp!=null)
{
session.removeAttribute("theRequestQueryString");
}
// If
authentication is successful, return to calling page and set 'uid'
parameter
if(error ==
null) {
if(temp!=null) {
response.sendRedirect(setpage +
"?"+temp);
}else {
response.sendRedirect(setpage);
}
} else {
// Display error message below.
%>
<html><head><title>UT-Houston Directory Service
Login</title></head>
<body BGCOLOR="#ffffff"
LINK="#003366" ALINK="#669999" VLINK="#003366">
<center><H2>Authentication/Authorization Failure in Check
Certificate Page!</H2></center>
<center>
<table border=1>
<tr>
<td>
The following error occurred:
</td>
</tr>
<tr>
<td>
<%=error%>
</td>
</tr>
<tr>
<td>
<% if(setpage!=null) { %><a
href="<%=setpage%>"><%=setpage%></a><%}%>
</td>
</tr>
</table>
</center>
</body>
</html>
<%
}
%>
Office of Academic Computing
1/25/04