package org.keycloak.adapters.springsecurity.filter;

import org.keycloak.constants.AdapterConstants;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;

/**
 * CSRF protection matcher that allows administrative POST requests from the Keycloak server.
 *
 * @author <a href="mailto:srossillo@smartling.com">Scott Rossillo</a>
 */
public class KeycloakCsrfRequestMatcher implements RequestMatcher {

    private static final List<String> ALLOWED_ENDPOINTS = Arrays.asList(
            AdapterConstants.K_LOGOUT,
            AdapterConstants.K_PUSH_NOT_BEFORE,
            AdapterConstants.K_QUERY_BEARER_TOKEN,
            AdapterConstants.K_TEST_AVAILABLE,
            AdapterConstants.K_VERSION
    );

    private Pattern allowedMethods = Pattern.compile("^(GET|HEAD|TRACE|OPTIONS)$");
    private Pattern allowedEndpoints = Pattern.compile(String.format("^\\/(%s)$", StringUtils.arrayToDelimitedString(ALLOWED_ENDPOINTS.toArray(), "|")));

    /* (non-Javadoc)
     * @see org.springframework.security.web.util.matcher.RequestMatcher#matches(javax.servlet.http.HttpServletRequest)
     */
    public boolean matches(HttpServletRequest request) {
        String uri = request.getRequestURI().replaceFirst(request.getContextPath(), "");
        return !allowedEndpoints.matcher(uri).matches() && !allowedMethods.matcher(request.getMethod()).matches();
    }
}
