Sample Custom LoginModule

The following code defines a sample custom login module CelmExampleUsernamePasswordLoginModule class:

CelmExampleUsernamePasswordLoginModule Sample Class

package com.example.security.authentication.provider.celm;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.LoginException;
import org.opensaml.xml.util.XMLHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import com.tibco.asg.security.provider.celm.CelmAbstractLoginModule;
/**
* CelmExampleUsernamePasswordLoginModule is an example LoginModule
* to demonstrate how to extend CelmExampleUsernamePasswordLoginModule.
*
*/
public class CelmExampleUsernamePasswordLoginModule extends CelmAbstractLoginModule
{
private static Logger logger =
LoggerFactory.getLogger(CelmExampleUsernamePasswordLoginModule.class);
private String authorizedUsername = null;
private String authorizedPassword = null;
private String authorizedRole = null;
/**
* Perform initialize.
* <p>
* This method is called when login() in initialize is called.
*
* @param subject the Subject for authentication.
* @param callbackHandler the callback handler to provide authentication
* variables like username/password, etc.
* @param sharedState
* @param options a map contains the options from properties file.
*/
@Override
public void initialize(Subject subject, CallbackHandler callbackHandler,
final Map<String, ?> sharedState, final Map<String, ?> options)
{
super.initialize(subject, callbackHandler, sharedState, options);
authorizedUsername =
(String)options.get("com.tibco.asg.security.provider.celm.authorizedUsername");
authorizedPassword =
(String)options.get("com.tibco.asg.security.provider.celm.authorizedPassword");
authorizedRole =
(String)options.get("com.tibco.asg.security.provider.celm.authorizedRole");
}
/**
* Perform login.
* <p>
* This method is called when login() in LoginModule is called.
*
*/
@Override
public boolean doLogin() throws LoginException
{
if (getMessageElement() != null)
extractUsernamePassword(getMessageElement().getOwnerDocument());
return authenticateUsernamePassword(getUsername(), getPassword());
}
/**
* Perform commit.
* <p>
* This method is called when commit() in LoginModule is called.
*
*/
@Override
public boolean doCommit() throws LoginException
{
return true;
}
/**
* Perform cleanup.
* <p>
* This method is called when cleanup() in LoginModule is called.
*
*/
@Override
public void doCleanUp() throws LoginException
{
super.doCleanUp();
}
//
// The methods below are example to show:
// 1. How to username/password can be extracted from SOAP header.
// 2. AUthenticat the user.
//
private static final String WSSE_NS = "http://schemas.xmlsoap.org/ws/2002/04/secext";
private static final String USERNAME = "Username";
private static final String PASSWORD = "Password";
/**
* Extract username and password from the request.
*
* This example extract the username and password from the document.
* It is expecting the username and password is from a element with
* a specific namespace.
*
* This example does not handle and valid replay attack.
*
* @param document
* @return
* @throws LoginException
*/
private void extractUsernamePassword(Document document) throws LoginException
{
try
{
NodeList nl = null;
nl = document.getElementsByTagNameNS(WSSE_NS, USERNAME);
if (nl.getLength() != 0)
{
// save the username
setUsername(nl.item(0).getFirstChild().getNodeValue());
}
nl = document.getElementsByTagNameNS(WSSE_NS, PASSWORD);
if (nl.getLength() != 0)
{
// save the password
setPassword(nl.item(0).getFirstChild().getNodeValue());
}
}
catch (Exception e)
{
logger.error("Unable to extract username/password from request", e);
}
}
/**
* Authenticate the given username and password.
*
* This example validate the username/password against the username/password
* extracted from the properties file in the
* {@link #initialize(Subject, CallbackHandler, Map, Map)} method above.
*
* Note that name identifier should be set if username is authenticated.
* The name identifier is used for the Subject's NameIdentifier when
* building the SAML assertion.
*
* There may be other way to validate the username/password, for example,
* look up password for the user in database.
*
* @param username username to verify.
* @param password password to verify.
* @throws LoginException throw if authentication failed.
*/
private boolean authenticateUsernamePassword(String username, String password)
throws LoginException
{
if (authorizedUsername == null && authorizedPassword == null)
throw new LoginException("Invalid credentials");
if (username.equals(authorizedUsername) &&
password.equals(authorizedPassword))
{
this.setNameIdentifier(username);
this.setRoles(extractRoles(username));
return true;
}
throw new LoginException("Invalid credentials");
}
/**
* Extract roles for the given user.
*
* This example adds the role extracted from the properties file.
*
* There may be other way to get the roles for the authenticate user,
* for example, look up the roles for the user in database.
*
* @param username user whos roleas to be extracted
* @return set of roles for the specified user.
*/
private Set<String> extractRoles(String username)
{
HashSet<String> roleSet = new HashSet<String>();
if (authorizedRole != null)
roleSet.add(authorizedRole);
return roleSet;
}
}
Note:

To compile the CelmExampleUsernamePasswordLoginModule class, you must include asg-function.jar in the class path.