2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * Copyright (c) 2005 Sun Microsystems Inc. All Rights Reserved
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * The contents of this file are subject to the terms
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * of the Common Development and Distribution License
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * (the License). You may not use this file except in
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * compliance with the License.
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * You can obtain a copy of the License at
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * https://opensso.dev.java.net/public/CDDLv1.0.html or
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * See the License for the specific language governing
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * permission and limitations under the License.
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * When distributing Covered Code, include this CDDL
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * Header Notice in each file and include the License file
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * If applicable, add the following below the CDDL Header,
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * with the fields enclosed by brackets [] replaced by
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * your own identifying information:
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * "Portions Copyrighted [year] [name of copyright owner]"
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * $Id: Application.java,v 1.9 2009/07/23 18:54:17 qcheng Exp $
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington * Portions Copyrighted 2011-2015 ForgeRock AS.
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Fosterpackage com.sun.identity.authentication.modules.application;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Fosterimport javax.security.auth.callback.CallbackHandler;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Fosterimport javax.security.auth.callback.NameCallback;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Fosterimport javax.security.auth.callback.PasswordCallback;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Fosterimport com.sun.identity.authentication.spi.InvalidPasswordException;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Fosterimport com.sun.identity.authentication.spi.AMLoginModule;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Fosterimport com.sun.identity.authentication.spi.AuthLoginException;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Fosterimport com.sun.identity.authentication.service.AuthD;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Fosterimport com.sun.identity.authentication.util.ISAuthConstants;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Fosterimport com.sun.identity.idm.AMIdentityRepository;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Fosterimport com.sun.identity.shared.datastruct.CollectionHelper;
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunningtonimport com.sun.identity.shared.locale.AMResourceBundleCache;
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunningtonimport org.forgerock.openam.ldap.LDAPAuthUtils;
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunningtonimport org.forgerock.openam.ldap.LDAPUtilException;
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunningtonimport org.forgerock.openam.ldap.ModuleState;
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunningtonimport org.forgerock.opendj.ldap.ResultCode;
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunningtonimport org.forgerock.opendj.ldap.SearchScope;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * Application login module.<br>
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * Use <code>IDToken0</code> to specify application name and
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * <code>IDToken1</code> to specify secret.
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * (Old usage : <code>Login.Token0</code> to specify application name and
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * <code>Login.Token1</code> to specify secret.) For example:
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * "module=Application&IDToken0=UrlAccessAgent&IDToken1=secret"
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * "module=Application&IDToken0=<user id for Agent>&IDToken1=
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * <password for Agent user>"
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * Old usage:
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * "module=Application&Login.Token0=UrlAccessAgent&Login.Token1=secret"
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Fosterpublic class Application extends AMLoginModule {
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster private static final String amAuthApplication = "amAuthApplication";
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster private static Debug debug = Debug.getInstance(amAuthApplication);
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster debug.message("Application module getting secret");
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster secret = (String) AccessController.doPrivileged(
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster ldapSSL = Boolean.valueOf(SystemProperties.get(
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster Constants.AM_DIRECTORY_SSL_ENABLED, "false")).booleanValue();
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster public void init(Subject subject, Map sharedState, Map options) {
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster bundle = amCache.getResBundle(amAuthApplication, locale);
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster debug.message("ApplicationAuth resbundle locale="+locale);
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster debug.error("ApplicationAuthModule Init: " + e.getMessage());
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster debug.message("Init : NULL secret in AMConfig.properties");
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * Implementation of <code>AMLoginModule</code> abstract method.
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * Refer to <code>AMLoginModule</code> for method syntax.
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster public int process(Callback[] callbacks, int state)
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster // check if there is any error during initialize
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster throw new AuthLoginException(amAuthApplication, errorMsg, null);
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster HttpServletRequest req = getHttpServletRequest();
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster secretParam = req.getParameter("Login.Token1");
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster throw new AuthLoginException(amAuthApplication, "wrongSecret",
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster if (secretParam == null || secretParam.length() == 0) {
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster throw new AuthLoginException(amAuthApplication, "noPassword", null);
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster "App.validate, secret matched for user : " + userName);
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster if (userName == null || userName.length() == 0) {
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster // backward compatible with the gateway for portal
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster ISAuthConstants.APPLICATION_USER_PREFIX + "gateway";
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster ISAuthConstants.APPLICATION_USER_PREFIX + userName;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster String userDNString = ISAuthConstants.APPLICATION_USER_NAMING_ATTR +
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster ISAuthConstants.SPECIAL_USERS_CONTAINER + "," +
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster userDNString + " is not a valid special user entry");
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster "App validation failed, User not Valid: " + userName);
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster } else if (!doFallbackAuth(userName, secretParam)) {
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster debug.error("App validation failed, User not Valid: " + userName);
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster throw new AuthLoginException(amAuthApplication, "userInvalid",
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster private boolean doFallbackAuth(String userName, String userPassword)
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster boolean success = false;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster debug.message("doFallbackAuth : User = " + userName);
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster if (userName != null && (userName.length() != 0)) {
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster if (authenticateToDatastore(userName, userPassword)) {
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster debug.message("Application.doFallbackAuth: Authenticating "
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster + "to DataStore Auth Module.");
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington } else if (authenticateToLDAP(userName, userPassword) == ModuleState.SUCCESS) {
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster "Auth is successful,returning User = " + userTokenId);
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * Returns Principal for the authenticated user.
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * @return Principal for the authenticated user or null if
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * authentication did not succeed.
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster public java.security.Principal getPrincipal() {
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster userPrincipal = new ApplicationPrincipal(userTokenId);
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * Sends callbacks to get appname and/or secret
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * @return Map contains appname and/or secret, key "uid" corresponding
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * to appname, key "secret" corresponds to secret
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster CallbackHandler callbackHandler = getCallbackHandler();
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster throw new AuthLoginException(amAuthApplication,
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster callbacks[0] = new NameCallback(bundle.getString("appname"));
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster // map to hold return
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster // process return
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster char[] pass = ((PasswordCallback) cb).getPassword();
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster String username = ((NameCallback) cb).getName();
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster debug.error("sendCallback: " + e.getMessage());
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington private ModuleState authenticateToLDAP(String userName, String userPassword)
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster debug.message("In authenticateToLDAP with User : " + userName);
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington String baseDN = CollectionHelper.getServerMapAttr(currentConfig, ISAuthConstants.LDAP_BASEDN);
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington ldapUtil = new LDAPAuthUtils(Collections.singleton(AuthD.directoryHostName + ":" + AuthD.directoryPort),
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington AMResourceBundleCache.getInstance().getResBundle(amAuthApplication, getLoginLocale()), baseDN,
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington ldapUtil.authenticateUser(userName, userPassword);
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington if (ldapUtil.getState() == ModuleState.SUCCESS) {
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster debug.message("Invalid adminID or admin Password");
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster throw new AuthLoginException(amAuthApplication,
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster if (initLDAPAttributes(ISAuthConstants.LDAP_SERVICE_NAME)) {
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster ldapUtil.authenticateUser(userName, userPassword);
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster debug.message("Invalid userID or user Password");
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster throw new AuthLoginException(amAuthApplication,
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington if (ResultCode.NO_SUCH_OBJECT.equals(ex.getResultCode())) {
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington debug.message("The specified user does not exist.");
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington throw new AuthLoginException(amAuthApplication, "NoUser", null);
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington } else if (ResultCode.INVALID_CREDENTIALS.equals(ex.getResultCode())) {
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington String failureUserID = ldapUtil.getUserId();
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington throw new InvalidPasswordException(amAuthApplication, "InvalidUP", null, failureUserID, ex);
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington throw new AuthLoginException(amAuthApplication, "basicLDAPex", null);
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * Authenticates to the datastore using idRepo API
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * @param userName User Name
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * @param userPassword User Password
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * @return <code>true</code> if success. <code>false</code> if failure
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster * @throws <code> AuthLoginException </code>
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster private boolean authenticateToDatastore(String userName,
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster String userPassword) throws AuthLoginException {
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster boolean retval = false;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster NameCallback nameCallback = new NameCallback("NamePrompt");
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster PasswordCallback passwordCallback = new PasswordCallback(
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster "PasswordPrompt",false);
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster passwordCallback.setPassword(userPassword.toCharArray());
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster AMIdentityRepository idrepo = getAMIdentityRepository(
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster debug.message("Application.authenticateToDatastore: "
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster private boolean initLDAPAttributes(String serviceName)
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster currentConfig = getOrgServiceTemplate(getRequestOrg(),serviceName);
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster // All LDAP module Attribute Initialization done here ...
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster serverHost = CollectionHelper.getServerMapAttr(currentConfig,
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster return false;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster String baseDN = CollectionHelper.getServerMapAttr(currentConfig,
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster "Fatal error: baseDN for search has invalid value");
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster throw new AuthLoginException(amAuthApplication, "basednnull",
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster String bindDN = CollectionHelper.getMapAttr(currentConfig,
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster String bindPassword = CollectionHelper.getMapAttr(
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster currentConfig, ISAuthConstants.LDAP_BINDPWD, "");
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster String userNamingAttr = CollectionHelper.getMapAttr(
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster currentConfig, ISAuthConstants.LDAP_UNA, "uid");
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster (Set)currentConfig.get(ISAuthConstants.LDAP_USERSEARCH);
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster String searchFilter = CollectionHelper.getMapAttr(currentConfig,
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster boolean ssl = Boolean.valueOf(CollectionHelper.getMapAttr(
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington currentConfig, ISAuthConstants.LDAP_SSL, "false"));
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster String tmp = CollectionHelper.getMapAttr(currentConfig,
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington SearchScope searchScope = SearchScope.WHOLE_SUBTREE;// SUBTREE is the default
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster String returnUserDN = CollectionHelper.getMapAttr(currentConfig,
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster // set LDAP Parameters
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster // set the optional attributes here
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington ldapUtil = new LDAPAuthUtils(Collections.singleton(serverHost + ":" + serverPort),
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington AMResourceBundleCache.getInstance().getResBundle(amAuthApplication, getLoginLocale()), baseDN,
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster ldapUtil.setUserNamingAttribute(userNamingAttr);
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster ldapUtil.setUserSearchAttribute(userSearchAttrs);
bee2440354b4bc8796e1de0b6cbd60e1f68deba0Phill Cunnington ldapUtil.setAuthPassword(bindPassword.toCharArray());
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster return true;
2d0a88b18a041738cfe635b45bd1db56af469c91Allan Foster throw new AuthLoginException(amAuthApplication, "basicLDAPex",