JDK-6578647 : Undefined requesting URL in "java.net.Authenticator.getPasswordAuthentication()"
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.net
  • Affected Version: 6
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2007-07-10
  • Updated: 2016-11-21
  • Resolved: 2009-06-22
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7
7 b62Fixed
Related Reports
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
jdk1.6.0_01

A DESCRIPTION OF THE PROBLEM :
When I use "Negotiate"(Kerberos) authentication and I extend "java.net.Authenticator" class and redefine "getPasswordAuthentication()" method, I get NULL value from "getRequestingURL()" and "getRequestingHost()" method(these methods are defined in java.net.Authenticator class). When I use "Basic" authentication - all work properly(these methods return correct value).
I use HttpURLConnection class for both authentication schema.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
package my.kerberos.test;

import java.net.Authenticator;
import java.net.PasswordAuthentication;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * This class is used as common point for standard java HttpURLConnection authentication.
 * It uses singleton pattern and do "Authenticator.setDefault(this)" in its constructor.
 * So it is default authenticator for all HttpURLConnection.
 *
 * @author Andrey Krasnov
 *
 */
public class BaseAuthenticator extends Authenticator {

	private Log log = LogFactory.getLog(this.getClass());
	
	private final static BaseAuthenticator instance = new BaseAuthenticator();
	static {
		Authenticator.setDefault(instance);
	}
	
	private Map<String, Account> urlMap = new HashMap<String, Account>();
	private Map<String, Account> hostMap = new HashMap<String, Account>();
	
	/**
	 * Register credentials for specified url
	 * @param url
	 * @param login
	 * @param password
	 * @return the previous value associated with key, or null if there was no mapping for key.
	 * (A null return can also indicate that the map previously associated null with key,
	 * if the implementation supports null values.)
	 */
	public static synchronized Account registerUrl(String url, String login, String password){
		if(url == null || login == null || password == null){
			throw new IllegalArgumentException("All parameters should be specified");
		}
		return instance.urlMap.put(url, new Account(login, password));
	}
	
	/**
	 * Register credentials for specified host
	 * @param host
	 * @param login
	 * @param password
	 * @return the previous value associated with key, or null if there was no mapping for key.
	 * (A null return can also indicate that the map previously associated null with key,
	 * if the implementation supports null values.)
	 */
	public static synchronized Account registerHost(String host, String login, String password){
		if(host == null || login == null || password == null){
			throw new IllegalArgumentException("All parameters should be specified");
		}
		return instance.hostMap.put(host, new Account(login, password));
	}
	
	/**
	 * Clear all registered credentials
	 */
	public static synchronized void reset(){
		instance.urlMap.clear();
		instance.hostMap.clear();
	}
	
	protected PasswordAuthentication getPasswordAuthentication() {
		
		log.debug("Authentication schema for \""+getRequestingURL()+"\": " + getRequestingScheme());
		
		Account account = urlMap.get(getRequestingURL());
		if( account != null ){
			return new PasswordAuthentication(account.login, account.password);
		}
		else if( (account = hostMap.get(getRequestingHost())) != null ){
			return new PasswordAuthentication(account.login, account.password);
		}
		
		return null;
	}
	
	/**
	 * This class encapsulates pair with login and password
	 *	@author Andrey Krasnov
	 *
	 */
	private static class Account {
		public final String login;
		public final char[] password;
		
		public Account(String login, String password){
			this.login = login;
			this.password = password.toCharArray();
		}
		
		public String toString(){
			return "[login: "+login+", password: ******]";
		}
	}
	
}

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

Comments
EVALUATION http://hg.openjdk.java.net/jdk7/tl/jdk/rev/8f405b65ddac
09-06-2009

EVALUATION Fixed, various getXXX() methods now return useful info.
09-06-2009

EVALUATION This violates the current Authenticator specification. The following methods are specified to possibly return null: getRequestingSite and getRequestingHost but the following methods are not: getRequestingURL, getRequestorType, getRequestingScheme, getRequestingPrompt, getRequestingProtocol and getRequestingPort. There seems to be a general specification issue with java.net.Authenticator. For example, if the authenticator was called by requestPasswordAuthentication(InetAddress addr, int port, String protocol, String prompt, String scheme) what will be returned from getRequestingURL and getRequestorType?
31-07-2007

EVALUATION For Kerberos authentication, the username and password is for the realm and there's only one realm. Therefore, web server info such as host/port/URL are all ignored when retrieving authenticate info through the Authenticator class.
31-07-2007