+

Search Tips   |   Advanced Search

Example: A com.ibm.wsspi.security.token.SingleSignonToken implementation

Use this file to see an example of a single sign-on implementation. The following sample code does not extend an abstract class, but implements the com.ibm.wsspi.security.token.SingleSignonToken interface directly. You can implement the interface directly, but it might cause you to write duplicate code. However, we might choose to implement the interface directly if considerable differences exist between how you handle the various token implementations.

For information on how to implement a custom single sign-on token, see Implement a custom single sign-on token for security attribute propagation.

package com.ibm.websphere.security.token;

import com.ibm.websphere.security.WSSecurityException;
import com.ibm.websphere.security.auth.WSLoginFailedException;
import com.ibm.wsspi.security.token.*;
import com.ibm.websphere.security.WebSphereRuntimePermission;
import java.io.ByteArrayOutputStream;
import java.io.ByteArrayInputStream;
import java.io.DataOutputStream;
import java.io.DataInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.io.InputStream;
import java.util.ArrayList;

public class CustomSingleSignonTokenImpl implements com.ibm.wsspi.security.
   token.SingleSignonToken
{
	private java.util.Hashtable hashtable = new java.util.Hashtable();
	private byte[] tokenBytes = null;
   // 2 hours in millis, by default
	private static long expire_period_in_millis = 2*60*60*1000; 
    
/**
 * Constructor used to create initial SingleSignonToken instance
 */

	public CustomSingleSignonTokenImpl (String principal)
	{
		// set the principal in the token
		addAttribute("principal", principal);
		// set the token version
		addAttribute("version", "1");
		// set the token expiration
		addAttribute("expiration", new Long(System.currentTimeMillis() + 
        expire_period_in_millis).toString());
	}

/**
 * Constructor used to deserialize the token bytes received during a propagation login.
 */
	public CustomSingleSignonTokenImpl (byte[] token_bytes)
	{
		try
		{
			// we should implement a decryption algorithm to decrypt the cookie bytes
			hashtable = (java.util.Hashtable) some_decryption_algorithm (token_bytes);
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}

/**
 * Validates the token including expiration, signature, and so on.
 * @return boolean
 */

	public boolean isValid ()
	{
		long expiration = getExpiration();

		// if we set the expiration to 0, it does not expire
		if (expiration != 0)
		{
			// return if this token is still valid
			long current_time = System.currentTimeMillis();
			
			boolean valid = ((current_time < expiration) ? true : false);
			System.out.println("isValid: returning " + valid);
			return valid;
		}
		else
		{
			System.out.println("isValid: returning true by default");
			return true;
		}
	}

/**
 * Gets the expiration as a long.
 * @return long
 */
	public long getExpiration()
	{
		// Get the expiration value from the hashtable
		String[] expiration = getAttributes("expiration");

		if (expiration != null && expiration[0] != null)
		{
			// expiration will always be the first element (should only be one)
			System.out.println("getExpiration: returning " + expiration[0]);
			return new Long(expiration[0]).longValue();
		}

		System.out.println("getExpiration: returning 0");
		return 0;
	}

/**
 * Returns if this token should be forwarded/propagated downstream.
 * @return boolean
 */
	public boolean isForwardable()
	{
		// We can choose whether your token gets propagated or not, in some cases 
     // we might want it to be local only.
		return true;  
	}

/**
 * Gets the principal that this Token belongs to. If this is an authorization token,
 * this principal string must match the authentication token principal string or the
 * message will be rejected.
 * @return String
 */
	public String getPrincipal()
	{
		// this could be any combination of attributes
		String[] principal = getAttributes("principal");

		if (principal != null && principal[0] != null)
		{
			return principal[0];
		}

		System.out.println("getExpiration: returning null");
		return null;
	}

/**
 * Returns a unique identifier of the token based upon information the provider
 * considers makes this a unique token.  This will be used for caching purposes
 * and may be used in combination with other token unique IDs that are part of
 * the same Subject.
 *
 * This method should return null if we want the access ID of the user to represent
 * uniqueness.  This is the typical scenario.
 *
 * @return String
 */
	public String getUniqueID()
	{
		// this could be any combination of attributes
		return getPrincipal();
	}

/**
 * Gets the bytes to be sent across the wire.  The information in the byte[]
 * needs to be enough to recreate the Token object at the target server.
 * @return byte[]
 */
	public byte[] getBytes ()
	{
		if (hashtable != null)
		{
			try
			{
				// do this if the object is set read-only during login commit,
				// since this guarantees no new data gets set.
				if (isReadOnly() && tokenBytes == null)
					tokenBytes = some_encryption_algorithm (hashtable);

				// we can deserialize the tokenBytes using a similiar decryption algorithm.
				return tokenBytes;
			}
			catch (Exception e)
			{
				e.printStackTrace();
				return null;
			}
		}

		System.out.println("getBytes: returning null");
		return null;
	}

/**
 * Gets the name of the token, used to identify the byte[] in the protocol message.
 * @return String
 */
	public String getName()
	{
		return "myCookieName";
	}

/**
 * Gets the version of the token as a short.  This is also used to identify the
 * byte[] in the protocol message.
 * @return short
 */
	public short getVersion()
	{
		String[] version = getAttributes("version");

		if (version != null && version[0] != null)
			return new Short(version[0]).shortValue();

		System.out.println("getVersion: returning default of 1");
		return 1;
    }

/**
 * When called, the token becomes irreversibly read-only.  The implementation
 * needs to ensure any setter methods check that this has been set.
 */
	public void setReadOnly()
	{
		addAttribute("readonly", "true");
	}

/**
 * Called internally to see if the token is readonly
 */
	private boolean isReadOnly()
	{
		String[] readonly = getAttributes("readonly");

		if (readonly != null && readonly[0] != null)
			return new Boolean(readonly[0]).booleanValue();

		System.out.println("isReadOnly: returning default of false");
		return false;
	}

/**
 * Gets the attribute value based on the named value.
 * @param String key
 * @return String[]
 */
	public String[] getAttributes(String key)
	{
		ArrayList array = (ArrayList) hashtable.get(key);

		if (array != null && array.size() > 0)
		{
			return (String[]) array.toArray(new String[0]);
		}

		return null;
	}

/**
 * Sets the attribute name/value pair.  Return the previous values set for key,
 * or null if not previously set.
 * @param String key
 * @param String value
 * @returns String[];
 */
	public String[] addAttribute(String key, String value)
	{
		// Get the current value for the key
		ArrayList array = (ArrayList) hashtable.get(key);
        
		if (!isReadOnly())
		{
			// copy the ArrayList to a String[] as it currently exists
			String[] old_array = null;
			if (array != null && array.size() > 0)
				old_array = (String[]) array.toArray(new String[0]);

			// allocate a new ArrayList if one was not found
			if (array == null)
				array = new ArrayList();

			// add the String to the current array list
			array.add(value);

			// add the current ArrayList to the Hashtable
			hashtable.put(key, array);

			// return the old array
			return old_array;
		}

		return (String[]) array.toArray(new String[0]);
	}

    
/**
 * Gets the List of all attribute names present in the token.
 * @return java.util.Enumeration
 */
	public java.util.Enumeration getAttributeNames()
	{
		return hashtable.keys();
	}

/**
 * Returns a deep copying of this token, if necessary.
 * @return Object
 */
	public Object clone()
	{
		com.ibm.websphere.security.token.CustomSingleSignonImpl deep_clone = 
			new com.ibm.websphere.security.token.CustomSingleSignonTokenImpl();

		java.util.Enumeration keys = getAttributeNames();

		while (keys.hasMoreElements()) 
		{
			String key = (String) keys.nextElement();

			String[] list = (String[]) getAttributes(key);
            
			for (int i=0; i<list.length; i++)
				deep_clone.addAttribute(key, list[i]);
		}
    
    		return deep_clone;
	}
}

  • Implement a custom single sign-on token for security attribute propagation