001/*
002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003 *
004 * Copyright (c) 2005 Sun Microsystems Inc. All Rights Reserved
005 *
006 * The contents of this file are subject to the terms
007 * of the Common Development and Distribution License
008 * (the License). You may not use this file except in
009 * compliance with the License.
010 *
011 * You can obtain a copy of the License at
012 * https://opensso.dev.java.net/public/CDDLv1.0.html or
013 * opensso/legal/CDDLv1.0.txt
014 * See the License for the specific language governing
015 * permission and limitations under the License.
016 *
017 * When distributing Covered Code, include this CDDL
018 * Header Notice in each file and include the License file
019 * at opensso/legal/CDDLv1.0.txt.
020 * If applicable, add the following below the CDDL Header,
021 * with the fields enclosed by brackets [] replaced by
022 * your own identifying information:
023 * "Portions Copyrighted [year] [name of copyright owner]"
024 *
025 * $Id: AuthContextLocal.java,v 1.12 2009/05/21 21:57:34 qcheng Exp $
026 *
027 * Portions Copyright 2013-2015 ForgeRock AS.
028 */
029
030package com.sun.identity.authentication.server;
031
032import com.iplanet.sso.SSOToken;
033import com.sun.identity.authentication.AuthContext;
034import com.sun.identity.authentication.service.AMLoginContext;
035import com.sun.identity.authentication.service.LoginState;
036import com.sun.identity.authentication.service.LoginStatus;
037import com.sun.identity.authentication.spi.AuthLoginException;
038import com.sun.identity.authentication.spi.PagePropertiesCallback;
039import com.sun.identity.authentication.util.ISAuthConstants;
040import com.sun.identity.policy.PolicyException;
041import com.sun.identity.policy.util.PolicyDecisionUtils;
042import com.sun.identity.shared.encode.URLEncDec;
043import com.sun.identity.shared.debug.Debug;
044import com.sun.identity.shared.locale.Locale;
045import java.security.Principal;
046import java.util.ArrayList;
047import java.util.Collections;
048import java.util.HashMap;
049import java.util.List;
050import java.util.Map;
051import java.util.ResourceBundle;
052import java.util.Set;
053import javax.security.auth.Subject;
054import javax.security.auth.callback.Callback;
055import javax.servlet.http.HttpSession;
056
057/**
058 * The <code>AuthContextLocal</code> provides the implementation for
059 * authenticating users.
060 * <p>
061 * A typical caller instantiates this class and starts the login process.
062 * The caller then obtains an array of <code>Callback</code> objects,
063 * which contains the information required by the authentication plug-in
064 * module. The caller requests information from the user. On receiving
065 * the information from the user, the caller submits the same to this class.
066 * If more information is required, the above process continues until all
067 * the information required by the plug-ins/authentication modules, has
068 * been supplied. The caller then checks if the user has successfully
069 * been authenticated. If successfully authenticated, the caller can
070 * then get the <code>Subject</code> and <code>SSOToken</code> for the user;
071 * if not successfully authenticated, the caller obtains the AuthLoginException.
072 * <p>
073 * The implementation supports authenticating users either locally
074 * i.e., in process with all authentication modules configured or remotely
075 * to an authentication service/framework. (See documentation to configure
076 * in either of the modes).
077 * <p>
078 * The <code>getRequirements()</code> and <code>submitRequirements()</code> 
079 * are used to pass the user credentials for authentication by the plugin 
080 * modules,<code>getStatus()</code> returns the authentication status.
081 * <p>
082 * It should be serializable as a requirement to be stored in HttpSession.
083 *
084 * @supported.api
085 */
086public final class AuthContextLocal extends Object
087    implements java.io.Serializable {
088
089    /*
090     * Protected variables used locally
091     */
092
093    // Debug & I18N class
094    private static final String amAuthContextLocal = "amAuthContextLocal";
095    /**
096     * Hold the debug instance
097     */
098    protected static Debug authDebug = Debug.getInstance(amAuthContextLocal);
099    
100    /**
101     * Holds the locale-specific information 
102     */
103    protected static ResourceBundle bundle =
104        Locale.getInstallResourceBundle(amAuthContextLocal);
105
106    /**
107     * Holds organizationName
108     */
109    protected String organizationName;
110    /**
111     * Holds the set of module instance names
112     */
113    protected Set moduleInstanceNames;
114    /**
115     * Holds the index type
116     */
117    protected AuthContext.IndexType indexType;
118    /**
119     * Holds the index name
120     */
121    protected String indexName;
122    /**
123     * Holds the login status
124     */
125    protected AuthContext.Status loginStatus;
126    /**
127     * Holds the host name
128     */
129    protected String hostName;
130    /**
131     * Holds the http session
132     */
133    protected HttpSession httpSession;
134    /**
135     * Holds Single Sign on Token
136     */
137    protected SSOToken ssoToken;
138    /**
139     * AuthLoginException
140     */
141    protected volatile AuthLoginException loginException = null;
142    /**
143     * Holds call back information
144     */
145    protected Callback[] informationRequired = null;
146    /**
147     * AuthLoginContext
148     */
149    public AMLoginContext amlc = null;
150    /**
151     * Holds LoginStatus
152     */
153    public LoginStatus ls;
154    /**
155     * Holds subject
156     */
157    protected Subject subject;
158    /**
159     * character array for password
160     */
161    protected char[] password;
162    
163    private LoginState loginState = null;
164
165    private String orgDN = null;
166    
167    /**
168     * Holds information about submittion of requirements
169     */
170    private boolean inSubmitRequirements = false;
171
172    /**
173     * Creates <code>AuthContextLocal</code> instance is obtained for a given
174     * organization name, or sub organization name. <code>login</code> method is
175     * then used to start the authentication process.
176     *
177     * @param orgName name of the user's organization.
178     *
179     * @supported.api
180     */
181    public AuthContextLocal(String orgName) {
182        authDebug.message("AuthContextLocal() constructor called");
183        organizationName = orgName;
184
185        amlc = new AMLoginContext(this);
186        if (authDebug.messageEnabled()) {
187            authDebug.message("AMLoginContext object is... " + amlc);
188        }
189        reset();
190    }
191
192    /**
193     * Returns authentication module/s instances(or) plugin(s) configured
194     * for an organization, or sub-organization that was set during the
195     * <code>AuthContext</code> constructor.
196     *
197     * @return authentication module/s instances (or plugins).
198     * @throws UnsupportedOperationException if an error occurred.
199     *
200     * @supported.api
201     */
202    public Set getModuleInstanceNames() {
203        moduleInstanceNames = amlc.getModuleInstanceNames();
204
205        return (moduleInstanceNames);
206    }
207
208    /**
209     * Starts the login process for the given <code>AuthContextLocal</code>
210     * object.
211     *
212     * @exception AuthLoginException if an error occurred during login.
213     * @supported.api
214     */
215    public void login() throws AuthLoginException {
216        login(null);
217    }
218    
219    /**
220     * Starts the login process for the given <code>AuthContextLocal</code>s
221     * object for the given <code>Principal</code> and the user's password.
222     * This method should be called primarily
223     * when the authenticator knows there would no other
224     * credentials needed to complete the authentication process.
225     *
226     * @param principal <code>Principal</code> of the user to be authenticated.
227     * @param password password for the user.
228     * @throws AuthLoginException if an error occurred 
229     *            during login.
230     * @supported.api
231     */
232    public void login(Principal principal, char[] password) 
233        throws AuthLoginException {
234
235        // Make sure principal and password are not null
236        if (principal == null)
237            throw new AuthLoginException(amAuthContextLocal, 
238                "invalid-username", null);
239        if (password == null)
240            throw new AuthLoginException(amAuthContextLocal, 
241                "invalid-password", null);
242
243        // Copy the password
244        this.password = password;
245
246        login(null, null, principal, password, null);
247    }
248
249    /**
250     * Start the login process for the <code>AuthContextLocal</code> object
251     * identified by the index type and index name.
252     * The <code>IndexType</code> defines the possible kinds
253     * of "objects" or "resources" for which an authentication can
254     * be performed.  Currently supported index types are
255     * users, roles, services (or application), levels and mechanism.
256     *
257     * @param type authentication index type.
258     * @param indexName authentication index name.
259     * @throws AuthLoginException if an error occurred
260     *            during login.
261     * @supported.api
262     */
263    public void login(AuthContext.IndexType type, String indexName)
264        throws AuthLoginException {
265        if (authDebug.messageEnabled()) {
266            authDebug.message("AuthContextLocal::login() called " +
267            "with IndexType : " + type + " & Indexname : " + indexName);
268        }
269
270        login(type, indexName, null, null, null);
271    }
272
273    /**
274     * Starts the login process for the given <code>AuthContextLocal</code>
275     * object for the given <code>Subject</code>.
276     * Refer to JAAS for description on <code>Subject</code>.
277     *
278     * @param subject <code>Subject</code> of the user to be authenticated.
279     * @throws AuthLoginException if an error occurred
280     *            during login.
281     * @supported.api
282     */
283    public void login(Subject subject) throws AuthLoginException {
284        login(null, null, null, null, subject);
285    }
286
287    /**
288     * Starts the login process for the given <code>AuthContextLocal</code>
289     * object identified by the index type and index name.
290     * The <code>IndexType</code> defines the possible kinds
291     * of "objects" or "resources" for which an authentication can
292     * be performed.Currently supported index types are
293     * users, roles, services (or application), levels and mechanism.
294     * The locale specifies the user preferred locale setting.
295     *
296     * @param type authentication index type.
297     * @param indexName authentication index name.
298     * @param locale locale setting.
299     * @throws AuthLoginException if an error occurred during 
300     *            login process.
301     */
302    public void login(
303        AuthContext.IndexType type,
304        String indexName,
305        String locale
306    ) throws AuthLoginException {
307        if (authDebug.messageEnabled()) {
308            authDebug.message("AuthContextLocal::login() called " +
309            "with IndexType : " + type + " & Indexname : " + indexName +
310            " & locale : " + locale);
311        }
312        login(type, indexName, null, null, null, null, locale);
313    }
314    
315    /**
316     * Starts the login process for the given <code>AuthContextLocal</code>
317     * object identified by the index type and index name.
318     * The <code>IndexType</code> defines the possible kinds
319     * of "objects" or "resources" for which an authentication can
320     * be performed.Currently supported index types are
321     * users, roles, services (or application), levels and mechanism.
322     * The locale specifies the user preferred locale setting.
323     *
324     * @param type authentication index type.
325     * @param indexName authentication index name.
326     * @param envMap Environment Map, key is String, value is set of string.
327     *        this is applicable only when the type is 
328     *        <code>AuthContext.IndexType.RESOURCE</code>
329     * @param locale locale setting.
330     * @throws AuthLoginException if an error occurred during 
331     *            login process.
332     */
333    public void login(
334        AuthContext.IndexType type,
335        String indexName,
336        Map envMap,
337        String locale
338    ) throws AuthLoginException {
339        if (authDebug.messageEnabled()) {
340            authDebug.message("AuthContextLocal::login() called " +
341            "with IndexType : " + type + " & Indexname : " + indexName +
342            " & locale : " + locale +
343            " & envMap : " + envMap);
344        }
345        login(type, indexName, null, null, null, envMap, locale);
346    }
347
348    /**
349     * Performs the Login for the given AuthContext
350     * @param type authentication index type
351     * @param indexName authentication index name
352     * @param principal principal name of the user to be authenticated
353     * @param password password for the user
354     * @param subject authentication subject
355     * @throws AuthLoginException if error occurs during login
356     */
357    protected void login(AuthContext.IndexType type, String indexName, 
358        Principal principal, char[] password, Subject subject) throws AuthLoginException {
359        login(type, indexName, principal, password, subject, null, null);
360    }
361
362    /**
363     * Performs the Login for the given AuthContext
364     * @param type authentication index type
365     * @param indexName authentication index name
366     * @param principal principal name of the user to be authenticated
367     * @param password password for the user
368     * @param subject authentication subject
369     * @param envMap Environment map, this is applicable only when the type
370     *        is <code>AuthContext.IndexType.RESOURCE</code>
371     * @param locale locale setting
372     * @throws AuthLoginException if error occurs during login
373     */
374    protected void login(AuthContext.IndexType type, String indexName, 
375        Principal principal, char[] password, Subject subject, Map envMap, String locale)
376        throws AuthLoginException {
377        try {
378            /*if (!getStatus().equals(AuthContext.Status.NOT_STARTED)) {
379                if (authDebug.messageEnabled()) {
380                    authDebug.message("AuthContextLocal::login called " +
381                    "when the current login status is : " + getStatus());
382                }
383                throw new AuthLoginException(amAuthContextLocal, 
384                    "invalidMethod", new Object[]{getStatus()});
385            }*/
386
387            // switch the login status
388            loginStatus = AuthContext.Status.IN_PROGRESS;
389
390            String redirectUrl = null;
391            // specially processing for resouce/IP/Environement based auth
392            if ((type != null) && type.equals(AuthContext.IndexType.RESOURCE)) { 
393                // this is resouce/IP/Env based authentication
394                // call Policy Decision Util to find out the actual auth type 
395                // required by policy
396                List result = Collections.EMPTY_LIST;
397                try {
398                    result = PolicyDecisionUtils.doResourceIPEnvAuth(
399                            indexName, organizationName, envMap);
400                } catch (PolicyException pe) {
401                    // ignore, continue to default realm based authentication
402                    // may need to revisit this in the future
403                    authDebug.warning("AuthContextLocal.login() policy error " +
404                        "indexName=" + indexName, pe);
405                    type = null;
406                    indexName = null;
407                }
408                if (authDebug.messageEnabled()) {
409                    authDebug.message("AuthContextLocal.login: policy decision="
410                        + result);
411                }
412                if (result.size() == 2) {
413                    type = (AuthContext.IndexType) result.get(0);
414                    indexName = (String) result.get(1);
415                } else if (result.size() == 1) {
416                    // this is the redirection case (Policy Redirection Advice)
417                    redirectUrl = (String) result.get(0);
418                    // append goto parameter for federation case
419                    Set tmp = (Set) envMap.get(ISAuthConstants.GOTO_PARAM);
420                    if ((tmp != null) && !tmp.isEmpty()) {
421                        String gotoParam = (String) tmp.iterator().next();
422                        if ((gotoParam != null) && (gotoParam.length() != 0)) {
423                            if ((redirectUrl != null) && 
424                                (redirectUrl.indexOf("?") != -1)) {
425                                redirectUrl = redirectUrl + "&" + 
426                                    ISAuthConstants.GOTO_PARAM + "=" + 
427                                    URLEncDec.encode(gotoParam);
428                            } else {
429                                redirectUrl = redirectUrl + "?" + 
430                                    ISAuthConstants.GOTO_PARAM + "=" + 
431                                    URLEncDec.encode(gotoParam);
432                            }
433                        }
434                    }
435                    type = null;
436                    indexName = null;
437                } else {
438                    // no policy decision, use default realm login
439                    type = null;
440                    indexName = null;
441                }
442
443            }
444            HashMap loginParamsMap = new HashMap();
445
446            loginParamsMap.put(INDEX_TYPE, type);
447            loginParamsMap.put(INDEX_NAME, indexName);
448            loginParamsMap.put(PRINCIPAL, principal);
449            loginParamsMap.put(PASSWORD, password);
450            loginParamsMap.put(SUBJECT, subject);
451            loginParamsMap.put(LOCALE, locale);
452            if (redirectUrl != null) {
453                loginParamsMap.put(REDIRECT_URL, redirectUrl);
454            }
455
456            if (authDebug.messageEnabled()) {
457                authDebug.message(
458                    "loginParamsMap : " + loginParamsMap.toString());
459            }
460
461            authDebug.message("calling AMLoginContext::exceuteLogin : ");
462            amlc.executeLogin(loginParamsMap);
463            authDebug.message("after AMLoginContext::exceuteLogin : ");
464            if (amlc.getStatus() == LoginStatus.AUTH_SUCCESS) {
465                loginStatus = AuthContext.Status.SUCCESS;
466            } else if (amlc.getStatus() == LoginStatus.AUTH_FAILED) {
467                loginStatus = AuthContext.Status.FAILED;
468            }
469            if (authDebug.messageEnabled()) {
470                authDebug.message(
471                    "Status at the end of login() : " + loginStatus);
472            }
473        } catch (AuthLoginException e) {
474            if (authDebug.messageEnabled()) {
475                authDebug.message("Exception in ac.login : " + e.toString());
476            }
477            throw e;
478        }
479    }
480
481    /**
482     * Resets this instance of <code>AuthContextLocal</code>
483     * object, so that a new login process can be initiated.
484     * A new authentication process can started using any
485     * one of the <code>login</code> methods.
486     */
487    public void reset() {
488        authDebug.message("AuthContextLocal::reset() called");
489        loginStatus = AuthContext.Status.NOT_STARTED;
490        informationRequired = null;
491        loginException = null;
492    }
493
494    /**
495     * Returns the set of Principals the user has been authenticated as.
496     * This should be invoked only after successful authentication.
497     * If the authentication fails or the authentication is in process,
498     * this will return <code>null</code>.
499     *
500     * @return The set of Principals the user has been authenticated as.
501     * @supported.api
502     */
503    public Subject getSubject() {
504        if (!loginStatus.equals(AuthContext.Status.SUCCESS)) {
505            return (null);
506        }
507        if (subject == null) {
508            subject = amlc.getSubject();
509        }
510        return (subject);
511    }
512
513    /**
514     * Checks if the login process requires more information from the user to
515     * complete the authentication.
516     *
517     * @return <code>true</code> if more credentials are required
518     *         from the user.
519     * @supported.api
520     */
521    public boolean hasMoreRequirements() {
522        authDebug.message("AuthContextLocal::hasMoreRequirements()");
523
524        if ((amlc.getStatus() == LoginStatus.AUTH_SUCCESS) ||
525            (amlc.getStatus() == LoginStatus.AUTH_FAILED)
526        ) {
527            return false;
528        } else {
529            informationRequired = amlc.getRequiredInfo();
530            return (informationRequired != null);
531        }
532    }
533
534    /**
535     * Checks if the login process requires more information from the user to
536     * complete the authentication
537     * @param noFilter falg to indicate if there is a Filter
538     * @return <code>true</code> if more credentials are required
539     *         from the user.
540     */
541    public boolean hasMoreRequirements(boolean noFilter) {
542        authDebug.message("AuthContextLocal::hasMoreRequirements()");
543
544        if ((amlc.getStatus() == LoginStatus.AUTH_SUCCESS) ||
545            (amlc.getStatus() == LoginStatus.AUTH_FAILED)
546        ) {
547            return false;
548        } else {
549            informationRequired = amlc.getRequiredInfo();
550            return (getCallbacks(informationRequired, noFilter) != null);
551        }
552    }
553
554    /**
555     * Returns an array of <code>Callback</code> objects that
556     * must be populated by the user and returned back.
557     * These objects are requested by the authentication plug-ins,
558     * and these are usually displayed to the user. The user then provides
559     * the requested information for it to be authenticated.
560     *
561     * @return an array of <code>Callback</code> objects requesting credentials
562     *         from user.
563     * @supported.api
564     */
565    public Callback[] getRequirements() {
566        authDebug.message("AuthContextLocal::getRequirements()");
567
568        if ((amlc.getStatus() == LoginStatus.AUTH_SUCCESS) ||
569            (amlc.getStatus() == LoginStatus.AUTH_FAILED)
570        ) {
571            return null;
572        } else {
573            return (informationRequired);
574        }
575    }
576
577    /**
578     * Returns an array of <code>Callback</code> objects that
579     * must be populated by the user and returned back.
580     * These objects are requested by the authentication plug-ins,
581     * and these are usually displayed to the user. The user then provides
582     * the requested information for it to be authenticated.
583     *
584     * @param noFilter flag to indicate if there is a Filter
585     * @return an array of <code>Callback</code> objects requesting credentials
586     *         from user.
587     * @supported.api
588     */
589    public Callback[] getRequirements(boolean noFilter) {
590        authDebug.message("AuthContextLocal::getRequirements()");
591
592        if ((amlc.getStatus() == LoginStatus.AUTH_SUCCESS) ||
593            (amlc.getStatus() == LoginStatus.AUTH_FAILED)
594        ) {
595            return null;
596        } else {
597            return (getCallbacks(informationRequired, noFilter));
598        }
599    }
600
601    /**
602     * Submit the populated <code>Callback</code> objects
603     * to the authentication plug-in modules. Called after
604     * <code>getRequirements</code> method and obtaining
605     * user's response to these requests.
606     *
607     * @param info array of <code>Callback</code> objects
608     * @supported.api
609     */
610    public void submitRequirements(Callback[] info) {
611        authDebug.message("AuthContextLocal::submitRequirements()");
612        inSubmitRequirements = true;
613        try{
614           informationRequired = null;
615           amlc.submitRequiredInfo(info) ;
616           if (!amlc.isPureJAAS()) {
617                amlc.runLogin();
618           }
619           if (amlc.getStatus() == LoginStatus.AUTH_SUCCESS) {
620                loginStatus = AuthContext.Status.SUCCESS;
621           } else if (amlc.getStatus() == LoginStatus.AUTH_FAILED) {
622                loginStatus = AuthContext.Status.FAILED;
623           }
624           authDebug.message("AuthContextLocal::submitRequirements end");
625           if (authDebug.messageEnabled()) {
626                authDebug.message("Status at the end of submitRequirements() : "
627                                + loginStatus);
628           }
629         } finally {
630           inSubmitRequirements = false;
631         }
632    }
633
634    /**
635     * Logs out the user and also invalidates the <code>SSOToken</code>
636     * associated with this <code>AuthContextLocal</code>.
637     *
638     * @throws AuthLoginException if an error occurred during logout
639     * @supported.api
640     */
641    public void logout() throws AuthLoginException {
642        authDebug.message("AuthContextLocal::logout()");
643
644        try {
645            amlc.logout();
646        } catch (Exception e) {
647            if (authDebug.messageEnabled()) {
648                authDebug.message("Exception in AMLoginContext::logout() "
649                    + e.getMessage());
650            }
651            throw new AuthLoginException(amAuthContextLocal, "logoutError",
652                null, e);
653        }
654
655        authDebug.message("Called AMLoginContext::logout()");
656        loginStatus = AuthContext.Status.COMPLETED;
657    }
658
659    /**
660     * Returns login exception, if any, during
661     * the authentication process. Typically set when the login
662     * fails.
663     *
664     * @return login exception.
665     * @supported.api
666     */
667    public AuthLoginException getLoginException() {
668        authDebug.message("AuthContextLocal::getLoginException()");
669        return (loginException);
670    }
671
672    /**
673     * Sets the login exception that represents errors during the 
674     * authentication process.
675     *
676     * @param exception AuthLoginException to be set.
677     */
678    public void setLoginException(AuthLoginException exception) {
679        loginException = exception;
680    }
681
682    /**
683     * Returns the current status of the authentication process.
684     *
685     * @return the current status of the authentication process.
686     * @supported.api
687     */
688    public AuthContext.Status getStatus() {
689        authDebug.message("AuthContextLocal::getStatus()");
690        if (amlc.getStatus() == LoginStatus.AUTH_SUCCESS) {
691            loginStatus = AuthContext.Status.SUCCESS;
692        }
693        else if (amlc.getStatus() == LoginStatus.AUTH_FAILED) {
694            loginStatus = AuthContext.Status.FAILED;
695        }
696        else if (amlc.getStatus() == LoginStatus.AUTH_RESET) {
697            loginStatus =  AuthContext.Status.RESET;
698        }
699        else if (amlc.getStatus() == LoginStatus.AUTH_ORG_MISMATCH) {
700            loginStatus =  AuthContext.Status.ORG_MISMATCH;
701        }
702        else if (amlc.getStatus() == LoginStatus.AUTH_IN_PROGRESS) {
703            loginStatus =  AuthContext.Status.IN_PROGRESS;
704        }
705        else if (amlc.getStatus() == LoginStatus.AUTH_COMPLETED) {
706            loginStatus =  AuthContext.Status.COMPLETED;
707        }
708
709
710        if (authDebug.messageEnabled()) {
711            authDebug.message("AuthContextLocal:: Status : " + loginStatus);
712        }
713
714        return (loginStatus);
715    }
716
717    /**
718     * Sets the login status. Used internally and
719     * not visible outside this package.
720     * @param status login status
721     */
722    protected void setLoginStatus(AuthContext.Status status) {
723        authDebug.message("AuthContextLocal::setLoginStatus()");
724        loginStatus = status;
725    }
726
727    /**
728     * Returns the Single-Sign-On (SSO) Token for the authenticated
729     * user.Single-Sign-On token can be used as the authenticated token.
730     *
731     * @return single-sign-on token
732     * @supported.api
733     */
734    public SSOToken getSSOToken() {
735        ssoToken = amlc.getSSOToken();
736        return (ssoToken);
737    }
738
739    /**
740     * Returns the Successful Login URL for the authenticated user.
741     * 
742     * @return the Successful Login URL for the authenticated user.
743     */
744    public String getSuccessURL() {        
745        return amlc.getSuccessURL();        
746    }
747    
748    /**
749     * Returns the Failure Login URL for the authenticating user.
750     * 
751     * @return the Failure Login URL for the authenticating user.
752     */
753    public String getFailureURL() {        
754        return amlc.getFailureURL();        
755    }
756    
757    /**
758     * Returns the the organization name that was set during the
759     * <code>AuthContextLocal</code> constructor.
760     *
761     * @return Organization name.
762     *
763     * @supported.api
764     */
765    public String getOrganizationName() {
766        return (amlc.getOrganizationName());
767    }
768
769    /**
770     * Terminates an ongoing <code>login</code> call that has not yet completed.
771     *
772     * @throws AuthLoginException if an error occurred during abort.
773     *
774     * @supported.api
775     */
776    public void abort() throws AuthLoginException {
777        authDebug.message("AuthContextLocal::abort()");
778
779        try {
780            amlc.abort();
781        } catch (Exception e) {
782            if (authDebug.messageEnabled()) {
783                authDebug.message("Exception in AMLoginContext::abort() "
784                + e.getMessage());
785            }
786            throw new AuthLoginException(amAuthContextLocal, "abortError", 
787                null, e);
788        }
789
790        loginStatus = AuthContext.Status.COMPLETED;
791    }
792
793    /**
794     * Returns the error template.
795     *
796     * @return the error template.
797     */
798    public String getErrorTemplate() {
799        return amlc.getErrorTemplate();
800    }
801
802    /**
803     * Returns the error message.
804     *
805     * @return the error message.
806     */
807    public String getErrorMessage() {
808        return amlc.getErrorMessage();
809    }
810
811    /**
812     * Returns the error code.
813     *
814     * @return error code.
815     */
816    public String getErrorCode() {
817        return amlc.getErrorCode();
818    }
819
820    /**
821     * Returns the current 'authIdentifier' of the authentication process as
822     * String Session ID.
823     *
824     * @return <code>authIdentifier</code> of the authentication process
825     */
826    public String getAuthIdentifier() {        
827        return amlc.getAuthIdentifier();
828    }
829    
830    /**
831     * Returns the account lockout message. This can be either a dynamic
832     * message indicating the number of tries left or the the account
833     * deactivated message.
834     *
835     * @return account lockout message.
836     */
837    public String getLockoutMsg() {
838
839        String lockoutMsg = amlc.getLockoutMsg();
840
841        if (authDebug.messageEnabled()) {
842            authDebug.message("getLockoutMsg: lockoutMsg: " + lockoutMsg);
843        }
844
845        return lockoutMsg;
846    }
847
848    /**
849     * Checks the account is locked out
850     * @return <code>true</code> if the account is locked,
851     *         <code>false</code> otherwise
852     */
853    public boolean isLockedOut() {
854        boolean isLockedOut = amlc.isLockedOut();
855        if (authDebug.messageEnabled()) {
856            authDebug.message("isLockedOut : " + isLockedOut);
857        }
858
859        return isLockedOut;
860    }
861
862    /**
863     * Sets the client's host name , this method is used in case of remote 
864     * authentication,to set the client's hostname or IP address. 
865     * This could be used by the policy component to restrict access 
866     * to resources.
867     *
868     * @param hostname Host name.
869     */
870    public void setClientHostName(String hostname) {
871        hostName = hostname;
872    }
873
874    /**
875     * Returns the clients host name
876     * @return hostname
877     */
878    protected String getClientHostName() {
879        return (hostName);
880    }
881
882    public boolean submittedRequirements() {
883        return inSubmitRequirements;
884    }
885
886    /**
887     * Sets the <code>HttpSession</code> that will be used by
888     * the SSO component to store the session information. In the
889     * absence of <code>HttpSession</code> the information is stored
890     * in <code>HashMap</code> and will have issues with fail-over.
891     * With session fail-over turned on <code>HttpSession</code>
892     * would be provide persistance storage mechanism for SSO.
893     *
894     * @param session HttpSession
895     */
896    public void setHttpSession(HttpSession session) {
897        httpSession = session;
898    }
899
900    /**
901     * Returns the <code>HTTPSession</code> associated with the current
902     * authentication context
903     * @return httpSession
904     */
905    protected HttpSession getHttpSession() {
906        return (httpSession);
907    }
908
909    /**
910     * Returns the array of <code>Callback</code> requirements objects
911     * @param recdCallbacks callbacks requirements
912     * @param noFilter boolean to indicate if filter exists
913     * @return an array of <code>Callback</code> objects
914     */
915    protected static Callback[] getCallbacks(
916        Callback[] recdCallbacks,
917        boolean noFilter) {
918        if (recdCallbacks == null) {
919            return (null);
920        } else if (noFilter) {
921            return recdCallbacks;
922        } else {
923            Callback[] answer = new Callback[0];
924            ArrayList callbackList= new ArrayList(); 
925
926            for (int i = 0; i < recdCallbacks.length; i++) {
927                if (authDebug.messageEnabled()) {
928                    authDebug.message("In getCallbacks() callback : "
929                      + recdCallbacks[i]);
930                }
931                if (!(recdCallbacks[i] instanceof PagePropertiesCallback)) {
932                     callbackList.add(recdCallbacks[i]);
933                } 
934            }
935            return (Callback[]) callbackList.toArray(answer);
936        }
937    }
938
939    /**
940     * Sets the Login State
941     * @param state login state
942     */
943    public void setLoginState(LoginState state) {
944        loginState = state;
945    } 
946
947    /**
948     * Returns the login state
949     * @return loginState
950     */
951    public LoginState getLoginState() {
952        return loginState;
953    }
954
955    /**
956     * Sets the Organization DN
957     * @param orgDN Organization DN
958     */
959    public void setOrgDN(String orgDN) {
960        this.orgDN = orgDN;
961    }
962
963    /**
964     * Returns the Organization DN
965     * @return the Organization DN 
966     */
967    public String getOrgDN() {
968        return orgDN;
969    }
970
971    /**
972     * Holds LDAP URL
973     */
974    public final static String LDAP_AUTH_URL = "ldap://";
975
976    /**
977     * Holds principal name to be authenticated
978     */
979    public final static String PRINCIPAL = "principal";
980    /**
981     * Holds Password for the user
982     */
983    public final static String PASSWORD = "password";
984    /**
985     * authentication subject
986     */
987    public final static String SUBJECT = "subject";
988    /**
989     * authentication index type
990     */
991    public final static String INDEX_TYPE = "indexType";
992    
993    /**
994     * authentication index name
995     */
996    public final static String INDEX_NAME = "indexName";
997
998    /**
999     * locale setting
1000     */
1001    public final static String LOCALE = "locale";
1002    
1003    /**
1004     * Redirection URL
1005     */
1006    public static final String REDIRECT_URL = "redirectionURL";
1007}