Example usage for javax.security.auth.message AuthException AuthException

List of usage examples for javax.security.auth.message AuthException AuthException

Introduction

In this page you can find the example usage for javax.security.auth.message AuthException AuthException.

Prototype

public AuthException(String msg) 

Source Link

Document

Constructs an AuthException with the specified detail message.

Usage

From source file:net.java.jaspicoil.SimpleBasicServerAuthModule.java

/**
 * Authenticate a received service request.
 * <p/>// w  w  w . j a  v  a 2 s. c  om
 * This method is called to transform the mechanism-specific request message
 * acquired by calling getRequestMessage (on messageInfo) into the validated
 * application message to be returned to the message processing runtime. If
 * the received message is a (mechanism-specific) meta-message, the method
 * implementation must attempt to transform the meta-message into a
 * corresponding mechanism-specific response message, or to the validated
 * application request message. The runtime will bind a validated
 * application message into the the corresponding service invocation.
 * <p>
 * This method conveys the outcome of its message processing either by
 * returning an AuthStatus value or by throwing an AuthException.
 * <p/>
 * From a performance point of view this method will be called twice for
 * each resource with a security constraint on it. Resources with no
 * security constraint do not result in a call to this method.
 * 
 * @param messageInfo
 *            A contextual object that encapsulates the client request and
 *            server response objects, and that may be used to save state
 *            across a sequence of calls made to the methods of this
 *            interface for the purpose of completing a secure message
 *            exchange.
 * @param clientSubject
 *            A Subject that represents the source of the service request.
 *            It is used by the method implementation to store Principals
 *            and credentials validated in the request.
 * @param serviceSubject
 *            A Subject that represents the recipient of the service
 *            request, or null. It may be used by the method implementation
 *            as the source of Principals or credentials to be used to
 *            validate the request. If the Subject is not null, the method
 *            implementation may add additional Principals or credentials
 *            (pertaining to the recipient of the service request) to the
 *            Subject.
 * @return An AuthStatus object representing the completion status of the
 *         processing performed by the method. The AuthStatus values that
 *         may be returned by this method are defined as follows:
 *         <p/>
 *         <ul>
 *         <li>AuthStatus.SUCCESS when the application request message was
 *         successfully validated. The validated request message is
 *         available by calling getRequestMessage on messageInfo.
 *         <p/>
 *         <li>AuthStatus.SEND_SUCCESS to indicate that
 *         validation/processing of the request message successfully
 *         produced the secured application response message (in
 *         messageInfo). The secured response message is available by
 *         calling getResponseMessage on messageInfo.
 *         <p/>
 *         <li>AuthStatus.SEND_CONTINUE to indicate that message validation
 *         is incomplete, and that a preliminary response was returned as
 *         the response message in messageInfo.
 *         <p/>
 *         When this status value is returned to challenge an application
 *         request message, the challenged request must be saved by the
 *         authentication module such that it can be recovered when the
 *         module's validateRequest message is called to process the request
 *         returned for the challenge.
 *         <p/>
 *         <li>AuthStatus.SEND_FAILURE to indicate that message validation
 *         failed and that an appropriate failure response message is
 *         available by calling getResponseMessage on messageInfo.
 *         </ul>
 * @throws AuthException When the message processing failed without
 *         establishing a failure response message (in messageInfo).
 */
public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject)
        throws AuthException {
    // Get the servlet context
    final HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage();
    final HttpServletResponse response = (HttpServletResponse) messageInfo.getResponseMessage();
    final String auth = request.getHeader(AUTHORIZATION_HEADER);
    // Test prefix for HTTP BASIC Auth
    if (auth != null && StringUtils.startsWithIgnoreCase(auth, "basic ")) {
        // We might have a valid header, so try to decode it
        final String data = new String(Base64.decodeBase64(auth.substring(BASIC_PREFIX_LENGTH)), UTF_8);
        final int splitIndex = data.indexOf(':');
        if (splitIndex < 0) {
            return sendErrorAndAuthenticateRequest(request, response, "Wrong WWW-Authenticate header format");
        }
        final String username = data.substring(splitIndex);
        final char[] password = data.substring(splitIndex + 1, data.length()).toCharArray();

        // Prepare the JAAS callback to feed any LoginModule with user and password
        final NameCallback nameCallback = new NameCallback("username");
        nameCallback.setName(username);

        final PasswordCallback passwordCallback = new PasswordCallback(getRealm(request), false);
        passwordCallback.setPassword(password);

        final CallbackHandler delegatedHandler = new CallbackHandler() {
            public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
                for (int i = 0; i < callbacks.length; i++) {
                    final Callback c = callbacks[i];
                    if (c instanceof NameCallback) {
                        ((NameCallback) c).setName(username);
                    } else if (c instanceof PasswordCallback) {
                        ((PasswordCallback) c).setPassword(password);
                    } else {
                        throw new UnsupportedOperationException(
                                String.format("Callback type %s (%s) is not supported yet.", c.getClass(), c));
                    }
                }
            }
        };

        if (this.jaasContextName == null) {
            throw new UnsupportedOperationException(
                    "No delegate JAAS context found. As per JASPIC JAAS Bridge profile, this parameter is requiered.");
        }

        try {
            // Create a new JAAS context with the delegated data & try to login
            final LoginContext context = new LoginContext(this.jaasContextName, delegatedHandler);
            context.login();

            // Get the authenticated subject from the JAAS context
            Subject authenticatedSubject = context.getSubject();

            final PasswordValidationCallback passwordValidationCallback = new PasswordValidationCallback(
                    authenticatedSubject, username, password);

            // notify JASPIC containerr for the name, password and subject
            this.handler.handle(new Callback[] { passwordValidationCallback });

        } catch (final LoginException ex) {
            // If there was any issue during the JAAS login, fail the process
            final AuthException aex = new AuthException(
                    String.format("Fail to login user %s with the delegated JAAS context %s", username,
                            this.jaasContextName));
            aex.initCause(ex);
        } catch (final IOException e) {
            LOG.log(Level.WARNING, "Unable to call the handlers for name=" + nameCallback, e);
        } catch (final UnsupportedCallbackException e) {
            LOG.log(Level.WARNING, "Unable to call the handlers for name=" + nameCallback, e);
        }

    } else if (this.mandatory) {
        return sendErrorAndAuthenticateRequest(request, response,
                "AuthModule was mandatory but no valid credential was provided");
    } else {
        LOG.info("No authentication was provided bu Basic AuthModule is not mandatory so return SUCCESS.");
    }

    return AuthStatus.SUCCESS;
}

From source file:net.java.jaspicoil.MSPacSpnegoServerAuthModule.java

/**
 * Initialize this module with request and response message policies to
 * enforce, a CallbackHandler, and any module-specific configuration
 * properties. The request policy and the response policy must not both be
 * null./*ww  w .  j  av  a  2s . c  om*/
 * 
 * @param requestPolicy
 *            The request policy this module must enforce, or null.
 * @param responsePolicy
 *            The response policy this module must enforce, or null.
 * @param handler
 *            CallbackHandler used to request information.
 * @param options
 *            A Map of module-specific configuration properties.
 * @throws AuthException
 *             If module initialization fails, including for the case where
 *             the options argument contains elements that are not supported
 *             by the module.
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
public void initialize(MessagePolicy requestPolicy, MessagePolicy responsePolicy, CallbackHandler handler,
        Map options) throws AuthException {

    boolean useDelegatedLoginModule = false;
    // If no options or empty options was provided get away and display some
    // usage log
    // Please note that some AS such as JBoss 7 call this method twice.
    if (options == null || options.isEmpty()) {
        LOG.warning(String.format(
                "Options is either empty or null this time. Please make sure that "
                        + "at least the parameter %s and %s are set in the JASPIC provider configuration.",
                SERVICE_PRINCIPAL_NAME_KEY, KEYTAB_LOCATION_KEY));
        return;
    }

    this.requestPolicy = requestPolicy;
    this.responsePolicy = responsePolicy;

    // If none policy was provided, we assume this provider is mandatory.
    // This is unfortunately required as some container issue workaround
    this.mandatory = requestPolicy != null ? requestPolicy.isMandatory() : true;

    this.handler = handler;
    this.options = options;

    this.debug = options.containsKey(DEBUG_OPTIONS_KEY);

    // Set the debug level according to the logger config and the JASPIC
    // config
    this.debugLevel = LOG.isLoggable(Level.FINE) && !this.debug ? Level.FINE : Level.INFO;
    debug("Debug was set ({0},{1})", this.debug, this.debugLevel);

    this.jaasContextName = (String) options.get(JAAS_CONTEXT_KEY);
    debug("Jaas context name was set {0}", this.jaasContextName);

    if (this.jaasContextName == null && this.loginModuleName != null) {
        debug("There was no JAAS context parameter set on the JASPIC so using the default passed from the application server");
        this.jaasContextName = this.loginModuleName;
        useDelegatedLoginModule = true;
    }

    this.policyContextID = (String) options.get(POLICY_CONTEXT_OPTIONS_KEY);
    debug("Policy context set to {0}", this.policyContextID);

    this.servicePrincipal = (String) options.get(SERVICE_PRINCIPAL_NAME_KEY);
    debug("Principal set to {0}", this.servicePrincipal);

    // If there was no delegated LoginModule found we must set a SPN
    if (!useDelegatedLoginModule && this.servicePrincipal == null) {
        LOG.severe("A valid SPN must be configured for JASPIC connector with the property "
                + SERVICE_PRINCIPAL_NAME_KEY);
        return;
    }

    // Get the secure groups
    final String groupList = (String) options.get(SECURE_GROUP_SIDS_KEY);
    if (groupList != null && !"".equals(groupList.trim())) {
        this.secureGroups = Collections
                .unmodifiableSet(new HashSet<String>(Arrays.asList(groupList.trim().split(","))));
        debug("Secure groups set as: {0}", this.secureGroups);
    }

    // Get the mandatory groups
    final String mandatoryGroupList = (String) options.get(MANDATORY_GROUPS_KEY);
    if (mandatoryGroupList != null && !"".equals(mandatoryGroupList.trim())) {
        this.mandatoryGroups = Collections
                .unmodifiableSet(new HashSet<String>(Arrays.asList(mandatoryGroupList.trim().split(","))));
        debug("Mandatory groups set as: {0}", this.mandatoryGroups);
    }

    final String administratorGroupList = (String) options.get(ADMINISTRATOR_GROUPS_KEY);
    if (administratorGroupList != null && !"".equals(administratorGroupList.trim())) {
        this.administratorGroups = Collections
                .unmodifiableSet(new HashSet<String>(Arrays.asList(administratorGroupList.trim().split(","))));
        debug("Administrator groups set as: {0}", this.mandatoryGroups);
    }

    final String administratorOnlyUriList = (String) options.get(ADMINISTRATOR_ONLY_URIS_KEY);
    if (administratorOnlyUriList != null && !"".equals(administratorOnlyUriList.trim())) {
        this.administratorOnlyUris = Collections.unmodifiableSet(
                new HashSet<String>(Arrays.asList(administratorOnlyUriList.trim().split(","))));
        debug("Administrator restricted URIs set as: {0}", this.mandatoryGroups);
    }

    final String sessionAttributeList = (String) options.get(SESSION_ATTRIBUTES_KEY);
    if (sessionAttributeList != null && !"".equals(sessionAttributeList.trim())) {
        final String[] pairs = sessionAttributeList.trim().split(",");
        final Map<String, String> attributes = new HashMap<String, String>();
        for (final String pair : pairs) {
            final String[] vals = pair.split("=");
            attributes.put(vals[0], vals[1]);
        }
        this.sessionAttributes = Collections.unmodifiableMap(attributes);
        debug("Session attributes was set to {0}", this.sessionAttributes);
    }

    final String keyTabLocationString = (String) options.get(KEYTAB_LOCATION_KEY);
    if (!useDelegatedLoginModule && keyTabLocationString == null) {
        LOG.severe("A valid key tab location must be configured for JASPIC connector with the property "
                + KEYTAB_LOCATION_KEY);
        return;
    }

    if (keyTabLocationString != null) {
        // Try to reference the indicated keytab
        try {
            this.keyTabLocation = new URL(keyTabLocationString);
            debug("Keytab location was set to {0}", this.keyTabLocation);
        } catch (final MalformedURLException e) {
            LOG.log(Level.WARNING, "Unable to build " + KEYTAB_LOCATION_KEY + " from the parameter value "
                    + options.get(KEYTAB_LOCATION_KEY), e);
        }
    }

    URL groupMappingSource = null;
    try {
        final String groupParam = (String) options.get(GROUP_MAPPING_KEY);
        if (groupParam != null && !"".equals(groupParam.trim())) {
            groupMappingSource = new URL(groupParam);
        }

    } catch (final MalformedURLException e) {
        LOG.log(Level.WARNING, "Unable to build " + GROUP_MAPPING_KEY + " from the parameter value "
                + options.get(GROUP_MAPPING_KEY), e);
    }
    if (groupMappingSource != null) {
        final Properties groupMapping = new Properties();

        try {
            InputStream groupMappingInputstream = null;
            try {
                groupMappingInputstream = groupMappingSource.openStream();
                groupMapping.load(groupMappingInputstream);
            } finally {
                if (groupMappingInputstream != null) {
                    groupMappingInputstream.close();
                }
            }
            this.groupMapping = groupMapping;
            debug("Group mapping was set to {0}", this.groupMapping);
        } catch (final IOException ioex) {
            LOG.log(Level.WARNING, "Unable to load " + GROUP_MAPPING_KEY + " from the indicated ressource "
                    + options.get(GROUP_MAPPING_KEY), ioex);
        }
    }

    try {
        // Load the serviceSubject from a LoginModule, this is required to
        // get the Kerberos Key
        this.serviceSubject = initializeKerberosServerContext(this.jaasContextName, this.servicePrincipal,
                this.keyTabLocation, this.debug);
        debug("Service subject was set to {0}", this.serviceSubject);
    } catch (final LoginException e) {
        final AuthException aex = new AuthException("Kerberos service context initialization failed");
        aex.initCause(e);
        throw aex;
    }

    this.smartcardSecuredUsersOnly = Boolean.parseBoolean((String) options.get(SMARTCARD_SECURED_USERS_ONLY));
    debug("Only accept smartcard secured users ? {0}", this.smartcardSecuredUsersOnly);

    this.delegatedSecuredUsersOnly = Boolean.parseBoolean((String) options.get(DELEGATED_SECURED_USERS_ONLY));
    debug("Only accept delegated (KCD) users ? {0}", this.delegatedSecuredUsersOnly);

    this.userHeader = (String) options.get(USER_HEADER_KEY);
    debug("User header set to {0}", this.userHeader);

    // TODO Add some fetchExtraGroupsScript handling that will use
    // javax.script to execute
    // an idea is to use the first line as //#!!mime/type the mimetype will
    // be extracted out to known which engine to call
}

From source file:org.forgerock.openam.jaspi.modules.session.LocalSSOTokenSessionModule.java

/**
 * Validates the request by checking the validity of the SSOToken ID from the AM cookie.
 * <p>//w  w  w.ja v a 2s  .c o m
 * If the SSOToken ID is a restricted token then the request must also contain a url parameter "requester" which
 * must contain the application SSOToken ID of the application the restricted token was issued for.
 *
 * @param messageInfo {@inheritDoc}
 * @param clientSubject {@inheritDoc}
 * @param serviceSubject {@inheritDoc}
 * @return {@inheritDoc}
 * @throws AuthException If there is a problem validating the request.
 */
@Override
public AuthStatus validateRequest(final MessageInfo messageInfo, final Subject clientSubject,
        Subject serviceSubject) throws AuthException {
    if (!isInitialised()) {
        initDependencies();
    }

    final HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage();

    String requester = request.getParameter(REQUESTER_URL_PARAM);
    if (requester != null) {
        try {
            SSOToken requesterToken = getFactory().getTokenFromId(requester);
            if (getFactory().isTokenValid(requesterToken)) {
                Object o = RestrictedTokenContext.doUsing(requesterToken, new RestrictedTokenAction() {
                    public Object run() throws Exception {
                        return validate(request, messageInfo, clientSubject);
                    }
                });
                return (AuthStatus) o;
            }
        } catch (Exception ex) {
            throw new AuthException("An error occurred whilst trying to use restricted token.");
        }
    }
    return validate(request, messageInfo, clientSubject);
}

From source file:org.forgerock.openam.jaspi.modules.session.LocalSSOTokenSessionModule.java

/**
 * Validates the request by attempting to retrieve the SSOToken ID from the cookies on the request.
 * If the SSOToken ID cookie is not present then the method returns AuthStatus.SEND_FAILURE, otherwise if it is
 * present it is then used to retrieve the actual SSOToken from the SSOTokenManager, if valid then
 * AuthStatus.SUCCESS will be returned, otherwise AuthStatus.SEND_FAILURE will be returned.
 *
 * @param request The HttpServletRequest.
 * @param messageInfo A contextual object that encapsulates the client request and server response objects, and
 *                    that may be used to save state across a sequence of calls made to the methods of this
 *                    interface for the purpose of completing a secure message exchange.
 * @param clientSubject A Subject that represents the source of the service request. It is used by the method
 *                      implementation to store Principals and credentials validated in the request.
 * @return AuthStatus.SUCCESS if the SSOToken ID is valid, otherwise AuthStatus.SEND_FAILURE.
 * @throws AuthException If there is a problem validating the request.
 *///  ww w.  ja  v a2s . com
private AuthStatus validate(HttpServletRequest request, MessageInfo messageInfo, Subject clientSubject)
        throws AuthException {

    String tokenId = getRequestUtils().getTokenId(request);
    if (StringUtils.isEmpty(tokenId)) {
        tokenId = request.getHeader(getCookieHeaderName());
    }
    if (!StringUtils.isEmpty(tokenId)) {
        SSOToken ssoToken = getFactory().getTokenFromId(tokenId);

        if (ssoToken != null) {

            int authLevel;
            try {
                authLevel = ssoToken.getAuthLevel();
                String name = ssoToken.getPrincipal().getName();
                handler.handle(new Callback[] { new CallerPrincipalCallback(clientSubject, name) });

                clientSubject.getPrincipals().add(ssoToken.getPrincipal());
            } catch (SSOException e) {
                throw new AuthException(e.getMessage());
            } catch (UnsupportedCallbackException e) {
                throw new AuthException(e.getMessage());
            } catch (IOException e) {
                throw new AuthException(e.getMessage());
            }

            Map<String, Object> context = (Map<String, Object>) messageInfo.getMap()
                    .get("org.forgerock.authentication.context");
            context.put("authLevel", authLevel);
            context.put("tokenId", ssoToken.getTokenID().toString());
            //TODO add more properties to context map

            return AuthStatus.SUCCESS;
        }
    }
    return AuthStatus.SEND_FAILURE;
}

From source file:org.forgerock.openidm.jaspi.modules.IDMJaspiModuleWrapper.java

/**
 * Constructs a new instance of the IDMJaspiModuleWrapper.
 *//*  w ww .jav a2 s.com*/
public IDMJaspiModuleWrapper() throws AuthException {
    this.authnFilterHelper = OSGiAuthnFilterBuilder.getInstance();
    if (authnFilterHelper == null) {
        throw new AuthException("OSGiAuthnFilterHelper is not ready.");
    }
    this.authModuleConstructor = new AuthModuleConstructor();
    this.roleCalculatorFactory = new RoleCalculatorFactory();
    this.augmentationScriptExecutor = new AugmentationScriptExecutor(authnFilterHelper);
}

From source file:org.forgerock.openidm.jaspi.modules.PassthroughAuthenticator.java

/**
 * Performs the ICF Passthrough authentication.
 *
 * @param authData The AuthData object./*from  ww w  .  j  av a 2s  . c om*/
 * @param password The user's password.
 * @return The AuthData object the was passed in, with information set on it from the results of the authentication
 * request.
 * @throws AuthException If pass-through authentication fails.
 */
public boolean authenticate(AuthData authData, String password) throws AuthException {

    String userRolesProperty = propertyMapping.get("userRoles").asString();

    if (!StringUtils.isEmpty(passThroughAuth) && !"anonymous".equals(authData.getUsername())) {
        JsonResource router = getJsonResource();
        if (null != router) {
            JsonResourceAccessor accessor = new JsonResourceAccessor(router,
                    JsonResourceContext.getContext(JsonResourceContext.newRootContext(), "resource"));

            JsonValue params = new JsonValue(new HashMap<String, Object>());
            params.put(ServerConstants.ACTION_NAME, "authenticate");
            params.put("username", authData.getUsername());
            params.put("password", password);
            try {
                JsonValue result = accessor.action(passThroughAuth, params, null);
                boolean authenticated = result.isDefined(ServerConstants.OBJECT_PROPERTY_ID);
                if (authenticated) {
                    authData.setResource(passThroughAuth);
                    authData.setUserId(result.get(ServerConstants.OBJECT_PROPERTY_ID).required().asString());

                    result = accessor.read(passThroughAuth + "/" + authData.getUserId());

                    if (userRolesProperty != null && result.isDefined(userRolesProperty)) {
                        authData.setRoles((List) result.get(userRolesProperty).getObject());
                    } else if (authData.getRoles().size() == 0) {
                        authData.getRoles().addAll(defaultRoles);
                    }

                    return true;
                }
            } catch (JsonResourceException e) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Failed pass-through authentication of {} on {}.", authData.getUsername(),
                            passThroughAuth, e);
                }
                if (e.isServerError()) {
                    throw new AuthException("Failed pass-through authentication of " + authData.getUsername()
                            + " on " + passThroughAuth + ".");
                }
                //authentication failed
                return false;
            }
        }
    }

    return false;
}

From source file:org.josso.jaspi.agent.JASPISSOAuthModule.java

@Override
public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject)
        throws AuthException {

    HttpServletRequest hreq = (HttpServletRequest) messageInfo.getRequestMessage();
    HttpServletResponse hres = (HttpServletResponse) messageInfo.getResponseMessage();

    if (log.isDebugEnabled()) {
        log.debug("Processing : " + hreq.getContextPath() + " [" + hreq.getRequestURL() + "]");
    }/* w  w w  .j  a v  a2  s.  co  m*/

    try {
        // ------------------------------------------------------------------
        // Check with the agent if this context should be processed.
        // ------------------------------------------------------------------
        String contextPath = hreq.getContextPath();
        String vhost = hreq.getServerName();

        // In catalina, the empty context is considered the root context
        if ("".equals(contextPath)) {
            contextPath = "/";
        }

        if (!_agent.isPartnerApp(vhost, contextPath)) {
            if (log.isDebugEnabled()) {
                log.debug("Context is not a josso partner app : " + hreq.getContextPath());
            }
            AuthStatus status = AuthStatus.SUCCESS;
            return status;
        }

        // ------------------------------------------------------------------
        // Check some basic HTTP handling
        // ------------------------------------------------------------------
        // P3P Header for IE 6+ compatibility when embedding JOSSO in a IFRAME
        SSOPartnerAppConfig cfg = _agent.getPartnerAppConfig(vhost, contextPath);
        if (cfg.isSendP3PHeader() && !hres.isCommitted()) {
            hres.setHeader("P3P", cfg.getP3PHeaderValue());
        }

        // Get our session ...
        HttpSession session = hreq.getSession(true);

        // ------------------------------------------------------------------
        // Check if the partner application required the login form
        // ------------------------------------------------------------------
        if (log.isDebugEnabled()) {
            log.debug("Checking if its a josso_login_request for '" + hreq.getRequestURI() + "'");
        }

        if (hreq.getRequestURI().endsWith(_agent.getJossoLoginUri())
                || hreq.getRequestURI().endsWith(_agent.getJossoUserLoginUri())) {

            if (log.isDebugEnabled()) {
                log.debug("josso_login_request received for uri '" + hreq.getRequestURI() + "'");
            }

            //save referer url in case the user clicked on Login from some public resource (page)
            //so agent can redirect the user back to that page after successful login
            if (hreq.getRequestURI().endsWith(_agent.getJossoUserLoginUri())) {
                saveLoginBackToURL(hreq, hres, session, true);
            } else {
                saveLoginBackToURL(hreq, hres, session, false);
            }

            String loginUrl = _agent.buildLoginUrl(hreq);

            if (log.isDebugEnabled()) {
                log.debug("Redirecting to login url '" + loginUrl + "'");
            }

            //set non cache headers
            _agent.prepareNonCacheResponse(hres);
            hres.sendRedirect(hres.encodeRedirectURL(loginUrl));

            // Request is authorized for this URI
            return AuthStatus.SEND_CONTINUE;
        }

        // ------------------------------------------------------------------
        // Check if the partner application required a logout
        // ------------------------------------------------------------------
        if (log.isDebugEnabled()) {
            log.debug("Checking if its a josso_logout request for '" + hreq.getRequestURI() + "'");
        }

        if (hreq.getRequestURI().endsWith(_agent.getJossoLogoutUri())) {

            if (log.isDebugEnabled()) {
                log.debug("josso_logout request received for uri '" + hreq.getRequestURI() + "'");
            }

            String logoutUrl = _agent.buildLogoutUrl(hreq, cfg);

            if (log.isDebugEnabled()) {
                log.debug("Redirecting to logout url '" + logoutUrl + "'");
            }

            // Clear previous COOKIE ...
            Cookie ssoCookie = _agent.newJossoCookie(hreq.getContextPath(), "-", hreq.isSecure());
            hres.addCookie(ssoCookie);

            // invalidate session (unbind josso security context)
            session.invalidate();

            //set non cache headers
            _agent.prepareNonCacheResponse(hres);
            hres.sendRedirect(hres.encodeRedirectURL(logoutUrl));

            // Request is authorized for this URI
            return AuthStatus.SEND_CONTINUE;
        }

        // ------------------------------------------------------------------
        // Check for the single sign on cookie
        // ------------------------------------------------------------------
        if (log.isDebugEnabled()) {
            log.debug("Checking for SSO cookie");
        }
        Cookie cookie = null;
        Cookie cookies[] = hreq.getCookies();
        if (cookies == null) {
            cookies = new Cookie[0];
        }
        for (int i = 0; i < cookies.length; i++) {
            if (org.josso.gateway.Constants.JOSSO_SINGLE_SIGN_ON_COOKIE.equals(cookies[i].getName())) {
                cookie = cookies[i];
                break;
            }
        }

        String jossoSessionId = (cookie == null) ? null : cookie.getValue();
        if (log.isDebugEnabled()) {
            log.debug("Session is: " + session);
        }

        // Get session map for this servlet context.
        Map sessionMap = (Map) hreq.getSession().getServletContext().getAttribute(KEY_SESSION_MAP);
        if (sessionMap == null) {
            synchronized (this) {
                sessionMap = (Map) hreq.getSession().getServletContext().getAttribute(KEY_SESSION_MAP);
                if (sessionMap == null) {
                    sessionMap = Collections.synchronizedMap(new HashMap());
                    hreq.getSession().getServletContext().setAttribute(KEY_SESSION_MAP, sessionMap);
                }
            }
        }

        LocalSession localSession = (LocalSession) sessionMap.get(session.getId());
        if (localSession == null) {
            localSession = new JASPILocalSession(session);
            // the local session is new so, make the valve listen for its events so that it can
            // map them to local session events.
            // Not Supported : session.addSessionListener(this);
            sessionMap.put(session.getId(), localSession);

        }

        // ------------------------------------------------------------------
        // Check if the partner application submitted custom login form
        // ------------------------------------------------------------------

        if (log.isDebugEnabled()) {
            log.debug("Checking if its a josso_authentication for '" + hreq.getRequestURI() + "'");
        }
        if (hreq.getRequestURI().endsWith(_agent.getJossoAuthenticationUri())) {

            if (log.isDebugEnabled()) {
                log.debug("josso_authentication received for uri '" + hreq.getRequestURI() + "'");
            }

            JASPISSOAgentRequest customAuthRequest = (JASPISSOAgentRequest) doMakeSSOAgentRequest(cfg.getId(),
                    SSOAgentRequest.ACTION_CUSTOM_AUTHENTICATION, jossoSessionId, localSession, null, hreq,
                    hres);

            _agent.processRequest(customAuthRequest);

            // Request is authorized
            return AuthStatus.SEND_CONTINUE;
        }

        if (cookie == null || cookie.getValue().equals("-")) {

            // ------------------------------------------------------------------
            // Trigger LOGIN OPTIONAL if required
            // ------------------------------------------------------------------

            if (log.isDebugEnabled())
                log.debug("SSO cookie is not present, verifying optional login process ");

            // We have no cookie, remember me is enabled and a security check without assertion was received ...
            // This means that the user could not be identified ... go back to the original resource
            if (hreq.getRequestURI().endsWith(_agent.getJossoSecurityCheckUri())
                    && hreq.getParameter("josso_assertion_id") == null) {

                if (log.isDebugEnabled())
                    log.debug(_agent.getJossoSecurityCheckUri()
                            + " received without assertion.  Login Optional Process failed");

                String requestURI = this.getSavedRequestURL(hreq);
                _agent.prepareNonCacheResponse(hres);
                hres.sendRedirect(hres.encodeRedirectURL(requestURI));
                AuthStatus status = AuthStatus.SEND_CONTINUE;
                return status;
            }

            // This is a standard anonymous request!
            if (!hreq.getRequestURI().endsWith(_agent.getJossoSecurityCheckUri())) {

                // If saved request is NOT null, we're in the middle of another process ...
                if (!_agent.isResourceIgnored(cfg, hreq) && _agent.isAutomaticLoginRequired(hreq, hres)) {

                    if (log.isDebugEnabled()) {
                        log.debug("SSO cookie is not present, attempting automatic login");
                    }

                    // Save current request, so we can co back to it later ...
                    saveRequestURL(hreq, hres);
                    String loginUrl = _agent.buildLoginOptionalUrl(hreq);

                    if (log.isDebugEnabled()) {
                        log.debug("Redirecting to login url '" + loginUrl + "'");
                    }

                    //set non cache headers
                    _agent.prepareNonCacheResponse(hres);
                    hres.sendRedirect(hres.encodeRedirectURL(loginUrl));
                    //hreq.getRequestDispatcher(loginUrl).forward(hreq, hres);
                    AuthStatus status = AuthStatus.SEND_CONTINUE;
                    return status;
                } else {
                    if (log.isDebugEnabled()) {
                        log.debug("SSO cookie is not present, but login optional process is not required");
                    }
                }
            }

            if (log.isDebugEnabled()) {
                log.debug("SSO cookie is not present, checking for outbound relaying");
            }

            if (!(hreq.getRequestURI().endsWith(_agent.getJossoSecurityCheckUri())
                    && hreq.getParameter("josso_assertion_id") != null)) {
                log.debug("SSO cookie not present and relaying was not requested, skipping");
                AuthStatus status = AuthStatus.SUCCESS;
                return status;
            }

        }

        // ------------------------------------------------------------------
        // Check if this URI is subject to SSO protection
        // ------------------------------------------------------------------
        if (_agent.isResourceIgnored(cfg, hreq)) {
            // Ignored resources are authorized
            return AuthStatus.SUCCESS;
        }

        // This URI should be protected by SSO, go on ...
        if (log.isDebugEnabled()) {
            log.debug("Session is: " + session);
        }

        // ------------------------------------------------------------------
        // Invoke the SSO Agent
        // ------------------------------------------------------------------
        if (log.isDebugEnabled()) {
            log.debug("Executing agent...");
        }

        // ------------------------------------------------------------------
        // Check if a user has been authenticated and should be checked by the agent.
        // ------------------------------------------------------------------
        if (log.isDebugEnabled()) {
            log.debug("Checking if its a josso_security_check for '" + hreq.getRequestURI() + "'");
        }

        if (hreq.getRequestURI().endsWith(_agent.getJossoSecurityCheckUri())
                && hreq.getParameter("josso_assertion_id") != null) {

            if (log.isDebugEnabled()) {
                log.debug("josso_security_check received for uri '" + hreq.getRequestURI() + "' assertion id '"
                        + hreq.getParameter("josso_assertion_id"));
            }

            String assertionId = hreq.getParameter(Constants.JOSSO_ASSERTION_ID_PARAMETER);

            JASPISSOAgentRequest relayRequest;

            if (log.isDebugEnabled()) {
                log.debug("Outbound relaying requested for assertion id [" + assertionId + "]");
            }

            relayRequest = (JASPISSOAgentRequest) doMakeSSOAgentRequest(cfg.getId(),
                    SSOAgentRequest.ACTION_RELAY, null, localSession, assertionId, hreq, hres);

            SingleSignOnEntry entry = _agent.processRequest(relayRequest);
            if (entry == null) {
                // This is wrong! We should have an entry here!
                if (log.isDebugEnabled()) {
                    log.debug("Outbound relaying failed for assertion id [" + assertionId
                            + "], no Principal found.");
                }
                // Throw an exception, we will handle it below !
                throw new RuntimeException(
                        "Outbound relaying failed. No Principal found. Verify your SSO Agent Configuration!");
            } else {
                // Add the SSOUser as a Principal
                if (!clientSubject.getPrincipals().contains(entry.principal)) {
                    clientSubject.getPrincipals().add(entry.principal);
                }
                SSORole[] ssoRolePrincipals = _agent.getRoleSets(cfg.getId(), entry.ssoId,
                        relayRequest.getNodeId());
                List<String> rolesList = new ArrayList<String>();

                for (int i = 0; i < ssoRolePrincipals.length; i++) {
                    if (clientSubject.getPrincipals().contains(ssoRolePrincipals[i])) {
                        continue;
                    }
                    rolesList.add(ssoRolePrincipals[i].getName());

                    clientSubject.getPrincipals().add(ssoRolePrincipals[i]);
                    log.debug("Added SSORole Principal to the Subject : " + ssoRolePrincipals[i]);
                }

                registerWithCallbackHandler(entry.principal, entry.principal.getName(), entry.ssoId,
                        rolesList.toArray(new String[rolesList.size()]));
            }

            if (log.isDebugEnabled()) {
                log.debug("Outbound relaying succesfull for assertion id [" + assertionId + "]");
            }

            if (log.isDebugEnabled()) {
                log.debug("Assertion id [" + assertionId + "] mapped to SSO session id [" + entry.ssoId + "]");
            }

            // The cookie is valid to for the partner application only ... in the future each partner app may
            // store a different auth. token (SSO SESSION) value
            cookie = _agent.newJossoCookie(hreq.getContextPath(), entry.ssoId, hreq.isSecure());
            hres.addCookie(cookie);

            //Redirect user to the saved splash resource (in case of auth request) or to request URI otherwise
            String requestURI = getSavedSplashResource(hreq);
            if (requestURI == null) {
                requestURI = getSavedRequestURL(hreq);
                if (requestURI == null) {

                    if (cfg.getDefaultResource() != null) {
                        requestURI = cfg.getDefaultResource();
                    } else {
                        // If no saved request is found, redirect to the partner app root :
                        requestURI = hreq.getRequestURI().substring(0,
                                (hreq.getRequestURI().length() - _agent.getJossoSecurityCheckUri().length()));
                    }

                    // If we're behind a reverse proxy, we have to alter the URL ... this was not necessary on tomcat 5.0 ?!
                    String singlePointOfAccess = _agent.getSinglePointOfAccess();
                    if (singlePointOfAccess != null) {
                        requestURI = singlePointOfAccess + requestURI;
                    } else {
                        String reverseProxyHost = hreq
                                .getHeader(org.josso.gateway.Constants.JOSSO_REVERSE_PROXY_HEADER);
                        if (reverseProxyHost != null) {
                            requestURI = reverseProxyHost + requestURI;
                        }
                    }

                    if (log.isDebugEnabled())
                        log.debug("No saved request found, using : '" + requestURI + "'");
                }
            }

            _agent.clearAutomaticLoginReferer(hreq, hres);
            _agent.prepareNonCacheResponse(hres);

            // Check if we have a post login resource :
            String postAuthURI = cfg.getPostAuthenticationResource();
            if (postAuthURI != null) {
                String postAuthURL = _agent.buildPostAuthUrl(hres, requestURI, postAuthURI);
                if (log.isDebugEnabled()) {
                    log.debug("Redirecting to post-auth-resource '" + postAuthURL + "'");
                }
                hres.sendRedirect(postAuthURL);
            } else {
                if (log.isDebugEnabled()) {
                    log.debug("Redirecting to original '" + requestURI + "'");
                }
                hres.sendRedirect(hres.encodeRedirectURL(requestURI));
            }

            AuthStatus status = AuthStatus.SEND_SUCCESS;
            return status;
        }

        if (log.isDebugEnabled()) {
            log.debug("Creating Security Context for Session [" + session + "]");
        }
        SSOAgentRequest r = doMakeSSOAgentRequest(cfg.getId(),
                SSOAgentRequest.ACTION_ESTABLISH_SECURITY_CONTEXT, jossoSessionId, localSession, null, hreq,
                hres);
        SingleSignOnEntry entry = _agent.processRequest(r);

        if (log.isDebugEnabled()) {
            log.debug("Executed agent.");
        }

        // ------------------------------------------------------------------
        // Has a valid user already been authenticated?
        // ------------------------------------------------------------------
        if (log.isDebugEnabled()) {
            log.debug("Process request for '" + hreq.getRequestURI() + "'");
        }

        if (entry != null) {
            if (log.isDebugEnabled()) {
                log.debug("Principal '" + entry.principal + "' has already been authenticated");
            }
            // Add the SSOUser as a Principal
            if (!clientSubject.getPrincipals().contains(entry.principal)) {
                clientSubject.getPrincipals().add(entry.principal);
            }
            SSORole[] ssoRolePrincipals = _agent.getRoleSets(cfg.getId(), entry.ssoId, r.getNodeId());
            List<String> rolesList = new ArrayList<String>();
            for (int i = 0; i < ssoRolePrincipals.length; i++) {
                if (clientSubject.getPrincipals().contains(ssoRolePrincipals[i])) {
                    continue;
                }
                rolesList.add(ssoRolePrincipals[i].getName());
                clientSubject.getPrincipals().add(ssoRolePrincipals[i]);
                log.debug("Added SSORole Principal to the Subject : " + ssoRolePrincipals[i]);
            }
            registerWithCallbackHandler(entry.principal, entry.principal.getName(), entry.ssoId,
                    rolesList.toArray(new String[rolesList.size()]));
        } else {
            log.debug("No Valid SSO Session, attempt an optional login?");
            // This is a standard anonymous request!

            if (cookie != null) {
                // cookie is not valid
                cookie = _agent.newJossoCookie(hreq.getContextPath(), "-", hreq.isSecure());
                hres.addCookie(cookie);
            }

            if (cookie != null
                    || (getSavedRequestURL(hreq) == null && _agent.isAutomaticLoginRequired(hreq, hres))) {
                if (log.isDebugEnabled()) {
                    log.debug("SSO Session is not valid, attempting automatic login");
                }

                // Save current request, so we can co back to it later ...
                saveRequestURL(hreq, hres);
                String loginUrl = _agent.buildLoginOptionalUrl(hreq);

                if (log.isDebugEnabled()) {
                    log.debug("Redirecting to login url '" + loginUrl + "'");
                }

                //set non cache headers
                _agent.prepareNonCacheResponse(hres);
                hres.sendRedirect(hres.encodeRedirectURL(loginUrl));

                // Request is authorized for this URI
                return AuthStatus.SEND_CONTINUE;
            } else {
                if (log.isDebugEnabled()) {
                    log.debug("SSO cookie is not present, but login optional process is not required");
                }
            }

        }

        // propagate the login and logout URLs to
        // partner applications.
        hreq.setAttribute("org.josso.agent.gateway-login-url", _agent.getGatewayLoginUrl());
        hreq.setAttribute("org.josso.agent.gateway-logout-url", _agent.getGatewayLogoutUrl());
        hreq.setAttribute("org.josso.agent.ssoSessionid", jossoSessionId);

        clearSavedRequestURLs(hreq, hres);

        AuthStatus status = AuthStatus.SUCCESS;
        return status;
    } catch (Throwable t) {
        log.warn(t.getMessage(), t);
        throw new AuthException(t.getMessage());
        //return AuthStatus.FAILURE;
    } finally {
        if (log.isDebugEnabled()) {
            log.debug("Processed : " + hreq.getContextPath() + " [" + hreq.getRequestURL() + "]");
        }
    }
}