Tuesday, February 3, 2009

Customized authn SPI module in OpenSSO

It is typical that customers write custom authentication SPI modules in customizing OpenSSO. Here is the set of steps that we need to do:

1. Login into OpenSSO as amadmin

2. Access the following URL

3. Choose create-svc option

4. Copy and paste the service xml file for your Custom Auth Module. Sample pasted below.

5. To register the custom auth module into the authentication core framework, choose register-auth-module option. Enter the complete module class name i.e including the package.

6. Copy the jar file that contains your SPI plugin classes into $WAR_DIR/WEB-INF/lib

7. If you have any property file that stores i18n keys for your module configuration label, copy it to $WAR_DIR/WEB-INF/classes

8. Copy xml file that contains callbacks for authn module to $WAR_DIR/opensso/config/auth/default folder. You need to copy it to the appropriate folder instead of default if locale is different than en_US.

9. Restart the server

10. Your Custom Auth Module should be listed under types of Authentication modules and once instance is created, it should be configurable based on what attributes you have listed in your service xml file.

11. You are ready to test your custom SPI auth plugin.

Sample SPI plugin
package com.iplanet.am.samples.authentication.spi.providers;

import com.iplanet.am.util.Debug;
import com.iplanet.am.util.Misc;
import com.sun.identity.authentication.service.AuthD;
import com.sun.identity.authentication.spi.AMLoginModule;
import com.sun.identity.authentication.spi.InvalidPasswordException;
import com.sun.identity.authentication.util.ISAuthConstants;
import java.security.Principal;
import java.util.Map;
import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.login.LoginException;
import javax.servlet.http.Cookie;

* @testcase for sample login module
public class LakshmanTest extends AMLoginModule {
final private static String DEBUG_NAME = "amAuthLakshmanTest";
final private static Debug debug = Debug.getInstance(DEBUG_NAME);
private String authLevel;
static String bundleName = AuthD.BUNDLE_NAME;
int failureNum = 0;
private String userTokenId;
private java.security.Principal userPrincipal = null;

public LakshmanTest() {
debug.error("inside LakshmanTest()");

public void init(Subject subject, Map sharedState, Map options) {
debug.error("inside LakshmanTest.init()");
debug.error("subject=" + subject);
debug.error("ss=" + sharedState);
debug.error("opts=" + options);

public int process(Callback[] callbacks, int state) throws LoginException {
debug.error("inside LakshmanTest.process()");

if (state == 1) {
debug.error("now in state one");

NameCallback nc = (NameCallback) callbacks[0];

if (!nc.getName().equals("tu1")) {
debug.error("name isn't tu1");
return 1;
} else {
debug.error("name is tu1");

return 2;
} else {
debug.error("now in state two");
PasswordCallback pc = (PasswordCallback) callbacks[0];
String password = new String(pc.getPassword());

if (!password.equalsIgnoreCase("password")) {
throw new InvalidPasswordException("invalid password");

userTokenId = "tu1";

if (getHttpServletRequest() != null) {
debug.error("added cookie nibble");
debug.error("Object returned by getHttpServletRequest = " + getHttpServletRequest());
} else {
debug.error("getHttpServletRequest is null");

if (getHttpServletResponse() != null) {
debug.error("added cookie wibble");
getHttpServletResponse().addCookie(new Cookie("wibble", "baa"));
debug.error("Object returned by getHttpServletResponse = " + getHttpServletResponse());
} else {
debug.error("getHttpServletResponse is null");

return ISAuthConstants.LOGIN_SUCCEED;

public java.security.Principal getPrincipal() {
if (userPrincipal != null) {
return userPrincipal;
} else if (userTokenId != null) {
userPrincipal = new LakshmanTestPrincipal(userTokenId);
return userPrincipal;
} else {
return null;

public void destroyModuleState() {
failureNum = 0;

package com.iplanet.am.samples.authentication.spi.providers;

import java.io.Serializable;
import java.security.Principal;

public class LakshmanTestPrincipal implements Principal, Serializable {

final private String name;

public LakshmanTestPrincipal(String name) {
this.name = name;

public String getName() {
return name;

public boolean equals(Object obj) {
if (obj == null)
return false;
if (this == obj)
return true;
if (!(obj instanceof LakshmanTestPrincipal))
return false;
LakshmanTestPrincipal authprincipal = (LakshmanTestPrincipal) obj;

return getName().equals(authprincipal.getName());

public int hashCode() {
return name.hashCode();


  1. where is the service xml file for Custom Auth Module???

  2. hi can you plz post the service.xml

  3. This comment has been removed by a blog administrator.