JDK-6956762 : Static Caching of BasicAuthentication in AuthCache does not work as expected
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.net
  • Affected Version: 6u10
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2010-05-28
  • Updated: 2012-03-20
  • Resolved: 2010-08-17
Related Reports
Duplicate :  
Description
FULL PRODUCT VERSION :
java version "1.6.0_20"
Java(TM) SE Runtime Environment (build 1.6.0_20-b02)
Java HotSpot(TM) Client VM (build 16.3-b01, mixed mode, sharing)



ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]

A DESCRIPTION OF THE PROBLEM :
When opening a HttpURLConnection to a server requiring BasicAuthentication I provide a default Authenticator with correct User and Password.
When I then set a new Authenticator with INCORRECT User and Password pair, I expect the connection to fail, but the Connection still succeeds.

This is because there is the sun.net.www.protocol.http.AuthCacheValue which caches successful authentication, but the HttpURLConnection will not invalidate them.

The problem arises with an application where the User logs in to the app with the credentials of the Web Server running the backend logic. When the next user logs on with a wrong password, the connection still succeeds!



STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the example code.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Expected result would be:

Connection succeded for correct password. And then
Connection failed for WRONG password.

ACTUAL -
Actual Result was:

Connection succeded for correct password. And then
Connection still succeeded for WRONG password.


ERROR MESSAGES/STACK TRACES THAT OCCUR :
No error messages.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
package testapp1;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.PasswordAuthentication;
import java.net.URL;

/**
 * Test application showing the problem with the AuthCacheImpl static caching.
 */
public class Main {

    public static final String testUrl = "http://localhost:8080/"
            + "basicAuthenticationProtectedTestServer?q=XXXXX";

    public static void main(String[] args) {

        // Set authentication to correct pwd
        Authenticator.setDefault(new Authenticator() {
            public PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication("admin", "admin".toCharArray());
            }
        });

        System.out.println("Result 1 - should be true:" + checkConn());

        // Set authentication to wrong pwd
        Authenticator.setDefault(new Authenticator() {
            public PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication("admin", "wrongpasswd".toCharArray());
            }
        });

        System.out.println("Result 2 - should be false:" + checkConn());
    }

    /** checkConn tries to open HttpURLConnection to a basicAuthentication protected
     * server to get the HTTP Status.
     * @return true if connection succeeded, false if error (eg. 401 Unauthorized)
     */
    private static boolean checkConn() {

        BufferedReader inStream = null;
        try {
            URL connectionURL = new URL(testUrl);
            HttpURLConnection conn = (HttpURLConnection) connectionURL.openConnection();
            conn.setUseCaches(false); // disable caches

            // Send request to get http result code
            new BufferedReader(new InputStreamReader(conn.getInputStream()));

            String httpStatus = conn.getHeaderField(null); // HTTP-Status from header
            System.out.println("status:" + httpStatus);

            if (httpStatus == null) {
                return false; // no conn
            } else if (httpStatus.endsWith("200 OK")) {
                return true; // connect was OK
            } else if (httpStatus.endsWith("401 Unauthorized")) {
                return false; // wrong user/password
            } else {
                return false;
            }
        } catch (IOException iex) {
            System.out.println("Error.");
            return false; // so connection doesnt work, return false
        } finally {
            try {
                inStream.close();
            } catch (Exception ex) {}
        }
    }
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
I currently disable the Authentication Cache by executing

sun.net.www.protocol.http.AuthCacheValue.setAuthCache(
                    new sun.net.www.protocol.http.AuthCacheImpl());

before any http access.

This gives me compiler warnings because of the Proprietary API thing, but it works.