HTTPS SSH

Alternative NetBeans Authenticator

An Authenticator in Java SE, is a class used to obtain credentials information for network connections when authentication cannot be obtained by other means. Once an Authenticator has been registered in the JRE it will be invoked whenever the JRE has a need for network credentials.

Say your application tries to access http://foo.bar. In this case there may be some authentication involved as either the endpoint itself requires authentication or - even more likely - there's an in-between network proxy which requires authentication. In my experience, 9 times out of 10 when the JRE's Authenticator gets invoked, it is because of a network proxy.

Java SE can seamlessly pass some network proxies (e.g. one that uses NTLM for authentication) but will often fail with proxies that use SPNEGO. In any case, the reasons why Java SE may need to invoke the Authenticator are many, but it is also fully likely that you live in a world where the Authenticator never gets invoked. If so: lucky you!

Normally an Authenticator will prompt the user for such information using a dialog box or other means. This project is no different, but it provides an implementation which is particularly well suited for NetBeans Platform applications.

What is wrong the the standard NetBeans Platform Authenticator ?

The NetBeans Platform indeed registers its own Authenticator, called NbAuthenticator. If it didn't, you would get the default Java SE behaviour which is to fail the request if 'something' is requesting for credentials while a network request is being executed. Therefore the default Java SE doesn't have any UI. NbAuthenticator is a step up from this but still doesn't cut the mustard.

To give you an idea, this is what what you get with plain vanilla NetBeans, i.e. NbAuthenticator:

2016-04-23 14_57_53-Settings.png

The above example shows a NetBeans Platform application where a background task has triggered NetBeans' Authenticator (NbAuthenticator) to go into action and display a dialog to the user. I find this dialog pretty useless for a number of reasons:

  • The dialog doesn't tell the user who is asking for the information and why.
  • The dialog has a tendency to get hidden behind other modal dialog boxes that the application may have open at the time.
  • As network tasks are typically something that happen in the background (in fact they really shouldn't be performed in the foreground) the user will have no clue why he's suddenly seeing this dialog. In short he doesn't know what has triggered the dialog to pop up. I've even seen examples where the user doesn't understand which of the application's he has running on his workstation has initiated the dialog. Remember that the NetBeans Platform application which was actually responsible may even have been minimized at the time. In short the dialog will appear to the user as if it is detached from any application and it will seem unmotivated.

Let's improve on that.

The improved Authenticator (this project!)

With this project the Authenticator is somewhat different. True to how a background task should alert the user that some action is required, it uses the NetBeans Notification feature for this purpose:

2016-04-23 14_46_09-Settings.png

The user can respond to the Notification at his own pace. When the user clicks "Provide credentials" he will then be presented with something like this:

2016-04-24 11_14_05-Settings.png

As can be seen this dialog is a lot more informative than before. It tells the user who is asking for the credentials (in this case it's an intermediary network proxy asking for it) and it also tells him why (in this case something in the application, a background thread, is trying to retrieve http://planetnetbeans.org/rss20.xml). Lastly it tells you the auth scheme at play which probably won't mean much to the average user but is important in a support situation.

As you may have guessed, the screenshot example is really just a basic skeleton NetBeans Platform application which is trying to display the Start Page. It could have been any other network related task though, for example many NetBeans Platform applications will attempt to connect with an Update Center and in doing so they may have to pass an intermediary which requires authentication.

What happens to the background network task ?

You may wonder what will happen to your background network task if there's a need for authentication, i.e. if the Authenticator gets activated.

The Authenticator gets called on the thread that needs it. Most likely this is a background network task. Basically this task will just wait (that thread will block) until the dialog is presented and the credentials are obtained. If the user presses 'Cancel' on the dialog the code will assume the user doesn't want to provide the information and consequently the network operation will immediately fail. The Authenticator will wait up to 60 seconds for the user to respond to the dialog.

If the network task has a timeout on it, it may of course time out before the user has had a chance to input the information. Therefore you should think about the manual input scenario when you set timeouts for network tasks in an NetBeans Platform application. For example, the default timeout for Auto Update tasks in plain vanilla NB is 30 seconds, so it actually allows very little time for the user to manually input credentials in the dialog that the Authenticator will present.

Worth mentioning

The username and password you type in will be stored and then re-used for another time. The username is stored using classic NetBeans Preferences. The password is stored using NetBeans Keyring API. The information is stored under a key and this key is the realm which is being accessed. (think of the realm as the network endpoint)

Next time the same realm is being accessed the username and password field will already be filled out with values so all the user has to do is to press OK.

(this feature actually also existed in the NetBeans ditto, I just improved a bit on it in terms of making sure the realm key is a string that can be used as a NbPreferences key .... it would fail if the 'realm' was a textual IP address which is very often the case)

Workaround for JDK-/8068184/

The Authenticator has a build-in workaround for JDK-/8068184/. Without the workaround, NetBeans may freeze.

Prerequisites and installation

Plain vanilla NetBeans doesn't allow you to provide your own Authenticator. However the NetBeansProxy2 plugin provides this advantage as well as many others. In other words: Your application must be using NetBeansProxy2.

This module will register a service implementation of Authenticator in NetBeans' Global Lookup. NetBeansProxy2 module will look for such an implementation and use it if it exists. Voila! If NetBeansProxy2 doesn't find such an implementation it will just give you the default NetBeans one, called NbAuthenticator.

But you're not quite there yet. You also have to make sure to tell NB never to use its own Authenticator. This is important to do as there's a race during startup and we cannot tell if our ProxySelector gets installed before or after NB attemps to install its own Authenticator. Luckily in standard NB, there's a variable that controls if we want to install the NB Authenticator or not. This is the USE_Authentication variable in the Bundle for package org.netbeans.core. This variable should be set to false.

For those using the plugin from the IDE: If you are using an English language locale (check the About window in the IDE) then you don't need to do anything. If not, then you need to add --locale en to the netbeans_default_options variable in the IDE's config file.

For those using this module as part of their NB Platform application: In your branding you'll need to set USE_Authentication to false in Bundle in package org.netbeans.core.

Troubleshooting

Here's how to add some debugging.

  • NetBeans IDE:

If you are using this project as a plugin in an instance of NetBeans IDE: Go the the etc directory of the NetBeans install directory. Edit the netbeans.conf file and add this option to netbeans_default_options variable:

-J-Dorg.phansson.netbeans.net.nbnetauthenticator.level=FINEST
  • NetBeans Platform application:

If you are using this project as a module in a NetBeans Platform application: Go the the etc directory of the your app's install directory. Edit the <appname>.conf file and add this option to default_options variable:

-J-Dorg.phansson.netbeans.net.nbnetauthenticator.level=FINEST

License

Apache License, Version 2.0

I claim no copyright on anything in this project.