/*
 * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.com).
 *
 * 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.endpoint.util.filter;

import com.google.gson.Gson;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.identity.application.authentication.endpoint.util.AuthContextAPIClient;
import org.wso2.carbon.identity.application.authentication.endpoint.util.client.model.AuthenticationRequestWrapper;
import org.wso2.carbon.identity.core.ServiceURLBuilder;
import org.wso2.carbon.identity.core.URLBuilderException;

import java.io.IOException;
import java.util.Map;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

/**
 * Cache the parameters required in the authentication flow.
 */
public class AuthParameterFilter implements Filter {

    private static final Log log = LogFactory.getLog(AuthParameterFilter.class);
    private ServletContext context = null;

    private static final String DATA_API_PATH = "/api/identity/auth/v1.1/";
    private static final String SESSION_DATA_KEY = "sessionDataKey";
    private static final String SESSION_DATA_KEY_CONSENT = "sessionDataKeyConsent";
    private static final String ERROR_KEY = "errorKey";

    @Override
    public void init(FilterConfig filterConfig) {
        context = filterConfig.getServletContext();
    }

    /**
     * @param servletRequest
     * @param servletResponse
     * @param filterChain
     * @throws IOException
     * @throws ServletException
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
        if (servletRequest instanceof HttpServletRequest) {
            // Check if request contains 'sessionDataKey', 'sessionDataKeyConsent', 'errorKey', 'promptId'.
            if (servletRequest.getParameter(SESSION_DATA_KEY) != null) {
                // Cast ServletRequest to HttpServletRequest and get the wrapped request.
                HttpServletRequest httpServletRequest = getServletRequestWithParams(servletRequest, SESSION_DATA_KEY);
                filterChain.doFilter(httpServletRequest, servletResponse);
                return;
            }
            if (servletRequest.getParameter(SESSION_DATA_KEY_CONSENT) != null) {
                HttpServletRequest httpServletRequest =
                        getServletRequestWithParams(servletRequest, SESSION_DATA_KEY_CONSENT);
                filterChain.doFilter(httpServletRequest, servletResponse);
                return;
            }
            if (servletRequest.getParameter(ERROR_KEY) != null) {
                HttpServletRequest httpServletRequest = getServletRequestWithParams(servletRequest, ERROR_KEY);
                filterChain.doFilter(httpServletRequest, servletResponse);
                return;
            }
        }
        filterChain.doFilter(servletRequest, servletResponse);
    }

    /**
     * Get HttpServletRequest with parameters retrieved from the API.
     *
     * @param servletRequest - Received HttpServletRequest.
     * @param key            - Name of the key.
     * @return - HttpServletRequest with parameters.
     */
    private HttpServletRequest getServletRequestWithParams(ServletRequest servletRequest, String key) {
        String authAPIURL = buildAPIPath(key, servletRequest.getParameter(key));
        String contextProperties = AuthContextAPIClient.getContextProperties(authAPIURL);
        Gson gson = new Gson();
        Map<String, Object> cachedParams = gson.fromJson(contextProperties, Map.class);
        return new AuthenticationRequestWrapper((HttpServletRequest) servletRequest, cachedParams);
    }

    /**
     * Build the API Path using the key and value.
     *
     * @param key   - SessionDataKey or SessionDataKeyConsent.
     * @param value - Value of the key.
     * @return - API Path.
     */
    private String buildAPIPath(String key, String value) {

        try {
            String authAPIURL = ServiceURLBuilder.create().addPath(DATA_API_PATH).build().getAbsoluteInternalURL();

            if (!authAPIURL.endsWith("/")) {
                authAPIURL += "/";
            }

            switch (key) {
                case SESSION_DATA_KEY:
                    // Add 'sessionDataKey' to URL.
                    authAPIURL += "data/AuthRequestKey/" + value;
                    break;
                case SESSION_DATA_KEY_CONSENT:
                    // Add 'sessionDataKeyConsent' to URL.
                    authAPIURL += "data/OauthConsentKey/" + value;
                    break;
                case ERROR_KEY:
                    authAPIURL += "data/AuthenticationError/" + value;
                    break;
            }
            return authAPIURL;
        } catch (URLBuilderException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void destroy() {
    }
}

@@ -24,19 +24,19 @@
 2, WSO2 
-Inc
+LLC
 . (http:

update copyright header