Apache Camel v2.12 | CXF Component | Basic Authentication - java

Respected Experts,
I am trying to access a web service that requires basic authentication. I am able to access using the CXF's JaxWsDynamicClientFactory. The code piece for auth looks like:
JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
Client client = dcf.createClient(ID_WSDL);
HTTPConduit conduit= (HTTPConduit) client.getConduit();
AuthorizationPolicy authorization = conduit.getAuthorization();
authorization.setUserName(USERNAME);
authorization.setPassword(PWD);
conduit.setAuthorization(authorization);
However, when I try to use Camel's CXF component to access the same Web Service I get 401 Unauthorized error, since Camel is not sending the authentication information to the Web Service.
My route looks like:
from("file://c:/test?fileName=request.txt&noop=true").routeId("myrouteId")
.process(processor)
.to(cxf)
.to("log:{body}");
In my processor, I am setting the credentials as follows:
Map<String, Object> properties = new HashMap<String, Object>();
AuthorizationPolicy authPolicy = new AuthorizationPolicy();
authPolicy.setAuthorizationType(HttpAuthHeader.AUTH_TYPE_BASIC);
authPolicy.setUserName(USERNAME);
authPolicy.setPassword(PWD);
properties.put("org.apache.cxf.configuration.security.AuthorizationPolicy", authPolicy);
myEndpoint.setProperties(properties);
myEndpoint is CXFEndpoint, retrieved from Exchange.
Am I missing something or something wrong here.
There is a similar question. I had raised my doubt there as a answer since I was not able to comment. However, my answer has been deleted. So, I am raising a fresh question in a hope that I will get some direction to move forward on this.
Thks & brgds

With Willem's help, was able to make this working. The authentication credentials need to passed to the CXF Endpoint in the Route Builder rather than in the Processor. This is as explained by Williem on Camel forum:
If you set the cxfEndpoint property in a processor, it’s a setting of runtime.
As the CxfProducer is created during the camel context start the route, the cxfEndpoint’s property is >not updated.
So, to fix this add the following code to the Route Builder:
Map<String, Object> properties = new HashMap<String, Object>();
AuthorizationPolicy authPolicy = new AuthorizationPolicy();
authPolicy.setAuthorizationType(HttpAuthHeader.AUTH_TYPE_BASIC);
authPolicy.setUserName(USERNAME);
authPolicy.setPassword(PWD);
authPolicy.setAuthorization("true");
//properties.put(AuthorizationPolicy.class.getName(), authPolicy);
properties.put("org.apache.cxf.configuration.security.AuthorizationPolicy", authPolicy);
CxfEndpoint myCxfEp = (CxfEndpoint)getContext().getEndpoint("cxf://");
myCxfEp.setProperties(properties);
Also, version 2.12.3 of Apache Camel is introducing username and password options for basic authentication.

Related

jax-ws redirect http / https

I am having problem with jax-ws making it work if the server return 301 on http to https. I got an exception, and after debugging it with charles it seems that the redirect doesn't work. I also noticed that there is some trick for http to https[*], but i am not sure if it still apply to java8
That's the pseudo-code that i would like to use with a dirty fix that i found online
TestImplService service = new TestImplService();
Test test = service.getTestImplPort();
Map<String, Object> tmp = ((BindingProvider) test).getRequestContext();
/*dirty fix*/
tmp.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, tmp.get(BindingProvider.ENDPOINT_ADDRESS_PROPERTY).toString().replace("http:", "https:")
);
test.dosomething();
Replacing http with https work, but i am not 100% sure that's the correct way.
Let's suppose that the server decide to stop to support https, disable the 301 for http, then my fix won't work anymore.
Can i force the follow redirect in another way?
[*] https://docs.oracle.com/javase/6/docs/technotes/guides/deployment/deployment-guide/upgrade-guide/article-17.html
BindingProvider class BindingProvider.ENDPOINT_ADDRESS_PROPERTY property is usable for change endpoint URL; Sometimes HTTPS connection ended with network switches/routers. Therefor application server cannot realize the path of https.
service = new ....(url, SERVICE_NAME);
port = service.get...BasicHttpEndpoint();
BindingProvider provider = ((BindingProvider) port);
Map<String, Object> map = provider.getRequestContext();
String current = map.get(BindingProvider.ENDPOINT_ADDRESS_PROPERTY).toString();
map.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, current.replace("http:", "https:"));

How do I add HTTP headers to JAXWS created proxy classes

I've created a set of proxy classes in NetBeans for a SOAP web service.
I'd like to add an HTTP header to the outgoing request.
Map<String, Object> requestHeaders = new HashMap<>();
requestHeaders.put("X-Header", header);
AccountManagementService service = new AccountManagementService();
AccountManagementServiceSoap soap = service.getAccountManagementServiceSoap();
GetMembershipSummaryResponse.GetMembershipSummaryResult membershipSummary = soap.getMembershipSummary("mikeb#foobar.com");
I saw a bunch of JAX-WS header examples for when you are getting the individual port from the service. Is there an easier way? Can I just add the header to some collection on service or soap object?
after some digging I found this post: jax-ws change Content-type to Content-Type because server is hyper sensitive
which isn't really a full answer, so I am going to post the full answer here:
AccountManagementService service = new AccountManagementService();
AccountManagementServiceSoap soap = service.getAccountManagementServiceSoap();
((BindingProvider)soap).getRequestContext().put(MessageContext.HTTP_REQUEST_HEADERS,
Collections.singletonMap("X-Header",Collections.singletonList(header)));
GetMembershipSummaryResponse.GetMembershipSummaryResult membershipSummary = soap.getMembershipSummary("mikeb#foobar.com");

CXF + wsdl2java + authentication

I created the jar from the WSDL for my client using the wsdl2java command. Now, I need to know how I can authenticate my client in order to complete an operation?
I am using CXF 2.7.16. I created my service using the generated class MyApp_Service, I am struggling with this. Isn't there a simple way to tell my client the credentials it should use to gain access to the web service?
I read about the Spring configuration, however I am unable to figure out if it applies to my case and how if yes. I tried to cast the MyApp_Service class to BindingProvider in order to use the method which consist to put the USERNAME and PASSWORD properties in the context with a value. However, MyApp_Service cannot be cast to BindingProvider.
This is my first web service client application ever. So, any help will be welcomed.
Update 2015-05-28: I tried to define the AuthenticationPolicy but is seems not working. Here is the code:
Client client = JaxWsDynamicClientFactory.newInstance().createClient(wsdlUrl);
ClientImpl clt = (ClientImpl) client;
HTTPConduit cc = (HTTPConduit) clt.getConduit();
org.apache.cxf.configuration.security.ObjectFactory secOF = new org.apache.cxf.configuration.security.ObjectFactory();
AuthorizationPolicy ap = secOF.createAuthorizationPolicy();
ap.setUserName(usagerWS);
ap.setPassword(mdpWS);
ap.setAuthorizationType("Basic");
cc.setAuthorization(ap);
Sniffing with WireShark, the Authorization header is clearly missing in the HTTP request.
What is missing?
Problem solved, here is the solution:
MyApp_Service service = new MyApp_Service(wsdlUrl, new QName(namespace, serviceName));
MyApp port = service.getMyApp();
// Set credentials
Map<String, Object> reqCtxt = ((javax.xml.ws.BindingProvider) port).getRequestContext();
reqCtxt.put(javax.xml.ws.BindingProvider.USERNAME_PROPERTY, username);
reqCtxt.put(javax.xml.ws.BindingProvider.PASSWORD_PROPERTY, password);
No more usage of the dynamic client. Only the classes generated with wsdl2java are used.

How to retrieve data from website with basic authentication?

How can I connect to a website with basic authentication? I'm using the http component. I saw somewhere, that ?username=&password= is used, but it doesn't work for me.
Thanks to Ralf's answer I found out that I forgot to add authMethod to the url. Here is the solution:
http://localhost/?authMethod=Basic&authUsername=username&authPassword=password
Looking at the http compoment documentation the following should work:
http://...?authMethod=Basic&authUsername=...&authPassword=...
Be aware of the security implications of using basic auth without SSL/TLS.
I suggest you read this page and look down for the header "Authentication and Proxy". There you may find the following documented - authMethod, authUsername and authPassword. To use it I'd do something like this
String authUsername = "MyUser";
String authPassword = "MyPass";
HttpComponent http = new HttpComponent();
HttpConfiguration config = http.getHttpConfiguration();
config.setAuthMethod(AuthMethod.Basic);
config.setAuthUsername(authUsername);
config.setAuthPassword(authPassword);
http.setHttpConfiguration(config);

why OAuth request_token using openid4java is missing in the google's response?

I have succeed using openID and OAuth separately, but I can't make them work together.
Am I doing something incorrect:
String userSuppliedString = "https://www.google.com/accounts/o8/id";
ConsumerManager manager = new ConsumerManager();
String returnToUrl = "http://example.com:8080/app-test-1.0-SNAPSHOT/GAuthorize";
List<DiscoveryInformation> discoveries = manager.discover(userSuppliedString);
DiscoveryInformation discovered = manager.associate(discoveries);
AuthRequest authReq = manager.authenticate(discovered, returnToUrl);
session.put("openID-discoveries", discovered);
FetchRequest fetch = FetchRequest.createFetchRequest();
fetch.addAttribute("email","http://schema.openid.net/contact/email",true);
fetch.addAttribute("oauth", "http://specs.openid.net/extensions/oauth/1.0",true);
fetch.addAttribute("consumer","example.com" ,true);
fetch.addAttribute("scope","http://www.google.com/calendar/feeds/" ,true);
authReq.addExtension(fetch);
destinationUrl = authReq.getDestinationUrl(true);
then destinationUrl is
https://www.google.com/accounts/o8/ud?openid.ns=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0&openid.claimed_id=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select&openid.identity=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select&openid.return_to=http%3A%2F%2Fexample.com%3A8080%2FgoogleTest%2Fauthorize&openid.realm=http%3A%2F%2Fexample.com%3A8080%2FgoogleTest%2Fauthorize&openid.assoc_handle=AMlYA9WVkS_oVNWtczp3zr3sS8lxR4DlnDS0fe-zMIhmepQsByLqvGnc8qeJwypiRQAuQvdw&openid.mode=checkid_setup&openid.ns.ext1=http%3A%2F%2Fopenid.net%2Fsrv%2Fax%2F1.0&openid.ext1.mode=fetch_request&openid.ext1.type.email=http%3A%2F%2Fschema.openid.net%2Fcontact%2Femail&openid.ext1.type.oauth=http%3A%2F%2Fspecs.openid.net%2Fextensions%2Foauth%2F1.0&openid.ext1.type.consumer=example.com&openid.ext1.type.scope=http%3A%2F%2Fwww.google.com%2Fcalendar%2Ffeeds%2F&openid.ext1.required=email%2Coauth%2Cconsumer%2Cscope"
but in the response from google request_token is missing
http://example.com:8080/googleTest/authorize?openid.ns=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0&openid.mode=id_res&openid.op_endpoint=https%3A%2F%2Fwww.google.com%2Faccounts%2Fo8%2Fud&openid.response_nonce=2011-11-29T17%3A38%3A39ZEU2iBVXr_zQG5Q&openid.return_to=http%3A%2F%2Fexample.com%3A8080%2FgoogleTest%2Fauthorize&openid.assoc_handle=AMlYA9WVkS_oVNWtczp3zr3sS8lxR4DlnDS0fe-zMIhmepQsByLqvGnc8qeJwypiRQAuQvdw&openid.signed=op_endpoint%2Cclaimed_id%2Cidentity%2Creturn_to%2Cresponse_nonce%2Cassoc_handle%2Cns.ext1%2Cext1.mode%2Cext1.type.email%2Cext1.value.email&openid.sig=5jUnS1jT16hIDCAjv%2BwAL1jopo6YHgfZ3nUUgFpeXlw%3D&openid.identity=https%3A%2F%2Fwww.google.com%2Faccounts%2Fo8%2Fid%3Fid%3DAItOawk8YPjBcnQrqXW8tzK3aFVop63E7q-JrCE&openid.claimed_id=https%3A%2F%2Fwww.google.com%2Faccounts%2Fo8%2Fid%3Fid%3DAItOawk8YPjBcnQrqXW8tzK3aFVop63E7q-JrCE&openid.ns.ext1=http%3A%2F%2Fopenid.net%2Fsrv%2Fax%2F1.0&openid.ext1.mode=fetch_response&openid.ext1.type.email=http%3A%2F%2Fschema.openid.net%2Fcontact%2Femail&openid.ext1.value.email=example%40gmail.com
why?
In the above code, you have added OAuth extension parameters with the Attribute Exchange extension parameters. But since OAuth and Attribute Exchange are different extensions, therefore you have to create a different extension message for OAuth parameters and then add it to Authentication request message.
But since there is no mechanism to add OAuth parameters to the Authentication message, therefore you'll have to create such a mechanism. You can get information about it in the following link
http://code.google.com/p/openid4java/wiki/ExtensionHowTo
You can then use the code provided in the following link to hard code this mechanism
http://code.google.com/p/openid4java/issues/detail?id=110&q=oauth

Categories

Resources