Liberty: Security public APIs

Security public APIs in Liberty provide a way of extending the security infrastructure.

Liberty contains public APIs that you can use to implement security functions. The security public APIs in Liberty are a subset of the WebSphere® Application Server traditional security public APIs. The main classes are WSSecurityHelper, WSSubject, and RegistryHelper. These classes contain a subset of the methods that are available in the WebSphere Application Server traditional versions. There is also a new class WebSecurityHelper.

The following sections describe those main classes. There are also other classes such as UserRegistry, WSCredential, and other exception classes.

All the security public APIs supported by Liberty are in the Java™API documentation. The Java API documentation for each Liberty API is available in a separate .zip file in one of the javadoc subdirectories of the ${wlp.install.dir}/dev directory.

WSSecurityHelper
This class contains only the methods isServerSecurityEnabled() and isGlobalSecurityEnabled(). These calls return true if appSecurity-2.0 among others, is enabled. Otherwise, the methods return false. These methods are carried over from the WebSphere Application Server traditional WSSecurityHelper class for compatibility.
Note:
  • There are no cells in Liberty, so there is no distinction in Liberty between global security and server security. Therefore, both methods return the same value.
  • The method revokeSSOCookies(javax.servlet.http.HttpServletRequest req,javax.servlet.http.HttpServletResponse res) is not supported in Liberty. Instead, you can use the Servlet 3.0 logout function.
  • The method getLTPACookieFromSSOToken() is renamed to a new public API class: WebSecurityHelper.
WSSubject
This class provides utility methods for querying and setting the security thread context. All methods from the WebSphere Application Server traditional WSSubject are supported in Liberty except getRootLoginException(). In Liberty, you can look for login exceptions in the server logs and traces using the following trace specification: com.ibm.websphere.security.*=all:com.ibm.ws.security.*=all
Note: Java 2 Security is supported but not enabled by default in Liberty. So by default, the Java 2 security checks in WSSubject are not performed.
RegistryHelper
This class provides access to the UserRegistry object and trusted realm information. In Liberty, it contains the following subset of the WebSphere Application Server traditional methods:
public static UserRegistry getUserRegistry(String realmName) throws WSSecurityException
public static List<String> getInboundTrustedRealms(String realmName) throws WSSecurityException
public static boolean isRealmInboundTrusted(String inboundRealm, String localRealm)
Note: This method involves dynamic information that could change as OSGI dynamic services change. The values that are retrieved can become stale. The UserRegistry references should never be cached.
WebSecurityHelper
This class contains the renamed getLTPACookieFromSSOToken() method, which was moved from WSSecurityHelper:
public static Cookie getSSOCookieFromSSOToken() throws Exception
PasswordUtil
This class provides encoding and decoding methods for protecting sensitive information. To enable this class as an API configure the passwordUtilities-1.0 feature in the server.xml file.
Note: This class also exists in WebSphere Application Server traditional. However, Liberty adds more capabilities that introduce extra methods.

Security public API code examples

The following examples demonstrate how to use security public APIs in Liberty to do a programmatic login and operate on the Subject.
Example 1: Create a Subject and use it for authorization
This example demonstrates how to use WSSecurityHelper, WSSubject, and UserRegistry to do a programmatic login to create a Java Subject, then perform an action and use that Subject for any authorization that is required.
Note: The following code uses WSSecurityHelper to check if security is enabled before doing further security processing. This check is used extensively because of the modular nature of Liberty: If security is not enabled, then the security run time is not loaded. WSSecurityHelper is always loaded, even if security is not enabled.
import java.rmi.RemoteException;
import java.security.PrivilegedAction;

import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;

import com.ibm.websphere.security.CustomRegistryException;
import com.ibm.websphere.security.UserRegistry;
import com.ibm.websphere.security.WSSecurityException;
import com.ibm.websphere.security.WSSecurityHelper;
import com.ibm.websphere.security.auth.WSSubject;
import com.ibm.websphere.security.auth.callback.WSCallbackHandlerImpl;
import com.ibm.wsspi.security.registry.RegistryHelper;
public class myServlet {

	...
	if (WSSecurityHelper.isServerSecurityEnabled()) {
		UserRegistry ur = null;
		try {
			ur = RegistryHelper.getUserRegistry(null);
		} catch (WSSecurityException e1) {
			// record some diagnostic info
			return;
		}
		String userid = "user1";
		String password = "user1password";
		try {
			if (ur.isValidUser(userid)) {
				// create a Subject, authenticating with
				// a userid and password
				CallbackHandler wscbh = new WSCallbackHandlerImpl(userid, password);
				LoginContext ctx;
				ctx = new LoginContext("WSLogin", wscbh);
				ctx.login();
				Subject subject = ctx.getSubject();
				// Perform an action using the Subject for
				// any required authorization
				WSSubject.doAs(subject, action);
			}
		} catch (CustomRegistryException e) {
			// record some diagnostic info
			return;
		} catch (RemoteException e) {
			// record some diagnostic info
			return;
		} catch (LoginException e) {
			// record some diagnostic info
			return;
		}
	}
	...
	private final PrivilegedAction action = new PrivilegedAction() {
		@Override
		public Object run() {
			// do something useful here
			return null;
		}
	};

}
Example 2: Create a Subject and make it the current Subject on the thread
The following example demonstrates how to use WSSecurityHelper and WSSubject to do a programmatic login to create a Java Subject. Make that Subject the current Subject on the thread, and then restore the original security thread context.
Note: The following code uses WSSecurityHelper to check if security is enabled before doing further security processing.
import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;

import com.ibm.websphere.security.WSSecurityException;
import com.ibm.websphere.security.WSSecurityHelper;
import com.ibm.websphere.security.auth.WSSubject;
import com.ibm.websphere.security.auth.callback.WSCallbackHandlerImpl;
...
if (WSSecurityHelper.isServerSecurityEnabled()) {
	CallbackHandler wscbh = new WSCallbackHandlerImpl("user1", "user1password");
	LoginContext ctx;
	try {
		// create a Subject, authenticating with
		// a userid and password
		ctx = new LoginContext("WSLogin", wscbh);
		ctx.login();
		Subject mySubject = ctx.getSubject();
		Subject oldSubject = null;
		try {
			// Save a ref to the current Subject on the thread
			oldSubject = WSSubject.getRunAsSubject();
			// Make mySubject the current Subject on the thread
			WSSubject.setRunAsSubject(mySubject);
			// Do something useful here. Any authorization
			// required will be performed using mySubject
		} catch (WSSecurityException e) {
			// record some diagnostic info
			return;
		} finally {
			// Put the original Subject back on the thread context
			if (oldSubject != null) {
				try {
					WSSubject.setRunAsSubject(oldSubject);
				} catch (WSSecurityException e) {
					// record some diagnostic info 
				}
			}
		}
	} catch (LoginException e) {
		// record some diagnostic info
		return;
	}
}
Example 3: Get information of the current Subject on the thread
The following example demonstrates how to use WSSecurityHelper, WSSubject, and WSCredential to get information about the current Subject on the thread.
Note: The following code uses WSSecurityHelper to check if security is enabled before doing further security processing.
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Set;

import javax.security.auth.Subject;
import javax.security.auth.login.CredentialExpiredException;

import com.ibm.websphere.security.WSSecurityException;
import com.ibm.websphere.security.WSSecurityHelper;
import com.ibm.websphere.security.auth.CredentialDestroyedException;
import com.ibm.websphere.security.auth.WSSubject;
import com.ibm.websphere.security.cred.WSCredential;
...
if (WSSecurityHelper.isServerSecurityEnabled()) {
	// Get the caller's subject
	Subject callerSubject;
	try {
		callerSubject = WSSubject.getCallerSubject();
	} catch (WSSecurityException e) {
		// record some diagnostic info
		return;
	}
	WSCredential wsCred = null;
	Set<WSCredential> wsCredentials =
		callerSubject.getPublicCredentials(WSCredential.class);
	Iterator<WSCredential> wsCredentialsIterator = wsCredentials.iterator();
	if (wsCredentialsIterator.hasNext()) {
		wsCred = wsCredentialsIterator.next();
		try {
			// Print out the groups
			ArrayList<String> groups = wsCred.getGroupIds();
			for (String group : groups) {
				System.out.println("Group name: " + group);
			}
		} catch (CredentialExpiredException e) {
			// record some diagnostic info
			return;
		} catch (CredentialDestroyedException e) {
			// record some diagnostic info
			return;
		}
	}
}
}