I am currently working on authorizing the Qlik API proxy using Java. To do this I have to navigate through several redirects and then open a WebSocket. I have a version of C# that completes the task but need to port it over to java.
In Java, I am able to complete the redirects and obtain the session key for the WebSocket but I cannot seem to configure the NTLM credentials correctly for the WebSocket to accept them.
I am currently using apache HTTP client v 4.5. And nv-websocket-client for the WebSocket.
https://hc.apache.org/httpcomponents-client-4.5.x/index.html
https://github.com/TakahikoKawasaki/nv-websocket-client
In Java, I made a credentials object and set the NTLM credentials for the https request.
The issue is that in C# the call to the WebSocket seems to be automatically picking up the request.UseDefaultCredentials = true;.
My question is there a way to get this same functionality in Java or a library that supports the functions. Or if someone has used Java to complete this task any insight would be great.
I have tried configuring the headers for the WebSocket request to mirror the NTLM request, but I am not really sure where to go from here. Below is the c# set up I am looking to complete the same task.
HttpWebRequest request = (HttpWebRequest) WebRequest.Create(URI);
request.Headers = headers;
request.Method = "GET";
request.Accept = "application/json";
request.Credentials = true;
System.Net.CredentialCache.DefaultNetworkCredentials;
request.UseDefaultCredentials = true;
request.AllowAutoRedirect = false;
request.CookieContainer = new CookieContainer();
I am currently receiving:
webSocketFrame(FIN=1,RSV1=0,RSV2=0,RSV3=0,Opcode=TEXT,Length=226,Payload="
{"jsonrpc":"2.0",
"method":"OnAuthenticationInformation",
"params":{"loginUri":baseurl+port"/internal_windows_authentication/?
targetId=ID returned here",
"mustAuthenticate":true}}")
The response I am looking for it:
webSocketFrame(FIN=1,RSV1=0,RSV2=0,RSV3=0,Opcode=TEXT,Length=226,Payload="
{"jsonrpc":"2.0",
"method":"OnAuthenticationInformation",
"params":{"loginUri":baseurl+port"/internal_windows_authentication/?
targetId=ID returned here ",
"mustAuthenticate":false}}") <---- the boolean flag is changed
Related
Can some one help me to setup Oauth 2 Authorisation server Vert.x (3.3.0).I dont find any documentation related to it.
I found vertx-auth-oauth2 this vert.x module but I guess it will be useful if Authorisation server is different
e.g
The following code snippet is from vert.x documentation
OAuth2Auth oauth2 = OAuth2Auth.create(vertx, OAuth2FlowType.AUTH_CODE, new OAuth2ClientOptions()
.setClientID("YOUR_CLIENT_ID")
.setClientSecret("YOUR_CLIENT_SECRET")
.setSite("https://github.com/login")
.setTokenPath("/oauth/access_token")
.setAuthorizationPath("/oauth/authorize")
);
// when there is a need to access a protected resource or call a protected method,
// call the authZ url for a challenge
String authorization_uri = oauth2.authorizeURL(new JsonObject()
.put("redirect_uri", "http://localhost:8080/callback")
.put("scope", "notifications")
.put("state", "3(#0/!~"));
// when working with web application use the above string as a redirect url
// in this case GitHub will call you back in the callback uri one should now complete the handshake as:
String code = "xxxxxxxxxxxxxxxxxxxxxxxx"; // the code is provided as a url parameter by github callback call
oauth2.getToken(new JsonObject().put("code", code).put("redirect_uri", "http://localhost:8080/callback"), res -> {
if (res.failed()) {
// error, the code provided is not valid
} else {
// save the token and continue...
}
});
It is using Github as Authorisation server.I am curious to know how to implement Authorisation server in vert.x ,i know spring security provides this feature i.e Oauth2Server and OAuth2Client.
Vert.x OAuth2 is just a OAuth2Client, there is no server implementation so you cannot get it from the Vert.x Project itself.
Vert.x OAuth2 supports the following flows:
Authorization Code Flow (for apps with servers that can store persistent information).
Password Credentials Flow (when previous flow can’t be used or during development).
Client Credentials Flow (the client can request an access token using only its client credentials)
I have a working application for managing HDFS using WebHDFS.
I need to be able to do this on a Kerberos secured cluster.
The problem is, that there is no library or extension to negotiate the ticket for my app, I only have a basic HTTP client.
Would it be possible to create a Java service which would handle the ticket exchange and once it gets the Service ticket to just pass it to the app for use in a HTTP request?
In other words, my app would ask the Java service to negotiate the tickets and it would return the Service ticket back to my app in a string or raw string and the app would just attach it to the HTTP request?
EDIT: Is there a similar elegant solution like #SamsonScharfrichter described for HTTPfs? (To my knowledge, it does not support delegation tokens)
EDIT2: Hi guys, I am still completly lost. Im trying to figure out the Hadoop-auth client without any luck. Could you please help me out again? I already spent hours reading upon it without luck.
The examples say to do this:
* // establishing an initial connection
*
* URL url = new URL("http://foo:8080/bar");
* AuthenticatedURL.Token token = new AuthenticatedURL.Token();
* AuthenticatedURL aUrl = new AuthenticatedURL();
* HttpURLConnection conn = new AuthenticatedURL(url, token).openConnection();
* ....
* // use the 'conn' instance
* ....
Im lost already here. What initial connection do I need? How can
new AuthenticatedURL(url, token).openConnection();
take two parameters? there is no constructor for such a case. (im getting error because of this). Shouldnt a principal be somewhere specified? It is probably not going to be this easy.
URL url = new URL("http://<host>:14000/webhdfs/v1/?op=liststatus");
AuthenticatedURL.Token token = new AuthenticatedURL.Token();
HttpURLConnection conn = new AuthenticatedURL(url, token).openConnection(url, token);
Using Java code plus the Hadoop Java API to open a Kerberized session, get the Delegation Token for the session, and pass that Token to the other app -- as suggested by #tellisnz -- has a drawback: the Java API requires quite a lot of dependencies (i.e. a lot of JARs, plus Hadoop native libraries). If you run you app on Windows, in particular, it will be a tough ride.
Another option is to use Java code plus WebHDFS to run a single SPNEGOed query and GET the Delegation Token, then pass it to the other app -- that option requires absolutely no Hadoop library on your server. The barebones version would be sthg like
URL urlGetToken = new URL("http://<host>:<port>/webhdfs/v1/?op=GETDELEGATIONTOKEN") ;
HttpURLConnection cnxGetToken =(HttpURLConnection) urlGetToken.openConnection() ;
BufferedReader httpMessage = new BufferedReader( new InputStreamReader(cnxGetToken.getInputStream()), 1024) ;
Pattern regexHasToken =Pattern.compile("urlString[\": ]+(.[^\" ]+)") ;
String httpMessageLine ;
while ( (httpMessageLine =httpMessage.readLine()) != null)
{ Matcher regexToken =regexHasToken.matcher(httpMessageLine) ;
if (regexToken.find())
{ System.out.println("Use that template: http://<Host>:<Port>/webhdfs/v1%AbsPath%?delegation=" +regexToken.group(1) +"&op=...") ; }
}
httpMessage.close() ;
That's what I use to access HDFS from a Windows Powershell script (or even an Excel macro). Caveat: with Windows you have to create your Kerberos TGT on the fly, by passing to the JVM a JAAS config pointing to the appropriate keytab file. But that caveat also applies to the Java API, anyway.
You could take a look at the hadoop-auth client and create a service which does the first connection, then you might be able to grab the 'Authorization' and 'X-Hadoop-Delegation-Token' headers and cookie from it and add it to your basic client's requests.
First you'll need to have either used kinit to authenticate your user for application before running. Otherwise, you're going to have to do a JAAS login for your user, this tutorial provides a pretty good overview on how to do that.
Then, to do the login to WebHDFS/HttpFS, we'll need to do something like:
URL url = new URL("http://youhost:8080/your-kerberised-resource");
AuthenticatedURL.Token token = new AuthenticatedURL.Token();
HttpURLConnection conn = new AuthenticatedURL().openConnection(url, token);
String authorizationTokenString = conn.getRequestProperty("Authorization");
String delegationToken = conn.getRequestProperty("X-Hadoop-Delegation-Token");
...
// do what you have to to get your basic client connection
...
myBasicClientConnection.setRequestProperty("Authorization", authorizationTokenString);
myBasicClientConnection.setRequestProperty("Cookie", "hadoop.auth=" + token.toString());
myBasicClientConnection.setRequestProperty("X-Hadoop-Delegation-Token", delegationToken);
I have a dot net application that call a java web service. I am trying to implement authentication by passing credentials to the java service. Here is the dot net code setting the credentials. How can I get these credentials in my java application? They aren't set in the headers...
System.Net.NetworkCredential serviceCredentials = new NetworkCredential("user", "pass");
serviceInstance.Credentials = serviceCredentials;
serviceInstance is an instance of SoapHttpClientProtocol.
I've tried injecting the WebServiceContext like so
#Resource
WebServiceContext wsctx;
and pulling the crentials from the headers but they aren't there.
You are not passing the credentials to your service the correct way. In order to get the Authorize http request header do the following:
// Create the network credentials and assign
// them to the service credentials
NetworkCredential netCredential = new NetworkCredential("user", "pass");
Uri uri = new Uri(serviceInstance.Url);
ICredentials credentials = netCredential.GetCredential(uri, "Basic");
serviceInstance.Credentials = credentials;
// Be sure to set PreAuthenticate to true or else
// authentication will not be sent.
serviceInstance.PreAuthenticate = true;
Note: Be sure to set PreAuthenticate to true or else authentication will not be sent.
see this article for more information.
I had to dig-up some old code for this one :)
Update:
After inspecting the request/response headers using fiddler as suggested in the comments below a WWW-Authenticate header was missing at the Java Web Service side.
A more elegant way of implementing "JAX-WS Basic authentication" can be found in this article here using a SoapHeaderInterceptor (Apache CXF Interceptors)
As the title states, we're looking for a way to access a .NET 3.5 Web service that is behind a Windows integrated (NTLM) authentication.
We've searched the internets and this forum this entire week, and we've yet to find a solution to this problem.
We've tried, DefaultHttpConnections, different variations of HttpPost, HttpGet etc.
However we try to authenticate ourselves we run into these:
SSLHandshakeException
or
Authentication scheme ntlm not supported
Authentication error: Unable to respond to any of these challenges:
ntlm=WWW-Authenticate: NTLM, negotiate=WWW-Authenticate: Negotiate
The IIS authentication is set as follows:
The page we're trying to access is an .aspx in a subfolder to the default site, and we dont have previliges and neither is it safe to change the authentication to the default site.
I know many others out there in the internets has similar problems.
And also, the app we're developing is not supposed to use web-views.
Any constructive pointers about how to solve this will be highly appreciated. Thanks in advance.
UPDATE: We have now changed the service to perform both basic and ntlm authentication.
When we run the code below to a localhost test-server we get the proper response, the localhost does not have any sort of authentication mechanism. The response as follows:
<soap:Body>
<FooResponse xmlns="uri:FlexAPI">
<FooResult>
<typeFooBar>
<FooNumber>4545</FooNumber>
<BarNumber>1</BarNumber>
</typeFooBar>
</FooResult>
</FooResponse>
</soap:Body>
However, When we run the code below on our authenticated server we get this.
org.xmlpull.v1.XmlPullParserException: expected:
START_TAG {http://schemas.xmlsoap.org/soap/envelope/}Envelope
(position:START_TAG #2:44 in java.io.InputStreamReader#4054b398)
SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
request.addProperty("Foo", Bar.getText().toString());
request.addProperty("Foo", Bar.getText().toString());
request.addProperty("Foo", Bar() );
request.addProperty("Foo", Bar.getText().toString());
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.dotNet = true;
envelope.setOutputSoapObject(request);
envelope.encodingStyle = "utf-8";
envelope.implicitTypes = false;
String myUrlz= "http://" + myUrl.getText().toString() +"/Foo/Bar.asmx";
HttpTransportBasicAuth auth = new HttpTransportBasicAuth(myUrlz, "Foo", "Bar");
auth.debug = true;
try
{
auth.call(SOAP_ACTION, envelope); // Fails on this line.
System.out.println("Dump" + auth.responseDump);
// all the other stuff.....
}
catch (FooException Bar)
{
// ¯\_(ツ)_/¯
}
So basically, we're recieveing html response instead of xml when accessing the protected service. And yes, the localhost service and the sharp service are exactly the same except for the authentication part.
The short answer is no, there is no out-of-the-box method for NTLM on android.
The long answer is that there have been successful attempts in hacking together your own solution using the Apache HttpClient. See the following links:
http://danhounshell.com/blog/android-using-ntlm-authentication-with-httpclient/
http://mrrask.wordpress.com/2009/08/21/android-authenticating-via-ntlm/
There is no way an Android device can have a valid NTLM token for a Windows domain it does not belong to.
The only option you have is to change the authentification mechanism on the server to something more appropriate. If you need to restrict access to the page, here are some options available to you:
Basic authentification (over http or over https)
form based authentification (over http or over https)
https with SSL certificate authentification (in Android app and server side)
public page with Oauth (over http or hhtps)
public page with OpenID (over http or hhtps)
I'm struggling to successfully make a web service call to a SOAP web service from a web page. The web service is a Java web service that uses JAX-WS.
Here is the web method that I'm trying to call:
#WebMethod
public String sayHi(#WebParam(name="name") String name)
{
System.out.println("Hello "+name+"!");
return "Hello "+name+"!";
}
I've tried doing the web service call using the JQuery library jqSOAPClient (http://plugins.jquery.com/project/jqSOAPClient).
Here is the code that I've used:
var processResponse = function(respObj)
{
alert("Response received: "+respObj);
};
SOAPClient.Proxy = url;
var body = new SOAPObject("sayHi");
body.ns = ns;
body.appendChild(new SOAPObject("name").val("Bernhard"));
var sr = new SOAPRequest(ns+"sayHi",body);
SOAPClient.SendRequest(sr,processResponse);
No response seems to be coming back. When in jqSOAPClient.js I log the xData.responseXML data member I get 'undefined'. In the web service I see the warning
24 Mar 2011 10:49:51 AM com.sun.xml.ws.transport.http.server.WSHttpHandler handleExchange
WARNING: Cannot handle HTTP method: OPTIONS
I've also tried using a javascript library, soapclient.js (http://www.codeproject.com/kb/Ajax/JavaScriptSOAPClient.aspx). The client side code that I use here is
var processResponse = function(respObj)
{
alert("Response received: "+respObj);
};
var paramaters = new SOAPClientParameters();
paramaters.add("name","Bernhard");
SOAPClient.invoke(url,"sayHi",paramaters,true,processResponse);
I've bypassed the part in soapclient.js that fetches the WSDL, since it doesn't work
(I get an: IOException: An established connection was aborted by the software in your host machine on the web service side). The WSDL is only retrieved for the appropriate name space to use, so I've just replaced the variable ns with the actual name space.
I get exactly the same warning on the web service as before (cannot handle HTTP method: OPTIONS) and in the browser's error console I get the error "document is null". When I log the value of req.responseXML in soapclient.js I see that it is null.
Could anyone advise on what might be going wrong and what I should do to get this to work?
I found out what was going on here. It is the same scenario as in this thread: jQuery $.ajax(), $.post sending "OPTIONS" as REQUEST_METHOD in Firefox.
Basically I'm using Firefox and when one is doing a cross domain call (domain of the address of the web service is not the same as the domain of the web page) from Firefox using AJAX, Firefox first sends an OPTIONS HTTP-message (before it transmits the POST message), to determine from the web service if the call should be allowed or not. The web service must then respond to this OPTIONS message to tell if it allows the request to come through.
Now, the warning from JAX-WS ("Cannot handle HTTP method: OPTIONS") suggests that it won't handle any OPTIONS HTTP-messages. That's ok - the web service will eventually run on Glassfish.
The question now is how I can configure Glassfish to respond to the OPTIONS message.
In the thread referenced above Juha says that he uses the following code in Django:
def send_data(request):
if request.method == "OPTIONS":
response = HttpResponse()
response['Access-Control-Allow-Origin'] = '*'
response['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS'
response['Access-Control-Max-Age'] = 1000
response['Access-Control-Allow-Headers'] = '*'
return response
if request.method == "POST":
# ...
Access-Control-Allow-Origin gives a pattern which indicates which origins (recipient addresses) will be accepted (mine might be a bit more strict than simply allowing any origin) and Access-Control-Max-Age tells after how many seconds the client will have to request permission again.
How do I do this in Glassfish?
Have you actually tested that ws is working properly?
You can use SoapUI for inspecting request/response etc.
When you confirm that ws is working from SoapUI, inspect what is format of raw Soap message. Then try to inspect how it looks before sending with .js method, and compare them.
It might help you understand what is wrong.
Check if this helps
http://bugs.jquery.com/attachment/ticket/6029/jquery-disable-firefox3-cross-domain-magic.patch
it's marked as invalid
http://bugs.jquery.com/ticket/6029
but it might give you some hint
On the other hand, instead to override proper settings for cross-domain scripting might be better if you can create and call local page that will do request to ws and return result.
Or even better, you can create page that will receive url as param and do request to that url and just return result. That way it will be more generic and reusable.