Refer to the following example of a custom login module:
package com.ibm.websphere.security;
import java.util.Map;
import java.lang.reflect.Array;
import javax.security.auth.Subject;
import javax.security.auth.callback.*;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;
import javax.security.auth.kerberos.*;
import com.ibm.websphere.security.auth.WSLoginFailedException;
import com.ibm.wsspi.security.token.AttributeNameConstants;
import com.ibm.wsspi.wssecurity.platform.token.KRBAuthnToken;
/**
*
* @author IBM Corporation
* @version 1.0
* @since 1.0
*
*/
public class sampleSpnegoMappingLoginModule implements LoginModule {
/*
*
* Constant that represents the name of this mapping module. Whenever this sample
* code is used to create a class with a different name, this value should be changed.
*
*/
private final static String MAPPING_MODULE_NAME = "com.ibm.websphere.security.sampleSpnegoMappingLoginModule";
private String mapUid = null;
/**
* Construct an uninitialized WSLoginModuleImpl object.
*/
public sampleSpnegoMappingLoginModule() {
debugOut("sampleSpnegoMappingLoginModule() entry");
debugOut("sampleSpnegoMappingLoginModule() exit");
}
/**
* Initialize this login module.
*
*
* This is called by the LoginContext after this login module is
* instantiated. The relevant information is passed from the LoginContext
* to this login module. If the login module does not understands any of the data
* stored in the sharedState and options parameters,
* they can be ignored.
*
*
* @param subject The subject to be authenticated.
* @param callbackHandler
* A CallbackHandler for communicating with the end user to gather login information
(e.g., username and password).
* @param sharedState
* The state shared with other configured login modules.
* @param options The options specified in the login configuration for this particular login module.
*/
public void initialize(Subject subject, CallbackHandler callbackHandler,
Map sharedState, Map options) {
debugOut("initialize(subject = \"" + subject.toString() +
"\", callbackHandler = \"" + callbackHandler.toString() +
"\", sharedState = \"" + sharedState.toString() +
"\", options = \"" + options.toString() + "\")");
this.subject = subject;
this.callbackHandler = callbackHandler;
this.sharedState = sharedState;
this.options = options;
debug = "true".equalsIgnoreCase((String)this.options.get("debug"));
debugOut("initialize() exit");
}
/**
*
* Method to authenticate a Subject (phase 1).
*
*
*
* This method authenticates a Subject. It uses CallbackHandler to gather
* the Subject information, like username and password for example, and verify these
* information. The result of the authentication is saved in the private state within
* this login module.
*
*
* @return true if the authentication succeeded, or false
* if this login module should be ignored.
* @exception LoginException
* If the authentication fails.
*/
public boolean login() throws LoginException
{
debugOut("sampleSpnegoMappingLoginModule.login() entry");
boolean succeeded = false;
KRBAuthnToken krbAuthnToken = null;;
java.util.Set krb5Principals= subject.getPrivateCredentials(KRBAuthnToken.class);
java.util.Iterator krb5PrincIter = krb5Principals.iterator();
while (krb5PrincIter.hasNext()) {
krbAuthnToken = (KRBAuthnToken)krb5PrincIter.next();
String kerbPrincipal = (String) krbAuthnToken.getTokenPrincipal() + "@" + krbAuthnToken.getTokenRealm();
debugOut("Kerberos principal name: "+ kerbPrincipal.toString());
if (kerbPrincipal!= null && kerbPrincipal.equals("utle@WSSEC.AUSTIN.IBM.COM")){
mapUid = "user1";
debugOut("mapUid: "+mapUid);
java.util.Hashtable customProperties = (java.util.Hashtable)
sharedState.get(AttributeNameConstants.WSCREDENTIAL_PROPERTIES_KEY);
if (customProperties == null) {
customProperties = new java.util.Hashtable();
}
succeeded = true;
customProperties.put(AttributeNameConstants.WSCREDENTIAL_USERID, mapUid);
Map<String,java.util.Hashtable>mySharedState=(Map<String,java.
util.Hashtable>)sharedState;
mySharedState.put(AttributeNameConstants.WSCREDENTIAL_PROPERTIES_KEY,
customProperties);
debugOut("Add a mapping user ID to Hashtable, mapping ID = "+mapUid);
debugOut("login() custom properties = " + customProperties);
}
}
succeeded = true;
debugOut("sampleSpnegoMappingLoginModule.login() exit");
return succeeded;
}
/**
*
* Method to commit the authentication result (phase 2).
*
*
*
* This method is called if the LoginContext's overall authentication
* succeeded (the revelant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL login module
* succeeded).
*
*
* @return true if the commit succeeded, or false
* if this login module should be ignored.
* @exception LoginException
* If the commit fails.
*/
public boolean commit() throws LoginException
{
debugOut("commit()");
debugOut("commit()");
return true;
}
/**
* Method to abort the authentication process (phase 2).
*
*
* This method is called if the LoginContext's overall authentication
* failed (the revelant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL login module
* did not succeed).
*
*
*
* If this login module's authentication attempt succeeded, then this method cleans
* up the previous state saved in phase 1.
*
*
* @return true if the abort succeeded, or false
* if this login module should be ignored.
* @exception LoginException
* If the abort fails.
*/
public boolean abort() throws LoginException {
debugOut("abort() entry");
debugOut("abort() exit");
return true;
}
/**
* Method which logs out a Subject.
*
* @return true if the logout succeeded, or false
* if this login module should be ignored.
* @exception LoginException
* If the logout fails.
*/
public boolean logout() throws LoginException
{
debugOut("logout() entry");
debugOut("logout() exit");
return true;
}
private void cleanup()
{
debugOut("cleanup() entry");
debugOut("cleanup() exit");
}
/*
*
* Private method to print trace information. This implementation uses System.out
* to print trace information to standard output, but a custom tracing system can
* be implemented here as well.
*
*/
private void debugOut(Object o)
{
System.out.println("Debug: " + MAPPING_MODULE_NAME);
if (o != null) {
if (o.getClass().isArray()) {
int length = Array.getLength(o);
for (int i = 0; i < length; i++) {
System.out.println("\t" + Array.get(o, i));
}
} else {
System.out.println("\t" + o);
}
}
}
private Subject subject;
private CallbackHandler callbackHandler;
private Map sharedState;
private Map options;
protected boolean debug = false;
}