/*
 * SecurIDAuthenticationProviderImpl.java
 * Copyright ©  1999 - 2011  EMC Corporation. All Rights Reserved.
 */
 
package com.rsa.authagent.SecurIDJAAS;

import java.util.HashMap;
import javax.security.auth.login.AppConfigurationEntry;
import javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag;
import weblogic.management.security.ProviderMBean;
import weblogic.security.provider.PrincipalValidatorImpl;
import weblogic.security.spi.AuthenticationProvider;
import weblogic.security.spi.IdentityAsserter;
import weblogic.security.spi.PrincipalValidator;
import weblogic.security.spi.SecurityServices;

import weblogic.security.principal.WLSGroupImpl;
import weblogic.security.principal.WLSUserImpl;
import com.rsa.authagent.authapi.AuthSessionFactory;

/**
 * The SecurIDJAAS sample authenticator's runtime implementation.
 *
 * It also provides its own login module implementation
 * (SecurIDJAASSampleLoginModuleImpl).
 *
 * The SecurIDJAAS sample authenticator is used in one of two modes:
 *
 * In authentation mode, it configures its login module
 * to validate that the user's password is correct
 * and that the user exists.
 *
 * In identity assertion mode, it configures its login
 * module to just validate that the user exists.
 *
 * In either mode, it has the login module put
 * principals for the user and the user's groups into
 * the subject.
 *
 * Rather than write its own principal and principal validator
 * implementations, it uses the standard weblogic ones:
 * - weblogic.security.principal.WLSGroupImpl
 * - weblogic.security.principal.WLSUserImpl
 * - weblogic.security.provider.PrincipalValidatorImpl
 *
 * It stores the user and group definitions in a properties
 * file.  The SecurIDJAASSampleAuthenticatorDatabase class handles
 * the properties file.  This class just delegates
 * to the database class.

 * Note: The SecurIDJAAS sample authenticator's mbean's ProviderClassName
 * attribute must be set the the name of this class.
 *
 * @author Copyright (c) 2002 by BEA Systems. All Rights Reserved.
 */
public final class SecurIDAuthenticationProviderImpl implements AuthenticationProvider
{
  private String                            description; // a description of this provider
  private AuthSessionFactory sessionFactory;    // manages the user and group definitions for this provider
  private LoginModuleControlFlag            controlFlag; // how this provider's login module should be used during the JAAS login

  /**
   * Initialize the SecurIDJAAS sample authenticator.
   *
   * It either creates or re-opens the file containing the
   * SecurIDJAAS sample authenticator's user and group definitions.
   *
   * @param mbean A ProviderMBean that holds the SecurIDJAAS sample authenticator's
   * configuration data.  This mbean must be an instance of the SecurIDJAAS sample
   * authenticator's mbean.
   *
   * @param services The SecurityServices gives access to the auditor
   * so that the provider can to post audit events.
   * The SecurIDJAAS sample authenticator doesn't use this parameter.
   *
   * @see SecurityProvider
   */
  public void initialize(ProviderMBean mbean, SecurityServices services)
  {
    System.out.println("SecurIDAuthenticationProviderImpl.initialize3");

    // Cast the mbean from a generic ProviderMBean to a SecurIDAuthenticatorMBean.
    SecurIDAuthenticatorMBean myMBean = (SecurIDAuthenticatorMBean)mbean;

    // Set the description to the SecurIDJAAS sample authenticator's mbean's description and version 
    description = myMBean.getDescription() + "\n" + myMBean.getVersion();

    try {
	// Instantiate the helper that manages this provider's user and group definitions

    	sessionFactory = AuthSessionFactory.getInstance();

    }catch (Exception e ){
    	throw new IllegalArgumentException("AuthSessionFactory.getInstance() failed" + e);
    }
    // Extract the JAAS control flag from the SecurIDJAAS sample authenticator's mbean.
    // This flag controls how the SecurIDJAAS sample authenticator's login module is used
    // by the JAAS login, both for authentication and for identity assertion.
    String flag = myMBean.getControlFlag();
    if (flag.equalsIgnoreCase("REQUIRED")) {
      controlFlag = LoginModuleControlFlag.REQUIRED;
    } else if (flag.equalsIgnoreCase("OPTIONAL")) {
      controlFlag = LoginModuleControlFlag.OPTIONAL;
    } else if (flag.equalsIgnoreCase("REQUISITE")) {
      controlFlag = LoginModuleControlFlag.REQUISITE;
    } else if (flag.equalsIgnoreCase("SUFFICIENT")) {
      controlFlag = LoginModuleControlFlag.SUFFICIENT;
    } else {
      throw new IllegalArgumentException("invalid flag value" + flag);
    }
     System.out.println("SecurIDAuthenticationProviderImpl.initialize done");
 }

  /**
   * Get the SecurIDJAAS sample authenticator's description.
   *
   * @return A String containing a brief description of the SecurIDJAAS sample authenticator.
   *
   * @see SecurityProvider
   */
  public String getDescription()
  {
    return description;
  }

  /**
   * Shutdown the SecurIDJAAS sample authenticator.
   *
   * A no-op.
   *
   * @see SecurityProvider
   */
  public void shutdown()
  {
    System.out.println("SecurIDAuthenticationProviderImpl.shutdown");
  }

  /**
   * Create a JAAS AppConfigurationEntry (which tells JAAS
   * how to create the login module and how to use it).
   * This helper method is used both for authentication mode
   * and identity assertion mode.
   *
   * @param options A HashMap containing the options to pass to the
   * SecurIDJAAS sample authenticator's login module.  This method adds the
   * "sessionFactory helper" object to the options.  This allows the
   * login module to access the users and groups.
   *
   * @return An AppConfigurationEntry that tells JAAS how to use the SecurIDJAAS sample
   * authenticator's login module.
   */
  private AppConfigurationEntry getConfiguration(HashMap options)
  {
    System.out.println("SecurIDAuthenticationProviderImpl.getConfiguration");
    // add the "sessionFactory helper" object to the options so that the
    // login module can access the user and group definitions
    options.put("sessionFactory", sessionFactory);

    // make sure to specify the SecurIDJAAS sample authenticator's login module
    // and to use the control flag from the SecurIDJAAS sample authenticator's mbean.
    return new
      AppConfigurationEntry(
        "com.rsa.authagent.SecurIDJAAS.SecurIDLoginModuleImpl",
        controlFlag,
        options
      );
  }

  /**
   * Create a JAAS AppConfigurationEntry (which tells JAAS
   * how to create the login module and how to use it) when
   * the SecurIDJAAS sample authenticator is used to authenticate (vs. to
   * complete identity assertion).
   *
   * @return An AppConfigurationEntry that tells JAAS how to use the SecurIDJAAS sample
   * authenticator's login module for authentication.
   */
  public AppConfigurationEntry getLoginModuleConfiguration()
  {
   System.out.println("SecurIDAuthenticationProviderImpl.getLoginModuleConfiguration()");
    // Don't pass in any special options.
    // By default, the SecurIDJAAS sample authenticator's login module
    // will authenticate (by checking that the passwords match).
    HashMap options = new HashMap();
    return getConfiguration(options);
  }

  /**
   * Create a JAAS AppConfigurationEntry (which tells JAAS
   * how to create the login module and how to use it) when
   * the SecurIDJAAS sample authenticator is used to complete identity
   * assertion (vs. to authenticate).
   *
   * @return An AppConfigurationEntry that tells JAAS how to use the SecurIDJAAS sample
   * authenticator's login module for identity assertion.
   */
  public AppConfigurationEntry getAssertionModuleConfiguration()
  {
    // Pass an option indicating that we're doing identity
    // assertion (vs. authentication) therefore the login module
    // should only check that the user exists (instead of checking
    // the password)
   System.out.println("SecurIDAuthenticationProviderImpl.getAssertionModuleConfiguration()");
    HashMap options = new HashMap();
    options.put("IdentityAssertion","false");
    return getConfiguration(options);
  }

  /**
   * Return the principal validator that can validate the
   * principals that the authenticator's login module
   * puts into the subject.
   *
   * Since the SecurIDJAAS sample authenticator uses the built in
   * WLSUserImpl and WLSGroupImpl principal classes, just
   * returns the built in PrincipalValidatorImpl that knows
   * how to handle these kinds of principals.
   *
   * @return A PrincipalValidator that can validate the
   * principals that the SecurIDJAAS sample authenticator's login module
   * puts in the subject.
   */
  public PrincipalValidator getPrincipalValidator() 
  {
   System.out.println("SecurIDAuthenticationProviderImpl.getPrincipalValidator() ");
    return new PrincipalValidatorImpl();
  }

  /**
   * Returns this providers identity asserter object.
   *
   * @return null since the SecurIDJAAS sample authenticator doesn't
   * support identity assertion (that is, mapping a token
   * to a user name).  Do not confuse this with using a
   * login module in identity assertion mode where the
   * login module shouldn't try to validate the user.
   */
  public IdentityAsserter getIdentityAsserter()
  {
   System.out.println("SecurIDAuthenticationProviderImpl.getIdentityAsserter()");
    return null;
  }
}
