package org.pac4j.oidc.redirect;

import com.nimbusds.oauth2.sdk.id.State;
import com.nimbusds.openid.connect.sdk.AuthenticationRequest;
import com.nimbusds.openid.connect.sdk.Nonce;
import org.apache.commons.lang3.StringUtils;
import org.pac4j.core.client.RedirectAction;
import org.pac4j.core.context.WebContext;
import org.pac4j.core.exception.HttpAction;
import org.pac4j.core.exception.TechnicalException;
import org.pac4j.core.redirect.RedirectActionBuilder;
import org.pac4j.core.util.CommonHelper;
import org.pac4j.core.util.InitializableWebObject;
import org.pac4j.oidc.config.OidcConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

/**
 * Redirect to the OpenID Connect provider.
 *
 * @author Jerome Leleu
 * @since 1.9.2
 */
public class OidcRedirectActionBuilder extends InitializableWebObject implements RedirectActionBuilder {

    private static final Logger logger = LoggerFactory.getLogger(OidcRedirectActionBuilder.class);

    private OidcConfiguration configuration;

    private Map<String, String> authParams;

    public OidcRedirectActionBuilder() {}

    public OidcRedirectActionBuilder(final OidcConfiguration configuration) {
        this.configuration = configuration;
    }

    @Override
    protected void internalInit(final WebContext context) {
        CommonHelper.assertNotNull("configuration", configuration);

        this.authParams = new HashMap<>();
        final String scope = configuration.getScope();
        // add scope
        if(StringUtils.isNotBlank(scope)){
            this.authParams.put("scope", scope);
        } else {
            // default values
            this.authParams.put("scope", "openid profile email");
        }
        this.authParams.put("response_type", "code");
        this.authParams.put("redirect_uri", configuration.getCallbackUrl());
        // add custom values
        this.authParams.putAll(configuration.getCustomParams());
        // Override with required values
        this.authParams.put("client_id", configuration.getClientId());
    }

    @Override
    public RedirectAction redirect(final WebContext context) throws HttpAction {
        final Map<String, String> params = new HashMap<>(this.authParams);

        // Init state for CSRF mitigation
        State state = new State();
        params.put("state", state.getValue());
        context.setSessionAttribute(OidcConfiguration.STATE_ATTRIBUTE, state);
        // Init nonce for replay attack mitigation
        if (configuration.isUseNonce()) {
            Nonce nonce = new Nonce();
            params.put("nonce", nonce.getValue());
            context.setSessionAttribute(OidcConfiguration.NONCE_ATTRIBUTE, nonce.getValue());
        }

        // Build authentication request query string
        String queryString;
        try {
            queryString = AuthenticationRequest.parse(params).toQueryString();
        } catch (Exception e) {
            throw new TechnicalException(e);
        }
        String location = configuration.getProviderMetadata().getAuthorizationEndpointURI().toString() + "?" + queryString;
        logger.debug("Authentication request url: {}", location);

        return RedirectAction.redirect(location);
    }

    public OidcConfiguration getConfiguration() {
        return configuration;
    }

    public void setConfiguration(final OidcConfiguration configuration) {
        this.configuration = configuration;
    }

    @Override
    public String toString() {
        return CommonHelper.toString(this.getClass(), "configuration", configuration);
    }
}

@@ -2257,24 +2257,381 @@
 thParams);%0A%0A
+        addStateAndNonceParameters(context, params);%0A%0A        final String location = buildAuthenticationRequestUrl(params);%0A        logger.debug(%22Authentication request url: %7B%7D%22, location);%0A%0A        return RedirectAction.redirect(location);%0A    %7D%0A%0A    protected void addStateAndNonceParameters(final WebContext context, final Map%3CString, String%3E params) %7B%0A
         // I
@@ -3104,24 +3104,117 @@
 ;%0A        %7D%0A
+    %7D%0A%0A    protected String buildAuthenticationRequestUrl(final Map%3CString, String%3E params) %7B
 %0A        // 
@@ -3259,24 +3259,30 @@
 ing%0A        
+final 
 String query
@@ -3477,33 +3477,22 @@
         
-String location =
+return
  configu
@@ -3586,125 +3586,8 @@
 ng;%0A
-        logger.debug(%22Authentication request url: %7B%7D%22, location);%0A%0A        return RedirectAction.redirect(location);%0A
     

refactor OidcRedirectActionBuilder