How to set username and password using RESTEasy client builder? - java

I have a url which needs authentication (like a browser pop up appears asking username and password.)
Generally, we can use the following format to achieve this:
http://username:password#url.com
Using RESTEasy client builder
Client client = ClientBuilder.newClient();
WebTarget target = client.target("http://url.com");
How to achieve it without having to construct the http://username:password#url.com myself? I've seen if there are any methods which I could use to set it with no luck. Also I'm not sure how these credentials are passed, headers, cookies etc..

Looks like Basic Authentication. If that's the case, you just need to set the Authorization header to Basic base64encode(username:password).
For example:
String credentials = "username:password"
String base64encoded = Base64.getEncoder().encodeToString(credentials.getBytes());
Response response = target.request()
.header(HttpHeaders.AUTHORIZATION, "Basic " + base64encoded)....
The Base64 class I used is from Java 8. If you're not using Java 8, there are libraries that have Base64 support. Prior to Java 8, there's a com.sun internal Base64 class, but it's advised not to use those.
If you just want to run a quick test (and don't have Java 8 or don't want to go looking for a lib), you can go to this site and just type in your username:password and encode it, then just copy and paste to your code.
For example:
base64encode(username:password) == dXNlcm5hbWU6cGFzc3dvcmQ=

Related

Kubernetes Java API does not use username password supplied

This is in regards to version 0.2 of the Kubernetes Java client. I'm guessing the way to use basic authentication in the Java API is to do this
ApiClient client = Config.fromUserPassword( "https://....:6443", "user", "password", false );
Configuration.setDefaultApiClient( client );
CoreV1Api api = new CoreV1Api();
// Make api call like
api.listNode(...)
However the above code always returns 403 Forbidden. From the response message, it doesn't look like the user/pass is being used in the request.
{"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"nodes is forbidden: User \"system:anonymous\" cannot list nodes at the cluster scope","reason":"Forbidden","details":{"kind":"nodes"},"code":403}
I also debugged through the code a bit and I may be answering my own question but it looks like in CoreV1Api's methods, it never add basic auth as an authentication method and only uses BearerToken. Is basic auth supported or should I be using another API class?
Many kubernetes clusters do not set up basic auth, only bearer token auth. Are you sure your cluster configured basic authentication?
https://kubernetes.io/docs/admin/authentication/#static-password-file
Answering my own question but it doesn't look like the current version of the client actually executes the user/pass authentication. BearerToken is working however.
The java client ignores the HttpBasicAuth object, but if you use the ApiKeyAuth object and set the key prefix to "Basic" and the API key to the base64 encoded credentials, it will work.
For example:
String credentials= new String(Base64.getEncoder().encode("user:password".getBytes()));
ApiClient defaultClient = Configuration.getDefaultApiClient();
defaultClient.setBasePath("https://256.256.256.256");
ApiKeyAuth fakeBearerToken = (ApiKeyAuth) defaultClient.getAuthentication("BearerToken");
fakeBearerToken.setApiKey(credentials);
fakeBearerToken.setApiKeyPrefix("Basic");
This works because the kubernetes client will simply concatenate the API key prefix with the prefix, and put the result in the "Authorization" header.

Url encoding issue with Jersey Client

I need to make a service call such as this:
http://myservice.com/path?var1=value1&var2=value2
The issue I have is value1 and value2 ends up getting encoded, and this makes the service call fail. For example, value1 is something like "a=b&b=c;2&&="... it contains special characters, basically.
I am guessing that this is an issue for the service to fix - to properly handle decoding encoded characters, which I do not think it is currently doing.
Here is a sample of how I am making these requests:
WebTarget target = client.target("http://test.com")
.path("path1")
.queryParam("var1", var1);
Builder builder = target.request();
...
What's puzzling to me is that if I make the same request just using Chrome, everything works. So that makes me to believe that I should have some way with the Jersey API of "disabling" the encoding.
Only way I have found so far to use "raw" Url is to use URI.
So call like this
URI uri = URI.create("http://localhost/~Common~0#/edit?vadf&&sfs&&fdsfd=fs&fsd");
WebTarget target = client.target(uri);
You get request url
1 > GET http://localhost/~Common~0#/edit?vadf&&sfs&&fdsfd=fs&fsd
Everything else I tried resulted in encoding special characters.

Open an authenticated image served by django from java using Apache http client

I Am serving an authenticated image using django. The image is behind a view which require login, and in the end I have to check more things than just the authentication.
Because of a reason to complicated to explain here, I cannot use the real url to the image, but I Am serving it with a custom url leading to the authenticated view.
From java the image must be reachable, to save or display. For this part I use Apache httpclient.
In Apacahe I tried a lot of things (every example and combination of examples...) but can't seem to get it working.
For other parts of the webapp I use django-rest-framwork, which I succesfully connected to from java (and c and curl).
I use the login_reuired decorator in django, which makes the attempt to get to the url redirect to a login page first.
Trying the link and the login in a webviewer, I see the 200 code (OK) in the server console.
Trying the link with the httpclient, I get a 302 Found in the console.... (looking up 302, it means a redirect..)
this is what I do in django:
in urls.py:
url(r'^photolink/(?P<filename>.*)$', 'myapp.views.photolink',name='photolink'),
in views.py:
import mimetypes
import os
#login_required
def photolink(request, filename):
# from the filename I get the image object, for this question not interesting
# there is a good reason for this complicated way to reach a photo, but not the point here
filename_photo = some_image_object.url
base_filename=os.path.basename(filename_photo)
# than this is the real path and filename to the photo:
path_filename=os.path.join(settings.MEDIA_ROOT,'photos',mac,base_filename)
mime = mimetypes.guess_type(filename_photot)[0]
logger.debug("mimetype response = %s" % mime)
image_data = open(path_filename, 'rb').read()
return HttpResponse(image_data, mimetype=mime)
by the way, if i get this working i need another decorator to pass some other tests....
but i first need to get this thing working....
for now it's not a secured url.... plain http.
in java i tried a lot of things... using apache's httpclient 4.2.1
proxy, cookies, authentication negociation, with follow redirects... and so on...
Am I overlooking some basic thing here?...
it seems the login of the website client is not suitable for automated login...
so the problem can be in my code in django....or in the java code....
In the end the problem was, using HTTP authorization.
Which is not by default used in the login_required decorator.
adding a custom decorator that checks for HTTP authorization did the trick:
see this example: http://djangosnippets.org/snippets/243/

Simple Kerberos client in Java?

Applications such a Google's Chrome and IE can transparently handle Kerberos authentication; however I can not find a "simple" Java solution to match this transparency. All of the solutions I have found require the presence of a krb5.conf file and a login.conf file which nether of the above apps seem to require.
What is the best way to build a Java application with Kerberos SSO capabilities that just work?
[update]: to be clear I need a CLIENT side solution for creating tickets not validating them. Also, it seems that SPNEGO is the default "wrapper" protocol that will eventually delegate to Kerberos but I need to be able to handle the SPNEGO protocol as well.
There is now a simple solution for this using the Apache HTTP Components Client 4.5 or greater. This is still marked as experimental in 4.5 so your milage may vary, but this is working fine for me in an enterprise context.
In addition to the HC 4.5 client jars you will need to have the httpclient-win, jna and jna-platform jars on your classpath, as provided with http-component-client. You then construct a Kerberos enabled HC-client as follows:
CloseableHttpClient httpclient = WinHttpClients.createDefault();
Or using the builder:
HttpClientBuilder clientBuilder = WinHttpClients.custom();
Which can then be customised as required before building the client:
CloseableHttpClient client = clientBuilder.build();
This solution works without any external configuration, and most importantly solves the issue where the in-built JRE mechanism breaks for users with local Admin rights on Windows 7+. This is possible because the Kerberos ticket is being retrieved directly from the SSPI API via JNA, rather than going through the GSSAPI provided by the JRE.
Example code from the http-components team
This was all made possible by the good work of Daniel Doubrovkine Timothy Wall
and Ryan McKinley
Adding to David Roussels answer on url specific http based kerberos authentication:-
The reason why your code works is because your target SPN(server side principal) is configured to with HTTP/serverhostname.realm.com#DOMAIN.COM. In that case it will work because you are not explicitly setting the token. URLConnection internally sets a token with that SPN
1 Perform steps(from my previous answer) to get a subject
2 Use gss api init sec context to generate a context token. There are numerous tutorials out there for this step
3 Base 64 encode the token
4 Attach the token to urlconnection:-
URL url = new URL("http://myhost/myapp")
HttpURLConnection urlConn = (HttpURLConnection)url.openConnection(); =
urlConn.setRequestProperty("Authorization", "Negotiate " + encodedToken);
5 Implement a priviledged action:-
//this internally calls the getInputStream
public class PrivilegedGetInputStream implements PrivilegedExceptionAction<InputStream>
6 Wrap the whole thing in Subject.doAs
//use prev answer instructions to get subject
Subject.doAs(subject, new PrivilegedGetInputStream(urlConnection)
Oracle has an example using Java's SaslClient. I'm not a Java programmer, but when I pointed this out once to someone who is, they were able to make it work pretty quickly. It may still require a "conf" file somewhere (n.b. Kerberos uses environment variables, often starting with KRB5_, to know where to look for such files). Also note that Kerberos itself does not include a transport of any kind--your app needs to know how to send and receive the Kerberos payloads the way the server expects (and this is different depending on the server you are trying to authenticate with).
Edit: you edited your question, so here's a link related to SPNEGO in Java which might be of some use:
http://download.oracle.com/javase/6/docs/technotes/guides/security/jgss/lab/part5.html
You don't actually need to do anything. In Java 6, on a Windows client machine you can do this:
new URL("http://myhost/myapp").openStream();
And negotiate authentication just works. At least it does for me. And the server I tested on only supports Negotiate, not NTLM auth.
Ok if you want to avoid using a login.conf file you need to code differently:-
//define your own configuration
import javax.security.auth.login.Configuration;
public class CustomLoginConfiguration extends Configuration
//pass certain parameters to its constructor
//define an config entry
import javax.security.auth.login.AppConfigurationEntry;
private AppConfigurationEntry configEntry;
//define a map of params you wish to pass and fill them up
//the map contains entries similar to one you have in login.conf
Map<String, String> params = new HashMap<String, String>();
//define the configuration
configEntry = new AppConfigurationEntry(
"com.sun.security.auth.module.Krb5LoginModule",
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, params);
//implement getappconfig method
public AppConfigurationEntry[] getAppConfigurationEntry() {
return new AppConfigurationEntry[] { configEntry };
}
Now once you are done with this definition you can use this in you use this to fetch tickets from kdc
//get ticket in login context
LoginContext lc = null;
lc = new LoginContext("lc", null, callback, new CustomLoginConfiguration(argumentlist));
lc.login();
Now from here on you can fetch jaas subject and can basically do a ton of authentication stuff.
In case you need further pointers just leave a comment.
You can use system properties instead of config files to specify the KDC hostname and service name, but those things (at least) are mandatory....
Waffle will actually give you the information you need to set most of the properties, even if it won't get you a ticket. Look at the WindowsAuthProviderImpl class (the Waffle.chm help file shows the API).
I use JAAS do obtain a service ticket from Active Directory in two steps:
Use Krb5LoginModule to retrieve the cached TGT and add it to the Subject.
Use the Subject and GSS-API to retrieve a service ticket from the KDC.
There's a lot of good information and example code at The Java Way of Active Directory.
I created a small tool to simplify connecting with httpclient to kerberos, you might want to give it a try.
https://github.com/DovAmir/httpclientAuthHelper
DefaultHttpClient httpclient = new DefaultHttpClient();
AuthUtils.securityLogging(SecurityLogType.KERBEROS,true);
CredentialsUtils.setKerberosCredentials(client, new UsernamePasswordCredentials("xxx", "xxx"), "domain", "kdc");
client.executeMethod(httpget);
Use WAFFLE
Here's a good blog post on having a java client to use with Kerberos
http://sachithdhanushka.blogspot.com/2014/02/kerberos-java-client-configuration.html

Get parameter from curl command in REST web serivce

I want to get username and password from curl command in REST web service using Plain Java Class.
My java class is
#GET
public Response check(String username,String password)
{
authenticate.....
}
I use Netbean IDE with jersey framework. I created web service in POJO java class.
Do anyone know how to get username and password in web service java class?
My curl command is like :
curl -u username:password http://localhost:8080/project/resources
If this is building on the code from your question here, then getting the username is a matter of adding a new property to the resource annotated with #Context of type javax.ws.rs.core.SecurityContext (let's call it securityContext). Then you can access the username like this:
String username = securityContext.getUserPrincipal().getName();
The password is not available through this API though. This approach will only work if the user has already been authenticated by the container. To get at the password, the property would need to be of type javax.ws.rs.core.HttpHeaders (let's call it httpHeaders). Using this object, you'd have to call
String authHeader = httpHeaders.getRequestHeader("Authorization").get(0);
Using the curl command you listed would default to using HTTP basic authentication, giving you the username and password in a base64 encoded string consisting of username:password. To get those values you would need to parse, base64 decode, and parse again. The curl command you provided would add the following header to the request:
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
In the code snippet I provided before, authHeader would have the value
Basic dXNlcm5hbWU6cGFzc3dvc.mQ=
Getting the username and password would be like so
String[] pair = base64decode(authHeader.split(" ")[1]).split(":");
In that code substitute base64decode with your base64 decoding library of choice. After this call the username would be in pair[0] and the password would be in pair[1]. Note that all of this code is lacking null and boundary checks as well as exception handling that production code would require. It also only supports basic authentication. If you needed to support other authentication methods you would need to handle whatever decoding and parsing that method requires.
It seems to me that JAX-RS is geared more towards using the SecurityContext approach and relying on the container to authenticate the request, so understand all of the caveats with using the HttpHeaders approach.

Categories