Friday, November 23, 2012

ADF Mobile - Secured Web Service Access

I will dig today into secured Web Service access from ADF Mobile. There are good tutorials how to consume open Web Service in ADF Mobile, but in practice almost every Web Service exposed for the mobile must be secured - who wants to expose open Web Service on the public internet? ADF Mobile doesn't support Web Service Java Proxy, you have an option to use Data Control generated directly from the Web Service -  I will explain the steps how to configure such Data Control for secured Web Service access. Thanks to Joe Huang (ADF Mobile Product Manager) - he gave me very useful hints to finalize secured Web Service invocation from ADF Mobile.

In my next post - I will explain how to deploy and test the same application on real iPhone device.

I would recommend to read - 10.5 Accessing Secure Web Services, this is a good guide - but I will try to cover certain gaps. You can download sample application - mobilesecuredws.zip. This archive is based on previous blog sample application - ADF Mobile - Login Functionality and contains three applications:

1. ADFBasicAuthApp - typical ADF application with basic ADF security authentication enabled. This application is installed as authentication server.

2. ADFMobileSecuredApp - ADF Mobile application with deployment profile for iOS simulator. Implemented secured home page and configured with login page. Calls secured Web Service.

3. ADFSecuredService - ADF BC application enabled with Web Service from Application Module.

From this diagram you can understand all the relationships implemented in the sample application:


Access to ADF Mobile application is authenticated through WebLogic server security realm. Once initial authentication is completed - user is able to call secured Web Service. ADF Mobile injects user security information into Web Service header, security information is retrieved from security store constructed after login.

We should look now into the service part - where secured Web Service is implemented (ADFSecuredService application). Standard service interface is defined for Application Module and one custom method is exposed:


Custom method is not doing anything fancy, except that it prints success message:


How you can secure such Web Service? Just select implementation class in the structure window:


Locate OWSM Policies section in the Properties window and open property editor. There are different properties available, for this sample application I was using - oracle/wss_username_token_service_policy:


You can double check if security policy is assigned successfully for Web Service implementation class:


This is all with the service part, now we are going to switch to the ADF Mobile part (ADFMobileSecuredApp application). As I have said earlier, ADF Mobile doesn't support Java Web Service proxy, so we are going to use Web Service Data Control directly:


Once Data Control for Web Service is generated (I skip this part, because it is well documented anyway - just Google), you should select it in the Structure window, right click and choose - Define Web Service Security:


In the wizard, for your convenience - check option for Show only the compatible client policies for selection - this will filter only these security policies applied supported by the Web Service on server side:


Now we are approaching one of the most critical points in this post - connections.xml file configuration in ADF Mobile application:


This file defines two connections:

1. Authentication Server for Login
2. Secured Web Service

Both of these connections must point to the same adfCredentialStoreKey. There is a bug in current version, when you generated Web Service Data Control for ADF Mobile application - by default it is using different property name - credentialStoreKey. You should fix this property name manually to be adfCredentialStoreKey (check sample application). This is known issue - Enabling Credential Injection to Web Services (14726089).

Once again - adfCredentialStoreKey for authentication server:


Must be the same as for the secured Web Service:


Configuration is completed - now we can test it. Add button on ADF Mobile UI screen to invoke method from secured Web Service data control:


ADF Mobile is using the same bindings concept as regular ADF - action is defined in the page definition file, this action is responsible to call method from secured Web Service:


Run application on iPhone simulator directly from JDeveloper environment:


Few seconds and we are ready to login into ADF Mobile application:


Authentication is successful - press Test Web Service Secured Access button to invoke custom method from remote secured Web Service:


Check server log - method was invoked successfully:

17 comments:

Nasir Uddin said...

Thanks Andre,

This is just what I am after.

Cheers,
Nasir

Fedir Zymarev said...

Hi!
I have repeated this on my environment - all works just fine.
But when I deploy such webservice application to standalone WLS (11.1.1.6 with ADF patched to 11.2.0.3) web service stopped to recognize configured OWSM Policy:

PolicySet Invalid: WSM-06102 PolicyReference The policy reference URI "oracle/wss_username_token_service_policy" is not valid.

How to enable this only supported policy on WLS?

Joseph Bazil said...

Hi Andrejus,

I am trying to connect to webservice which I have created in OSB with OWSM policy. I am trying to use this web service in ADF. I am unable to pass the username and password in the SOAP header. Do you have any examples that can help me please.

Regards

Joseph Bazil

Andrejus Baranovskis said...

Hi Fedir,

May be this will help to resolve not found policy in your case: https://forums.oracle.com/forums/thread.jspa?threadID=2429926

Regards,
Andrejus

Andrejus Baranovskis said...

Hi Joseph,

Yes - take a look into ADFSecuredService application from this post.

Andrejus

Fedir Zymarev said...

Hi Andrejus,
Unfortunately, there's no such internal application mentioned on your link. Maybe there's a way to move it from BI WLS setup. But for now as a workaround I'll set up JDeveloper domain on my server and try to use it for mobile applications.

Andrejus Baranovskis said...

Sounds good Fedir.

But I think wsm-pm is not only specific to BI...

Anyway - try to run for now on JDev domain.

Andrejus

Anonymous said...

Nice post (as usual!).
But I got a small question.
Isn't it possible to merge the 2 non-mobile applications into 1?
If not, why? If it's possible, are there any disadvantages?

Andrejus Baranovskis said...

Hi,

Yes - you can merge 2 non mobile ADF apps into one. There are no disadvantages, just for me it was more fun to have it like that. It makes it easier to explain different parts of ADF. Without mixing everything into one app - is harder to understand what belongs to what for new ADF developers.

Andrejus

Anonymous said...

Hi Andrejus,
Thanks for a great example. How ever if we wanted to the User Name to be different for login and the secured web service, how would we achieve that ?

eg:- The Login Webservice user is against a LDAP but the webservices are secured using wss_user_token_policy having a Static Username/Password. Now how to pass the Static Username/Password to the secured web service?

Regards
Naveen

Andrejus Baranovskis said...

Hi,

wss_user_token_policy is also using user from WebLogic security provider. I dont think it is static.

Andrejus

Anonymous said...

Thank you for the response. How about a scenario where in we dont have a login page in ADF Mobile but the application uses Secured Webservices. In such a case since login page is absent we wouldnt be able to leverage the same adfcredentialstorekey hence what is the alternative to invoke the secured webservice ?

Regards
Naveen

Andrejus Baranovskis said...

You must have login page, I dont think there is alternative.

Andrejus

simo said...

HI thanks for your post. This was extremely helpful. If you have multiple features, is there any way of hiding the feature bar or even the springboard until the user has logged in. I tried securing a custom springboard to achieve this, and checked the option 'show springboard on launch'. Seems like the 'transition behaviour' is missing as an error occurred.

Jyotika Kondalkar said...

Hi,

I am trying to create a simple ADF Mobile App where on first page it accepts username and password and on submit it calls a web service and get response true or false. And depending on the result it displays error page or success page. So, do we have to use any managed beans or routers for this? How to implement this?
Do you have any example on the above scenario.

Thanks & Regards,
Jyotika

Anonymous said...

Hi,

I have created Rest Data Control for POST method, i created this data control as a button on page, when i run this page on emulator and click on this button, i am getting the below error:

"HTTP Status 400 Bad Request: The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without modifications."


Get method is working fine for me. Can you please help.

M.Ahmed said...

How can i call webservice with complex parameters grammatically
as
I've adf mobile application that is built with jdeveloper 11.1.2.4 with the latest ADF mobile extension

I've consumed a webservice that takes Object credential , String employeeId and return salary

the credentials Object consist of (String username , String password) in the soap header



i want to know how to consume this webservice and pass user name , password as i'v used this method







List paramNames = new ArrayList();
paramNames.add("user_number");


List paramsValues = new ArrayList();
paramsValues.add("45454");



List paramTypes = new ArrayList();
paramTypes.add(String.class);


try {
result =
(String)AdfmfJavaUtilities.invokeDataControlMethod("MYDC", null, "userInfo", paramNames,paramsValues, null);


} catch (AdfException ae) {
ae.printStackTrace();
throw new AdfException("Please check your network connection", AdfException.ERROR);
} catch (AdfInvocationException aie) {
aie.printStackTrace();
throw new AdfException("Please check your network connection", AdfException.ERROR);
}

I don't know how to add the user name and password as they are in a complex parameter called credentials