/*
 * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 *
 * WSO2 Inc. licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.wso2.carbon.identity.application.authentication.framework.util;

import com.google.gson.JsonObject;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.base.MultitenantConstants;
import org.wso2.carbon.identity.application.authentication.framework.config.model.StepConfig;
import org.wso2.carbon.identity.application.authentication.framework.context.AuthenticationContext;
import org.wso2.carbon.identity.base.IdentityException;
import org.wso2.carbon.identity.core.util.IdentityTenantUtil;
import org.wso2.carbon.registry.core.Registry;
import org.wso2.carbon.registry.core.Resource;
import org.wso2.carbon.registry.core.exceptions.RegistryException;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

/**
 * This class handles the redirect URL retrieval for invalid session index.
 */
public class LoginContextManagementUtil {

    private static final String SP_REDIRECT_URL_RESOURCE_PATH = "/identity/config/relyingPartyRedirectUrls";
    private static final Log log = LogFactory.getLog(LoginContextManagementUtil.class);
    private static final String CLEAR_EXISTING_SESSION_PARAM = "clearSession";

    public static void handleLoginContext(HttpServletRequest request, HttpServletResponse response)
            throws IOException {

        String sessionDataKey = request.getParameter("sessionDataKey");
        String relyingParty = request.getParameter("relyingParty");
        String tenantDomain = request.getParameter("tenantDomain");

        JsonObject result = new JsonObject();
        response.setContentType("application/json");
        if (StringUtils.isBlank(relyingParty) || StringUtils.isBlank(sessionDataKey)) {
            if (log.isDebugEnabled()) {
                log.debug("Required data to proceed is not available in the request.");
            }
            //cannot handle the request without sessionDataKey
            result.addProperty("status", "success");
            response.getWriter().write(result.toString());
            return;
        }

        AuthenticationContext context = FrameworkUtils.getAuthenticationContextFromCache(sessionDataKey);
        // Valid Request
        if (context != null) {
            if (isStepHasMultiOption(context)) {
                context.setCurrentAuthenticator(null);
            }
            result.addProperty("status", "success");
            response.getWriter().write(result.toString());
        } else {
            String clearCookieFlagValue = request.getParameter(CLEAR_EXISTING_SESSION_PARAM);
            if (Boolean.parseBoolean(clearCookieFlagValue)) {
                Cookie cookie = new Cookie(FrameworkConstants.COMMONAUTH_COOKIE, null);
                cookie.setMaxAge(0);
                cookie.setSecure(true);
                cookie.setHttpOnly(true);
                cookie.setPath("/");
                response.addCookie(cookie);
            }
            String redirectUrl = getRelyingPartyRedirectUrl(relyingParty, tenantDomain);
            if (StringUtils.isBlank(redirectUrl)) {
                if (log.isDebugEnabled()) {
                    log.debug("Redirect URL is not available for the relaying party - " + relyingParty + " for " +
                            "sessionDataKey: " + sessionDataKey);
                }
                // Can't handle
                result.addProperty("status", "success");
                response.getWriter().write(result.toString());
            } else {
                if (log.isDebugEnabled()) {
                    log.debug("Redirect URL is: " + redirectUrl + " for the relaying party - " + relyingParty +
                            " for " + "sessionDataKey: " + sessionDataKey);
                }
                result.addProperty("status", "redirect");
                result.addProperty("redirectUrl", redirectUrl);
                response.getWriter().write(result.toString());
            }
        }
    }

    /**
     * Returns the redirect url configured in the registry against relying party.
     *
     * @param relyingParty Name of the relying party
     * @param tenantDomain Tenant Domain.
     * @return Redirect URL.
     */
    public static String getRelyingPartyRedirectUrl(String relyingParty, String tenantDomain) {
        if (log.isDebugEnabled()) {
            log.debug("retrieving configured url against relying party : " + relyingParty + "for tenant domain : " +
                    tenantDomain);
        }

        int tenantId;
        if (StringUtils.isEmpty(tenantDomain)) {
            if (log.isDebugEnabled()) {
                log.debug("Tenant domain is not available. Hence using super tenant domain");
            }
            tenantDomain = MultitenantConstants.SUPER_TENANT_DOMAIN_NAME;
            tenantId = MultitenantConstants.SUPER_TENANT_ID;
        } else {
            tenantId = IdentityTenantUtil.getTenantId(tenantDomain);
        }
        try {
            IdentityTenantUtil.initializeRegistry(tenantId);
            Registry registry = IdentityTenantUtil.getConfigRegistry(tenantId);
            if (registry.resourceExists(SP_REDIRECT_URL_RESOURCE_PATH)) {
                Resource resource = registry.get(SP_REDIRECT_URL_RESOURCE_PATH);
                if (resource != null) {
                    String redirectUrl = resource.getProperty(relyingParty);
                    if (StringUtils.isNotEmpty(redirectUrl)) {
                        return redirectUrl;
                    }
                }
            }
        } catch (RegistryException e) {
            log.error("Error while getting data from the registry.", e);
        } catch (IdentityException e) {
            log.error("Error while getting the tenant domain from tenant id : " + tenantId, e);
        }
        return null;
    }

    /**
     * Returns whether post authentication handler execution is ended or not.
     *
     * @param authenticationContext Authentication context.
     * @return True if post authentication handlers have finished execution on this context. else false.
     */
    public static boolean isPostAuthenticationExtensionCompleted(AuthenticationContext authenticationContext) {

        Object object = authenticationContext.getProperty(FrameworkConstants.POST_AUTHENTICATION_EXTENSION_COMPLETED);
        if (object != null && object instanceof Boolean) {
            return (Boolean) object;
        } else {
            return false;
        }
    }

    /**
     * Mark post authentication handler execution completion on authentication context.
     *
     * @param authenticationContext Authentication context.
     */
    public static void markPostAuthenticationCompleted(AuthenticationContext authenticationContext) {

        authenticationContext.setProperty(FrameworkConstants.POST_AUTHENTICATION_EXTENSION_COMPLETED,
                true);
    }

    private static boolean isStepHasMultiOption(AuthenticationContext context) {

        Map<Integer, StepConfig> stepMap = context.getSequenceConfig().getStepMap();
        boolean stepHasMultiOption = false;

        if (stepMap != null && !stepMap.isEmpty()) {
            StepConfig stepConfig = stepMap.get(context.getCurrentStep());

            if (stepConfig != null) {
                stepHasMultiOption = stepConfig.isMultiOption();
            }
        }
        return stepHasMultiOption;
    }
}

@@ -1434,42 +1434,8 @@
 n;%0A%0A
-import javax.servlet.http.Cookie;%0A
 impo
@@ -1901,87 +1901,8 @@
 ss);
-%0A    private static final String CLEAR_EXISTING_SESSION_PARAM = %22clearSession%22;
 %0A%0A  
@@ -3190,466 +3190,8 @@
 e %7B%0A
-            String clearCookieFlagValue = request.getParameter(CLEAR_EXISTING_SESSION_PARAM);%0A            if (Boolean.parseBoolean(clearCookieFlagValue)) %7B%0A                Cookie cookie = new Cookie(FrameworkConstants.COMMONAUTH_COOKIE, null);%0A                cookie.setMaxAge(0);%0A                cookie.setSecure(true);%0A                cookie.setHttpOnly(true);%0A                cookie.setPath(%22/%22);%0A                response.addCookie(cookie);%0A            %7D%0A
     

Revert changes done in #2655