package org.apereo.cas.support.saml.web.idp.profile.sso;

import org.apereo.cas.authentication.AuthenticationSystemSupport;
import org.apereo.cas.authentication.principal.Service;
import org.apereo.cas.authentication.principal.ServiceFactory;
import org.apereo.cas.authentication.principal.WebApplicationService;
import org.apereo.cas.configuration.CasConfigurationProperties;
import org.apereo.cas.services.ServicesManager;
import org.apereo.cas.support.saml.OpenSamlConfigBean;
import org.apereo.cas.support.saml.SamlIdPConstants;
import org.apereo.cas.support.saml.services.idp.metadata.cache.SamlRegisteredServiceCachingMetadataResolver;
import org.apereo.cas.support.saml.web.idp.profile.AbstractSamlProfileHandlerController;
import org.apereo.cas.support.saml.web.idp.profile.builders.SamlProfileObjectBuilder;
import org.apereo.cas.support.saml.web.idp.profile.builders.enc.SamlIdPObjectSigner;
import org.apereo.cas.support.saml.web.idp.profile.builders.enc.validate.SamlObjectSignatureValidator;
import org.apereo.cas.support.saml.web.idp.profile.sso.request.SSOSamlHttpRequestExtractor;

import lombok.val;
import org.opensaml.messaging.decoder.servlet.BaseHttpServletRequestXMLMessageDecoder;
import org.opensaml.saml.saml2.binding.decoding.impl.HTTPPostDecoder;
import org.opensaml.saml.saml2.binding.decoding.impl.HTTPRedirectDeflateDecoder;
import org.opensaml.saml.saml2.core.AuthnRequest;
import org.opensaml.saml.saml2.core.Response;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * The {@link SSOSamlPostProfileHandlerController} is responsible for
 * handling profile requests for SAML2 Web SSO.
 *
 * @author Misagh Moayyed
 * @since 5.0.0
 */
public class SSOSamlPostProfileHandlerController extends AbstractSamlProfileHandlerController {
    private final SSOSamlHttpRequestExtractor samlHttpRequestExtractor;

    public SSOSamlPostProfileHandlerController(final SamlIdPObjectSigner samlObjectSigner,
                                               final AuthenticationSystemSupport authenticationSystemSupport,
                                               final ServicesManager servicesManager,
                                               final ServiceFactory<WebApplicationService> webApplicationServiceFactory,
                                               final SamlRegisteredServiceCachingMetadataResolver samlRegisteredServiceCachingMetadataResolver,
                                               final OpenSamlConfigBean configBean,
                                               final SamlProfileObjectBuilder<Response> responseBuilder,
                                               final CasConfigurationProperties casProperties,
                                               final SamlObjectSignatureValidator samlObjectSignatureValidator,
                                               final SSOSamlHttpRequestExtractor samlHttpRequestExtractor,
                                               final Service callbackService) {
        super(samlObjectSigner,
            authenticationSystemSupport,
            servicesManager,
            webApplicationServiceFactory,
            samlRegisteredServiceCachingMetadataResolver,
            configBean,
            responseBuilder,
            casProperties,
            samlObjectSignatureValidator,
            callbackService);
        this.samlHttpRequestExtractor = samlHttpRequestExtractor;
    }


    /**
     * Handle SSO POST profile request.
     *
     * @param response the response
     * @param request  the request
     * @throws Exception the exception
     */
    @GetMapping(path = SamlIdPConstants.ENDPOINT_SAML2_SSO_PROFILE_REDIRECT)
    public void handleSaml2ProfileSsoRedirectRequest(final HttpServletResponse response,
                                                     final HttpServletRequest request) throws Exception {
        handleSsoPostProfileRequest(response, request, new HTTPRedirectDeflateDecoder());
    }

    /**
     * Handle SSO POST profile request.
     *
     * @param response the response
     * @param request  the request
     * @throws Exception the exception
     */
    @PostMapping(path = SamlIdPConstants.ENDPOINT_SAML2_SSO_PROFILE_POST)
    public void handleSaml2ProfileSsoPostRequest(final HttpServletResponse response,
                                                 final HttpServletRequest request) throws Exception {
        handleSsoPostProfileRequest(response, request, new HTTPPostDecoder());
    }

    /**
     * Handle profile request.
     *
     * @param response the response
     * @param request  the request
     * @param decoder  the decoder
     * @throws Exception the exception
     */
    public void handleSsoPostProfileRequest(final HttpServletResponse response,
                                            final HttpServletRequest request,
                                            final BaseHttpServletRequestXMLMessageDecoder decoder) throws Exception {
        val authnRequest = this.samlHttpRequestExtractor.extract(request, decoder, AuthnRequest.class);
        initiateAuthenticationRequest(authnRequest, response, request);
    }

}

@@ -1091,16 +1091,50 @@
 actor;%0A%0A
+import lombok.extern.slf4j.Slf4j;%0A
 import l
@@ -1144,16 +1144,16 @@
 ok.val;%0A
-
 import o
@@ -1596,16 +1596,141 @@
 Mapping;
+%0Aimport org.springframework.web.bind.annotation.RequestMapping;%0Aimport org.springframework.web.bind.annotation.RequestMethod;
 %0A%0Aimport
@@ -1988,16 +1988,23 @@
 0.0%0A */%0A
+@Slf4j%0A
 public c
@@ -3745,35 +3745,34 @@
    * Handle SSO 
-POS
+GE
 T profile reques
@@ -3757,32 +3757,41 @@
 SSO GET profile 
+redirect 
 request.%0A     *%0A
@@ -4172,32 +4172,32 @@
 ows Exception %7B%0A
-
         handleSs
@@ -4269,32 +4269,756 @@
 oder());%0A    %7D%0A%0A
+    /**%0A     * Handle SSO HEAD profile redirect request (not allowed).%0A     *%0A     * @param response the response%0A     * @param request  the request%0A     * @throws Exception the exception%0A     */%0A    @RequestMapping(path = SamlIdPConstants.ENDPOINT_SAML2_SSO_PROFILE_REDIRECT, method = %7B RequestMethod.HEAD %7D)%0A    public void handleSaml2ProfileSsoRedirectHeadRequest(final HttpServletResponse response,%0A                                                         final HttpServletRequest request) throws Exception %7B%0A        LOGGER.info(%22Endpoint %5B%7B%7D%5D called with HTTP HEAD returning 400 Bad Request%22, SamlIdPConstants.ENDPOINT_SAML2_SSO_PROFILE_REDIRECT);%0A        response.setStatus(HttpServletResponse.SC_BAD_REQUEST);%0A    %7D%0A%0A
     /**%0A     * H

Handle HEAD /idp/profile/SAML2/Redirect/SSO [Forward-Port] (#3706)