I agree, the downcast here is ugly.

A more clean solution is to have the provider be a callback that we ask for data from:

  c = credentialsProvider.getCredentials(uri, "Username", "Password");
  username = c.get(0);
  passsword = c.get(1);

Or something like that.  The idea being that the protocol here provides prompts to the provider letting it know what it needs, and the provider returns that data in the credentials object.

To be safe we probably don't want to pass in username/password as strings, but instead have a prompt type object that is abstract, with two concrete instances for USERNAME and PASSWORD that are standard singletons.  LIkewise we could do a PASSPHRASE standard singleton to decrypt an SSH key.