Tuesday, October 25, 2016

WS Security - enabling passwordDigest authentication in an Oracle FMW environment

To have a basic level of authentication on web services (especially where there's no transport layer security) without having to pass clear text passwords in the WS Security headers. 

The concepts are fairly generic but this post is highly Oracle Fusion middleware/SOA Suite specific. There can be complex decision tree (see [1]) involved when selecting the 'appropriate' level of security for any system. As security involves trade-offs between cost, performance, usability and other variables, the 'appropriate' level of security could be highly specific to the environment, usecase, system and people. But as developers, we can still perform some due diligence based on the tools and knowledge available to us.  

My rule of thumb when developing a traditional web service or microservice is: If it's reading from a secure database or some system that is accessible only via authentication, it must only expose a secure endpoint. 

Now sites can differ considerably and so does the definition of what "secure" is. 
When exposing ah http endpoint (SOAP or REST) hosted on cloud or accessible over the Internet, one would as a minimum ensure that it's over TLS and has authentication enabled. 

In an on-premise hosted solution, traditionally https has not been widespread within organisations and web service endpoints meant for internal consumption have most commonly only been exposed over http - hopefully accompanied by infrastructure level setup (firewalls, DMZs etc.) that ensures that the data or service is only accessible inside a 'trusted' network. 

Even in a trusted network without TLS, it is probably best if passwords weren't floating around in clear text (which is what the default UsernameToken with passwordText policies do)
With a few steps, one can enable the passwordDigest authentication that not only protects the password in-transit, but also provides protection against replay attacks (if nonce and creation time properties are set in the SOAP header as well)

  • Basic steps are listed here:
  • For step 9.3.3, what I do is create a new policy pair based on oracle/wss_username_token_service_policy
This is done via /em -> WeblogicDomain -> Web Services -> WSM Policies

Search for oracle/wss_username_token_service_policy and copy to create a new one with the settings for passwordDigest applied (as per step 9.3.3 of the Oracle guide)

The one I created is singhpora/wss_UsernameToken_PasswordDigest_service_policy and 
(based on oracle/wss_username_token_client_policy) and I keep these source controlled. (An additional benefit of putting them in source control is so developers can import these into their local JDeveloper policy store for design time and also to promote their initial versions or changes across environments from development through to production,much like any other artefact)
  • Another associated step is to have the oracle.wsm.security map and basic.credentials key to be present on the server that will use the client policy (you can use custom map and key names if required). This needs to contain the username(s) and passwords of the users who are allowed to invoke the web services that use the username token policies. (You can follow the principle of least privilege when assigning a group to these users.)

This can clearly be seen when invoking the service via SOAPui. 
If your service uses a UsernameToken with PasswordDigest policy (like the one I shared above), SOAPui can be used to test it as it can automatically set the required security headers. 
If you look at the SOAPui logs, before applying the passwordDigest policy (e.g. when your services uses a username token with password text based authentication policy like in the default setup), this is how the password component of username token is created:

Unless your service is accessible only over SSL, this means you have passwords flowing around the network in clear text. Most corporate IT policies would I believe specifically forbid letting passwords float around like this and yet, this can often go unnoticed and unaddressed. 

After applying the username token with password digest policy, is how the WS Security headers get created:

Only the client and the server now know what the password is and no one in the middle can see this. 

* To enable digest authentication, the server has to store passwords in clear text. The reason is that with digests, the client (such as SOAPui in the above example) creates a hash of the actual password, creation time and nonce -* the server on its side has to create the same hash for successful authentication and this requires the server to know the clear text password. 
But this is still okay as this can be contained behind strict administrator control. Way better than having clear text passwords travelling over the network. 

[1] Decisions and choices involved when selecting the appropriate security policy: https://docs.oracle.com/middleware/1221/owsm/security/choose-owsm-policy.htm#OWSMS3988

[2] Setup steps for enabling digest authentication: https://docs.oracle.com/middleware/1212/owsm/OWSMS/configure-owsm-authentication.htm#OWSMS5450


Mihir Panda said...

Awesome article.
Is it possible to implement above solution in SOA 11g or it is possible only on 12C.
If possible in 11g how to od it?

Please help

Jang-Vijay Singh said...

@Mihir glad you liked it.
From what I read here, it might be supported -https://docs.oracle.com/cd/E28280_01/web.1111/b32511/intro_security.htm#WSSEC2343
The best way to check would be to run the "Basic steps" as per my post and see if the DefaultAuthenticator allows you to choose wsse:PasswordDigest