/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF 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.apache.catalina.authenticator;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import org.junit.Test;

import org.apache.catalina.Context;
import org.apache.catalina.Session;
import org.apache.catalina.session.ManagerBase;
import org.apache.catalina.startup.TesterServletEncodeUrl;
import org.apache.catalina.startup.Tomcat;
import org.apache.catalina.startup.TomcatBaseTest;
import org.apache.tomcat.util.buf.ByteChunk;
import org.apache.tomcat.util.codec.binary.Base64;
import org.apache.tomcat.util.descriptor.web.LoginConfig;
import org.apache.tomcat.util.descriptor.web.SecurityCollection;
import org.apache.tomcat.util.descriptor.web.SecurityConstraint;

/**
 * Test BasicAuthenticator and NonLoginAuthenticator when a
 * SingleSignOn Valve is active.
 *
 * <p>
 * In the absence of SSO support, a webapp using NonLoginAuthenticator
 * simply cannot access protected resources. These tests exercise the
 * the way successfully authenticating a different webapp under the
 * BasicAuthenticator triggers the additional SSO logic for both webapps.
 *
 * <p>
 * The two Authenticators are thoroughly exercised by two other unit test
 * classes: TestBasicAuthParser and TestNonLoginAndBasicAuthenticator.
 * This class mainly examines the way the Single SignOn Valve interacts with
 * two webapps when the second cannot be authenticated directly, but needs
 * to inherit its authentication via the other.
 *
 * <p>
 * When the server and client can both use cookies, the authentication
 * is preserved through the exchange of a JSSOSESSIONID cookie, which
 * is different to the individual and unique JSESSIONID cookies assigned
 * separately to the two webapp sessions.
 *
 * <p>
 * The other situation examined is where the server returns authentication
 * cookies, but the client is configured to ignore them. The Tomcat
 * documentation clearly states that SSO <i>requires</i> the client to
 * support cookies, so access to resources in other webapp containers
 * receives no SSO assistance.
 */
public class TestSSOnonLoginAndBasicAuthenticator extends TomcatBaseTest {

    protected static final boolean USE_COOKIES = true;
    protected static final boolean NO_COOKIES = !USE_COOKIES;

    private static final String USER = "user";
    private static final String PWD = "pwd";
    private static final String ROLE = "role";
    private static final String NICE_METHOD = "Basic";

    private static final String HTTP_PREFIX = "http://localhost:";
    private static final String CONTEXT_PATH_NOLOGIN = "/nologin";
    private static final String CONTEXT_PATH_LOGIN = "/login";
    private static final String URI_PROTECTED = "/protected";
    private static final String URI_PUBLIC = "/anyoneCanAccess";

    // session expiry in web.xml is defined in minutes
    private static final int SHORT_SESSION_TIMEOUT_MINS = 1;
    private static final int LONG_SESSION_TIMEOUT_MINS = 2;

    // we don't change the expiry scan interval - just the iteration count
    private static final int MANAGER_SCAN_INTERVAL_SECS = 10;
    private static final int MANAGER_EXPIRE_SESSIONS_FAST = 1;

    // now compute some delays - beware of the units!
    private static final int EXTRA_DELAY_SECS = 5;
    private static final int TIMEOUT_WAIT_SECS =  EXTRA_DELAY_SECS +
            (MANAGER_SCAN_INTERVAL_SECS * MANAGER_EXPIRE_SESSIONS_FAST) * 5;

    private static final String CLIENT_AUTH_HEADER = "authorization";
    private static final String SERVER_AUTH_HEADER = "WWW-Authenticate";
    private static final String SERVER_COOKIE_HEADER = "Set-Cookie";
    private static final String CLIENT_COOKIE_HEADER = "Cookie";
    private static final String ENCODE_SESSION_PARAM = "jsessionid";
    private static final String ENCODE_SSOSESSION_PARAM = "jssosessionid";

    private static final
            TestSSOnonLoginAndBasicAuthenticator.BasicCredentials
                    NO_CREDENTIALS = null;
    private static final
            TestSSOnonLoginAndBasicAuthenticator.BasicCredentials
                    GOOD_CREDENTIALS =
                new TestSSOnonLoginAndBasicAuthenticator.BasicCredentials(
                            NICE_METHOD, USER, PWD);

    private Tomcat tomcat;
    private Context basicContext;
    private Context nonloginContext;
    private List<String> cookies;
    private String encodedURL;

    /*
     * Run some sanity checks without an established SSO session
     * to make sure the test environment is correct.
     */
    @Test
    public void testEssentialEnvironment() throws Exception {

        // should be permitted to access an unprotected resource.
        doTestNonLogin(CONTEXT_PATH_NOLOGIN + URI_PUBLIC,
                       USE_COOKIES, HttpServletResponse.SC_OK);

        // should not be permitted to access a protected resource
        // with the two Authenticators used in the remaining tests.
        doTestNonLogin(CONTEXT_PATH_NOLOGIN + URI_PROTECTED,
                USE_COOKIES, HttpServletResponse.SC_FORBIDDEN);
        doTestBasic(CONTEXT_PATH_LOGIN + URI_PROTECTED,
                NO_CREDENTIALS, USE_COOKIES,
                HttpServletResponse.SC_UNAUTHORIZED);
    }

    @Test
    public void testEssentialEnvironmentWithoutCookies() throws Exception {

        // should be permitted to access an unprotected resource.
        doTestNonLogin(CONTEXT_PATH_NOLOGIN + URI_PUBLIC,
                       NO_COOKIES, HttpServletResponse.SC_OK);

        // should not be permitted to access a protected resource
        // with the two Authenticators used in the remaining tests.
        doTestNonLogin(CONTEXT_PATH_NOLOGIN + URI_PROTECTED,
                NO_COOKIES, HttpServletResponse.SC_FORBIDDEN);
        doTestBasic(CONTEXT_PATH_LOGIN + URI_PROTECTED,
                NO_CREDENTIALS, NO_COOKIES,
                HttpServletResponse.SC_UNAUTHORIZED);
    }

    /*
     * Logon to access a protected resource using BASIC authentication,
     * which will establish an SSO session.
     * Wait until the SSO session times-out, then try to re-access
     * the resource. This should be rejected with SC_FORBIDDEN 401 status.
     *
     * Note: this test should run for ~10 seconds.
     */
    @Test
    public void testBasicAccessAndSessionTimeout() throws Exception {

        setRapidSessionTimeoutDetection();

        doTestBasic(CONTEXT_PATH_LOGIN + URI_PROTECTED,
                NO_CREDENTIALS, USE_COOKIES,
                HttpServletResponse.SC_UNAUTHORIZED);
        doTestBasic(CONTEXT_PATH_LOGIN + URI_PROTECTED,
                GOOD_CREDENTIALS, USE_COOKIES,
                HttpServletResponse.SC_OK);

        // verify the SSOID exists as a cookie
        doTestBasic(CONTEXT_PATH_LOGIN + URI_PROTECTED,
                GOOD_CREDENTIALS, USE_COOKIES,
                HttpServletResponse.SC_OK);

        // make the session time out and lose authentication
        doImminentSessionTimeout(basicContext);

        doTestBasic(CONTEXT_PATH_LOGIN + URI_PROTECTED,
                NO_CREDENTIALS, USE_COOKIES,
                HttpServletResponse.SC_UNAUTHORIZED);
    }


    /*
     * Logon to access a protected resource using BASIC authentication,
     * which will establish an SSO session.
     * Immediately try to access a protected resource in the NonLogin
     * webapp while providing the SSO session cookie received from the
     * first webapp. This should be successful with SC_OK 200 status.
     */
    @Test
    public void testBasicLoginThenAcceptWithCookies() throws Exception {

        doTestBasic(CONTEXT_PATH_LOGIN + URI_PROTECTED,
                NO_CREDENTIALS, NO_COOKIES,
                HttpServletResponse.SC_UNAUTHORIZED);
        doTestBasic(CONTEXT_PATH_LOGIN + URI_PROTECTED,
                GOOD_CREDENTIALS, USE_COOKIES, HttpServletResponse.SC_OK);

        // send the cookie which proves we have an authenticated SSO session
        doTestNonLogin(CONTEXT_PATH_NOLOGIN + URI_PROTECTED,
                       USE_COOKIES, HttpServletResponse.SC_OK);
    }

    /*
     * Logon to access a protected resource using BASIC authentication,
     * which will establish an SSO session.
     * Immediately try to access a protected resource in the NonLogin
     * webapp, but without sending the SSO session cookie.
     * This should be rejected with SC_FORBIDDEN 403 status.
     */
    @Test
    public void testBasicLoginThenRejectWithoutCookie() throws Exception {

        doTestBasic(CONTEXT_PATH_LOGIN + URI_PROTECTED,
                NO_CREDENTIALS, USE_COOKIES,
                HttpServletResponse.SC_UNAUTHORIZED);
        doTestBasic(CONTEXT_PATH_LOGIN + URI_PROTECTED,
                GOOD_CREDENTIALS, USE_COOKIES,
                HttpServletResponse.SC_OK);

        // fail to send the authentication cookie to the other webapp.
        doTestNonLogin(CONTEXT_PATH_NOLOGIN + URI_PROTECTED,
                NO_COOKIES, HttpServletResponse.SC_FORBIDDEN);
    }

    /*
     * Logon to access a protected resource using BASIC authentication,
     * which will establish an SSO session.
     * Then try to access a protected resource in the NonLogin
     * webapp by sending the JSESSIONID from the redirect header.
     * The access request should be rejected because the Basic webapp's
     * sessionID is not valid for any other container.
     */
    @Test
    public void testBasicAccessThenAcceptAuthWithUri() throws Exception {

        setAlwaysUseSession();

        // first, fail to access the protected resource without credentials
        doTestBasic(CONTEXT_PATH_LOGIN + URI_PROTECTED,
                NO_CREDENTIALS, NO_COOKIES,
                HttpServletResponse.SC_UNAUTHORIZED);

        // now, access the protected resource with good credentials
        // to establish the session
        doTestBasic(CONTEXT_PATH_LOGIN + URI_PROTECTED,
                GOOD_CREDENTIALS, NO_COOKIES,
                HttpServletResponse.SC_OK);

        // next, access it again to harvest the session id url parameter
        String forwardParam = "?nextUrl=" + CONTEXT_PATH_LOGIN + URI_PROTECTED;
        doTestBasic(CONTEXT_PATH_LOGIN + URI_PROTECTED + forwardParam,
                GOOD_CREDENTIALS, NO_COOKIES,
                HttpServletResponse.SC_OK);

        // verify the sessionID was encoded in the absolute URL
        String firstEncodedURL = encodedURL;
        assertTrue(firstEncodedURL.contains(ENCODE_SESSION_PARAM));

        // access the protected resource with the encoded url (with session id)
        doTestBasic(firstEncodedURL + forwardParam,
                NO_CREDENTIALS, NO_COOKIES,
                HttpServletResponse.SC_OK);

        // verify the sessionID has not changed
        // verify the SSO sessionID was not encoded
        String secondEncodedURL = encodedURL;
        assertEquals(firstEncodedURL, secondEncodedURL);
        assertFalse(firstEncodedURL.contains(ENCODE_SSOSESSION_PARAM));

        // extract the first container's session ID
        int ix = secondEncodedURL.indexOf(ENCODE_SESSION_PARAM);
        String sessionId = secondEncodedURL.substring(ix);

        // expect to fail using that sessionID in a different container
        doTestNonLogin(CONTEXT_PATH_NOLOGIN + URI_PROTECTED + ";" + sessionId,
                NO_COOKIES, HttpServletResponse.SC_FORBIDDEN);
    }

    /*
     * Logon to access a protected resource using BASIC authentication,
     * which will establish an SSO session.
     * Immediately try to access a protected resource in the NonLogin
     * webapp while providing the SSO session cookie received from the
     * first webapp. This should be successful with SC_OK 200 status.
     *
     * Then, wait long enough for the BASIC session to expire. (The SSO
     * session should remain active because the NonLogin session has
     * not yet expired).
     * Try to access the protected resource again, before the SSO session
     * has expired. This should be successful with SC_OK 200 status.
     *
     * Finally, wait for the non-login session to expire and try again..
     * This should be rejected with SC_FORBIDDEN 403 status.
     *
     * (see bugfix https://bz.apache.org/bugzilla/show_bug.cgi?id=52303)
     *
     * Note: this test should run for ~20 seconds.
     */
    @Test
    public void testBasicExpiredAcceptProtectedWithCookies() throws Exception {

        setRapidSessionTimeoutDetection();

        // begin with a repeat of testBasicLoginAcceptProtectedWithCookies
        doTestBasic(CONTEXT_PATH_LOGIN + URI_PROTECTED,
                NO_CREDENTIALS, USE_COOKIES,
                HttpServletResponse.SC_UNAUTHORIZED);
        doTestBasic(CONTEXT_PATH_LOGIN + URI_PROTECTED,
                GOOD_CREDENTIALS, USE_COOKIES,
                HttpServletResponse.SC_OK);
        doTestNonLogin(CONTEXT_PATH_NOLOGIN + URI_PROTECTED,
                       USE_COOKIES, HttpServletResponse.SC_OK);

        // wait long enough for the BASIC session to expire,
        // but not long enough for the NonLogin session expiry.
        doImminentSessionTimeout(basicContext);

        // this successful NonLogin access should replenish the
        // the individual session expiry time and keep the SSO session alive
        doTestNonLogin(CONTEXT_PATH_NOLOGIN + URI_PROTECTED,
                       USE_COOKIES, HttpServletResponse.SC_OK);

        // wait long enough for the NonLogin session to expire,
        // which will also tear down the SSO session at the same time.
        doImminentSessionTimeout(nonloginContext);

        doTestNonLogin(CONTEXT_PATH_NOLOGIN + URI_PROTECTED, USE_COOKIES,
                HttpServletResponse.SC_FORBIDDEN);
        doTestBasic(CONTEXT_PATH_LOGIN + URI_PROTECTED,
                NO_CREDENTIALS, USE_COOKIES,
                HttpServletResponse.SC_UNAUTHORIZED);

    }


    public void doTestNonLogin(String uri, boolean useCookie,
            int expectedRC) throws Exception {

        Map<String,List<String>> reqHeaders = new HashMap<>();
        Map<String,List<String>> respHeaders = new HashMap<>();

        if (useCookie && (cookies != null)) {
            reqHeaders.put(CLIENT_COOKIE_HEADER, cookies);
        }

        ByteChunk bc = new ByteChunk();
        int rc = getUrl(HTTP_PREFIX + getPort() + uri, bc, reqHeaders,
                respHeaders);

        if (expectedRC != HttpServletResponse.SC_OK) {
            assertEquals(expectedRC, rc);
            assertTrue(bc.getLength() > 0);
        }
        else {
            assertEquals("OK", bc.toString());
        }
}

    private void doTestBasic(String uri,
            TestSSOnonLoginAndBasicAuthenticator.BasicCredentials credentials,
            boolean useCookie, int expectedRC) throws Exception {

        Map<String,List<String>> reqHeaders = new HashMap<>();
        Map<String,List<String>> respHeaders = new HashMap<>();

        if (useCookie && (cookies != null)) {
            reqHeaders.put(CLIENT_COOKIE_HEADER, cookies);
        }
        else {
            if (credentials != null) {
                List<String> auth = new ArrayList<>();
                auth.add(credentials.getCredentials());
                reqHeaders.put(CLIENT_AUTH_HEADER, auth);
            }
        }

        ByteChunk bc = new ByteChunk();
        int rc = getUrl(HTTP_PREFIX + getPort() + uri, bc, reqHeaders,
                respHeaders);

        assertEquals("Unexpected Return Code", expectedRC, rc);
        if (expectedRC != HttpServletResponse.SC_OK) {
            assertTrue(bc.getLength() > 0);
            if (expectedRC == HttpServletResponse.SC_UNAUTHORIZED) {
                // The server should identify the acceptable method(s)
                boolean methodFound = false;
                List<String> authHeaders = respHeaders.get(SERVER_AUTH_HEADER);
                for (String authHeader : authHeaders) {
                    if (authHeader.indexOf(NICE_METHOD) > -1) {
                        methodFound = true;
                        break;
                    }
                }
                assertTrue(methodFound);
            }
        }
        else {
            String thePage = bc.toString();
            assertNotNull(thePage);
            assertTrue(thePage.startsWith("OK"));
            if (useCookie) {
                List<String> newCookies = respHeaders.get(SERVER_COOKIE_HEADER);
                if (newCookies != null) {
                    // harvest cookies whenever the server sends some new ones
                    cookies = newCookies;
                }
            }
            else {
                encodedURL = "";
                final String start = "<a href=\"";
                final String end = "\">";
                int iStart = thePage.indexOf(start);
                int iEnd = 0;
                if (iStart > -1) {
                    iStart += start.length();
                    iEnd = thePage.indexOf(end, iStart);
                    if (iEnd > -1) {
                        encodedURL = thePage.substring(iStart, iEnd);
                    }
                }
            }
        }
    }




    /*
     * setup two webapps for every test
     *
     * note: the super class tearDown method will stop tomcat
     */
    @Override
    public void setUp() throws Exception {

        super.setUp();

        // create a tomcat server using the default in-memory Realm
        tomcat = getTomcatInstance();

        // associate the SingeSignOn Valve before the Contexts
        SingleSignOn sso = new SingleSignOn();
        tomcat.getHost().getPipeline().addValve(sso);

        // add the test user and role to the Realm
        tomcat.addUser(USER, PWD);
        tomcat.addRole(USER, ROLE);

        // setup both NonLogin and Login webapps
        setUpNonLogin();
        setUpLogin();

        tomcat.start();
    }

    @Override
    public void tearDown() throws Exception {

        tomcat.stop();
    }

    private void setUpNonLogin() throws Exception {

        // Must have a real docBase for webapps - just use temp
        nonloginContext = tomcat.addContext(CONTEXT_PATH_NOLOGIN,
                System.getProperty("java.io.tmpdir"));
        nonloginContext.setSessionTimeout(LONG_SESSION_TIMEOUT_MINS);

        // Add protected servlet to the context
        Tomcat.addServlet(nonloginContext, "TesterServlet1",
                new TesterServletEncodeUrl());
        nonloginContext.addServletMappingDecoded(URI_PROTECTED, "TesterServlet1");

        SecurityCollection collection1 = new SecurityCollection();
        collection1.addPatternDecoded(URI_PROTECTED);
        SecurityConstraint sc1 = new SecurityConstraint();
        sc1.addAuthRole(ROLE);
        sc1.addCollection(collection1);
        nonloginContext.addConstraint(sc1);

        // Add unprotected servlet to the context
        Tomcat.addServlet(nonloginContext, "TesterServlet2",
                new TesterServletEncodeUrl());
        nonloginContext.addServletMappingDecoded(URI_PUBLIC, "TesterServlet2");

        SecurityCollection collection2 = new SecurityCollection();
        collection2.addPatternDecoded(URI_PUBLIC);
        SecurityConstraint sc2 = new SecurityConstraint();
        // do not add a role - which signals access permitted without one
        sc2.addCollection(collection2);
        nonloginContext.addConstraint(sc2);

        // Configure the authenticator and inherit the Realm from Engine
        LoginConfig lc = new LoginConfig();
        lc.setAuthMethod("NONE");
        nonloginContext.setLoginConfig(lc);
        AuthenticatorBase nonloginAuthenticator = new NonLoginAuthenticator();
        nonloginContext.getPipeline().addValve(nonloginAuthenticator);
    }

    private void setUpLogin() throws Exception {

        // Must have a real docBase for webapps - just use temp
        basicContext = tomcat.addContext(CONTEXT_PATH_LOGIN,
                System.getProperty("java.io.tmpdir"));
        basicContext.setSessionTimeout(SHORT_SESSION_TIMEOUT_MINS);

        // Add protected servlet to the context
        Tomcat.addServlet(basicContext, "TesterServlet3",
                new TesterServletEncodeUrl());
        basicContext.addServletMappingDecoded(URI_PROTECTED, "TesterServlet3");
        SecurityCollection collection = new SecurityCollection();
        collection.addPatternDecoded(URI_PROTECTED);
        SecurityConstraint sc = new SecurityConstraint();
        sc.addAuthRole(ROLE);
        sc.addCollection(collection);
        basicContext.addConstraint(sc);

        // Add unprotected servlet to the context
        Tomcat.addServlet(basicContext, "TesterServlet4",
                new TesterServletEncodeUrl());
        basicContext.addServletMappingDecoded(URI_PUBLIC, "TesterServlet4");
        SecurityCollection collection2 = new SecurityCollection();
        collection2.addPatternDecoded(URI_PUBLIC);
        SecurityConstraint sc2 = new SecurityConstraint();
        // do not add a role - which signals access permitted without one
        sc2.addCollection(collection2);
        basicContext.addConstraint(sc2);

        // Configure the authenticator and inherit the Realm from Engine
        LoginConfig lc = new LoginConfig();
        lc.setAuthMethod("BASIC");
        basicContext.setLoginConfig(lc);
        AuthenticatorBase basicAuthenticator = new BasicAuthenticator();
        basicContext.getPipeline().addValve(basicAuthenticator);
    }

    /*
     * extract and save the server cookies from the incoming response
     */
    protected void saveCookies(Map<String,List<String>> respHeaders) {

        // we only save the Cookie values, not header prefix
        cookies = respHeaders.get(SERVER_COOKIE_HEADER);
    }

    /*
     * add all saved cookies to the outgoing request
     */
    protected void addCookies(Map<String,List<String>> reqHeaders) {

        if ((cookies != null) && (cookies.size() > 0)) {
            reqHeaders.put(CLIENT_COOKIE_HEADER, cookies);
        }
    }

    /*
     * Force non-default behaviour for both Authenticators.
     * The session id will not be regenerated after authentication,
     * which is less secure but needed for browsers that will not
     * handle cookies.
     */
    private void setAlwaysUseSession() {

        ((AuthenticatorBase) basicContext.getAuthenticator())
                .setAlwaysUseSession(true);
        ((AuthenticatorBase) nonloginContext.getAuthenticator())
                .setAlwaysUseSession(true);
    }

    /*
     * Force faster timeout for an active Container than can
     * be defined in web.xml. By getting to the active Session we
     * can choose seconds instead of minutes.
     * Note: shamelessly cloned from ManagerBase - beware of synch issues
     *       on the underlying sessions.
     */
    private void doImminentSessionTimeout(Context activeContext) {

        ManagerBase manager = (ManagerBase) activeContext.getManager();
        Session[] sessions = manager.findSessions();
        for (int i = 0; i < sessions.length; i++) {
            if (sessions[i]!=null && sessions[i].isValid()) {
                sessions[i].setMaxInactiveInterval(EXTRA_DELAY_SECS);
                // leave it to be expired by the manager
            }
        }


        try {
            Thread.sleep(EXTRA_DELAY_SECS * 1000);
        } catch (InterruptedException ie) {
            // ignored
        }

        // Paranoid verification that active sessions have now gone
        int count = 0;
        sessions = manager.findSessions();
        while (sessions.length != 0 && count < TIMEOUT_WAIT_SECS) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // Ignore
            }
            sessions = manager.findSessions();
            count++;
        }

        sessions = manager.findSessions();
        assertTrue(sessions.length == 0);
    }

    /*
     * Force rapid timeout scanning for both webapps
     * The StandardManager default service cycle time is 10 seconds,
     * with a session expiry scan every 6 cycles.
     */
    private void setRapidSessionTimeoutDetection() {

        ((ManagerBase) basicContext.getManager())
                .setProcessExpiresFrequency(MANAGER_EXPIRE_SESSIONS_FAST);
        ((ManagerBase) nonloginContext.getManager())
                .setProcessExpiresFrequency(MANAGER_EXPIRE_SESSIONS_FAST);
    }

    /*
     * Encapsulate the logic to generate an HTTP header
     * for BASIC Authentication.
     * Note: only used internally, so no need to validate arguments.
     */
    private static final class BasicCredentials {

        private final String method;
        private final String username;
        private final String password;
        private final String credentials;

        private BasicCredentials(String aMethod,
                String aUsername, String aPassword) {
            method = aMethod;
            username = aUsername;
            password = aPassword;
            String userCredentials = username + ":" + password;
            byte[] credentialsBytes =
                    userCredentials.getBytes(StandardCharsets.ISO_8859_1);
            String base64auth = Base64.encodeBase64String(credentialsBytes);
            credentials= method + " " + base64auth;
        }

        private String getCredentials() {
            return credentials;
        }
    }
}
