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)
Related
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
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.
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)
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)
We have a JSF web application that uses Acegi security. We also have a standalone Java Swing application. One function of the Swing app is to load the user's home page in a browser window.
To do this we're currently using Commons HttpClient to authenticate the user with the web app:
String url = "http://someUrl/j_acegi_security_check";
HttpClient client = new HttpClient();
System.setProperty(trustStoreType, "Windows-ROOT");
PostMethod method = new PostMethod(url);
method.addParameter("j_username", "USERNAME");
method.addParameter("j_password", "PASSWORD");
int statusCode = client.executeMethod(method);
if (statusCode == HttpStatus.SC_MOVED_TEMPORARILY ) {
Header locationHeader= method.getResponseHeader("Location");
String redirectUrl = locationHeader.getValue();
BrowserLauncher launcher = new BrowserLauncher();
launcher.openURLinBrowser(redirectUrl);
}
This returns a HTTP 302 redirect response, from which we take the redirect url and open it using BrowserLauncher 2. The url contains the new session ID, something like:
http://someUrl/HomePage.jsf;jsessionid=C4FB2F643CE48AC2DE4A8A4C354033D4
The problem we're seeing is that Acegi processes the redirect but throws an AuthenticationCredentialsNotFoundException. It seems that for some reason the authenticated credentials cannot be found in the security context.
Does anyone have an idea as to why this is happening? If anyone needs more info then I'll be happy to oblige.
Many thanks,
Richard
I have never done Acegi/SpringSecurity, but the symptoms are clear enough: some important information is missing in the request. You at least need to investigate all the response headers if there isn't something new which needs to be passed back in the header of the subsequent request. Maybe another cookie entry which represents the Acegi credentials.
But another caveat is that you in fact cannot open just the URL in a local browser instance, because there's no way to pass the necessary request headers along it. You'll need to have your Swing application act as a builtin webbrowser. E.g. get HTML response in an InputStream and render/display it somehow in a Swing frame. I would check if there isn't already an existing API for that, because it would involve much more work than you'd initially think .. (understatement).
In this case you can do Basic Authentication and set this header in every request instead of sending the jsessionid:
AUTHORIZATION:Basic VVNFUk5BTUU6UEFTU1dPUkQ=
The token VVNFUk5BTUU6UEFTU1dPUkQ= is the username and the password encoded base64.
Example:
scott:tiger
is:
c2NvdHQ6dGlnZXI=
One more thing: use SSL.