Monday, August 22, 2011

Do SAML with OWSM

In this blogpost I will explain the different SAML options and the advanced configurations you can do when you use the SAML client and server policies of Oracle Web Service Manager FMW 11gR1.
The following will be explained and configured in this blogpost.
  • A basic SAML authentication with 2 OWSM Servers.
  • Change the default SAML issuer name.
  • Allow only trusted SAML clients.
  • SAML Identity switching.
  • Virtual Users with User roles.
Creating a working SAML setup. 
For this we need two WebLogic domains and both have at least the Enterprise Manager web application and enabled the OWSM option. For this demo I will have one domain with SOA Suite and one with only a WebLogic Adminserver where we will deploy a JAX-WS Web Service which has an OWSM server policy. You can replace the SOA Suite with a OSB server ( it works in the same way ) . For OWSM, every domain need to have it's own MDS repository to store all the OWSM policies and for SOA Suite you also need a soa-infra database repos.

This will be our setup.
  • A client ( soapUI or WS client proxy ) calls an exposed web service of a SOA Suite composite and the client needs to provide a username token.
  • The exposed service has oracle/wss_username_token_service_policy as OWSM Server policy. The username token will be validated by WebLogic and the username will be passed on by SAML and signed with the signing certificate of the SOA Suite OWSM. The exposed service has a wire to a Mediator with a simple routing rule.
  • The Mediator has a wire to the Reference Web Service. This reference WS binding has oracle/wss11_saml_token_with_message_protection_client_policy as OWSM client policy.
  • The Reference WS binding calls a JAX-WS Web Service deployed on the other WebLogic Domain and this Web Service has oracle/wss11_saml_token_with_message_protection_service_policy as OWSM server policy. OWSM will validate the SAML issuer and check if it knows the username ( the password does not matter, because it is trusted )
The SOA Composite I used.

The JAX-WS service
Before we can test this SAML service, we need to generate some keystores, configure OWSM and add some users to WebLogic.
Execute the following commands to generate some self signed private keys and exchange the public keys ( this will trust each other certificates )

Go to the bin folder of your JDK.
cd c:\oracle\jrockit-jdk1.6.0_26-R28\bin

Generate a certificate for SOA ( server.jks ) and one for the JAX-WS server (  saml.jks )
keytool -genkey -alias serverKey -keyalg "RSA" -sigalg "SHA1withRSA" -dname "CN=server, C=US" -keypass welcome -keystore c:\temp\server.jks -storepass welcome -validity 3650
keytool -genkey -alias samlKey -keyalg "RSA" -sigalg "SHA1withRSA" -dname "CN=saml, C=US" -keypass welcome -keystore c:\temp\saml.jks -storepass welcome  -validity 3650

Export the public key
keytool -exportcert -alias serverKey -storepass welcome -keystore c:\temp\server.jks -file c:\temp\server.cer
keytool -exportcert -alias samlKey -storepass welcome -keystore c:\temp\saml.jks -file c:\temp\saml.cer

Import the keys in each other keystore ( for the trust (
keytool -import -alias serverKey -file c:\temp\server.cer -storepass welcome -keystore c:\temp\saml.jks
keytool -import -alias samlKey -file c:\temp\saml.cer -storepass welcome -keystore c:\temp\server.jks

Show the certificates in each keystore.
keytool -list -storepass welcome -keystore c:\temp\server.jks
keytool -list -storepass welcome -keystore c:\temp\saml.jks

Copy the server.jks to the config\fmwconfig folder of your SOA Suite domain. Do the same for the saml.jks keystore but then to fmwconfig of the JAX-WS server domain.

Go the Enterprise Manager (EM) application of the SOA Suite.  Open the WebLogic Domain treenode and select your SOA domain. In the Domain menu (right window)  go to Security -> Security Provider Configuration. Click on the Configure button in the keystore section.

  
Use ./server.jks in the Keystore Path field and serverKey in the Key and Crypt Alias. Use welcome for all the password fields.

We need to do the same at the JAX-WS server but then use the following values.
Use ./saml.jks in the Keystore Path field and samlKey in the Key and Crypt Alias. Use welcome for all the password fields.

Add a user with client as name and with weblogic1 as password in the myrealm security realm of the SOA Suite server. Do the same at the JAX-WS server but now use welcome1 as password.

Do a restart of the all the servers.

We can test the SAML setup by generating a Web Service Client proxy in JDeveloper. Here is an example how I add the client credentials.

that is all for the basic SAML test.

How to change the SAML issuer name. 
The default SAML issuer name is www.oracle.com , We can change this at the JAX-WS server. For this we need to go the EM application of the JAX-WS Server. Open the WebLogic Domain treenode and select your JAX-WS domain. In the Domain menu (right window)  go to Security -> Security Provider Configuration. Click on the Configure button in the Advanced section.

Here we can change the name attribute of saml.trusted.issuers.1 property to www.amis.nl and click on Ok. This way you will change the default trusted issuer for all the SAML login modules, if you only want to change this for SAML1.1 and not for SAML2 then you can open the saml.loginmodule instead (located at the Security Provider Configuration) and change it there. This will add an extra saml property name beside the one of www.oracle.com
You will need to restart the WebLogic server.

We also need to change an attribute on the reference web service binding of the SOA Composite. Select the reference binding and right click, to open the Configure WS Policies menu.

Click on the pencil to override the saml.issuer.name and use www.amis.nl

Deploy the composite and re-test it with the jdeveloper ws proxy client.

Allow only trusted SAML clients
In the current setup each public key found in the saml.jks keystore can sign a SAML token. In this part we can restrict this to only "CN=server, C=US", this is the DN of the signing certificate located at the SOA Suite server.

Go the Enterprise Manager (EM) application of the JAX-WS Server.  Open the WebLogic Domain treenode and select your JAX-WS domain. In the Domain menu (right window)  go to Web Services -> Platform Policy Configuration.

Go to the Trusted SAML clients Tab and add a new Trusted Issuer called www.amis.nl .
Select the just created Trusted Issuer and add a Trusted SAML Client and use CN=server, C=US as value.

Restart the JAX-WS Server and now only CN=server, C=US can sign the SAML token.

SAML Identity switching
In the last part of this blogpost we will change the identity of the SAML token. In the previous examples we used client as username and this is passed on to the JAX-WS server.  We will override this on the SOA Suite server.  In our test client we can now use weblogic as username and override to client in the SOA Composite.
Open the Mediator of the  SOA Composite where we will add an Assign to the request part of the Routing Rule.

Here we need to add the javax.xml.ws.security.auth.username property with client as value.

We also need to change the OWSM client policy to oracle/wss11_saml_token_identity_switch_with_message_protection_client_policy on the reference web service binding.

Deploy your composite.

Too bad, this is not enough we also need to give my SOA Composite the right permissions to do identity switching. Go the Enterprise Manager (EM) application of the SOA Suite.  Open the WebLogic Domain treenode and select your SOA domain. In the Domain menu (right window)  go to Security -> System Policies.

Select Codebase as Type and search. Select a Codebase policy and do Create Like.

Use file:${common.components.home}/modules/oracle.wsm.agent.common_11.1.1/wsm-agent-core.jar as value in the Codebase field and click on Edit.

Enter oracle.wsm.security.WSIdentityPermission in the Permission Class field. The action is always assert. The Resource Name is your Composite Name which does the identity switching.


Virtual Users with User roles
The last part is virtual users, in this section will we add some roles and change some attributes on the SOA Suite client user. Change the policy back on the composite reference ( oracle/wss11_saml_token_with_message_protection_client_policy ) and also use client as username in the web service proxy client.

First change some client user attributes. We can do this in the security realm of the SOA Suite WebLogic Domain.


Normally the user is only mapped to the user located at the JAX-WS server. To make virtual servers work we need to add a property to the saml.loginmodule located at the JAX-WS server.  For this we need to go the EM application of the JAX-WS Server. Open the WebLogic Domain treenode and select your JAX-WS domain. In the Domain menu (right window)  go to Security -> Security Provider Configuration.

Click on Edit and add a custom property oracle.security.jps.assert.saml.identity with value true.


Restart the JAX-WS WebLogic server.

We also need to do something in the SOA Composite.
Override the following properties

user.attributes with value  displayname,employeenumber ( use , to separate ldap attributes you want to pass on )
user.roles.include with value true
subject.precedence with value true

Deploy the composite and when you test your test client. You will see the following output on the JAX-WS Server.


virtual found
saml issuer: www.amis.nl

SAML attribute: employeenumber
value: 100

SAML attribute: Roles
value: Operators
value: AdminChannelUsers
value: IntegrationOperators
value: IntegrationMonitors
value: Monitors

SAML attribute: displayname
value: SAML client





14 comments:

  1. Thank you for an article!
    I have a question about similar situation: an ADFS+AD server and WebLogic with bpel needed to be protect ed with adfs SAML tokens.
    A question i have: how Weblogic maps his own users-groups (created in wl /console) with ActiveDirectory users-groups? Where to configure this mapping?

    ReplyDelete
  2. Hi,

    Did you read this http://biemond.blogspot.com/2011/10/using-fmw-identitystore-for-your-user.html

    is your AD authenticator the first authenticator in the weblogic console.

    thanks

    ReplyDelete
  3. It looks similar.
    I have been thinking its can be done inside wl/console.
    Thank you!

    ReplyDelete
  4. Great article.

    I have a question. Where you have HelloService, I have Sharepoint web service. Which needs Kerberos authentication.

    How can I provide the credentials for Kerberos authentication for the Sharepoint web service in External References?

    Do you have any example for that like this one?

    Thanks

    Rakesh

    ReplyDelete
  5. Hi,

    For sharepoint I think you need to enable saml on that server or use OWSM this support kerberos.

    like I did in this blog http://biemond.blogspot.com/2011/09/using-owsm-kerberos-policies.html

    thanks

    ReplyDelete
  6. Edwin,
    thanks for contributing openly with your examples and advise.

    After setting up the "basic SAML test" according to your prescribed scenario and with your code we have run into a message on one of the servers looking for 'orakey' in one of the requests made by components involved.

    Would you know if there is any extra configuration needed? Oracle documentation mentions this key/alias as WebCenter required. Would it have gotten overwritten with the keystore setup according to the prescribed above steps?


    Thanks

    ReplyDelete
    Replies
    1. Hi,

      It is a OWSM setting and orakey is the default value , this key is in the OWSM credential store . When you configure the key for signing and encryption then these values are added.

      Good luck

      Delete
  7. Hi Edwin, thanks for your examples, have been very useful for me.
    Excuse my bad writing of English. I have a question:

    I have an scenario with 2 Weblogic Domains, the first have a Oracle Portal and the second is a SOA Domain.

    Between the 2 domains there is a configuration of SSO using SAML, from the portal is invoked an ADF Application deployed in the SOA Domain, this app no longer requires the credentials because of the SSO configuration.

    In the OSB of the SOA Domain there is a Proxy Service with the OWSM Policy "oracle/wss11_saml_token_with_message_protection_service_policy" attached; I want to consume this service from the ADF App or from a BPM Process propagating the same credentials of the user authenticathed in the ADF Application.

    Is this possible Edwin?, I have tried whit a Web Service Data Control in the ADF App and configuring the Web Service Security with the policy required and overriding the property csf-key and it works. But I require to consume the service with the credentials of the user authenticathed and not with the key "csf-key" configured.

    I hope I have explained the problem correctly.

    Thank you!!

    ReplyDelete
    Replies
    1. Hi,

      When you are authenticated in the adf Application, then, the user subject is automatically provided to the ws. When you an OWSM policy with a user name token it should work. You got everything on one domain so why don't you use username token instead of saml , the username of the saml sso will be used. Of course the user also need to exist on the SOA domain. So between portal and adf you use saml sso and on the OSB use username token policies.
      Don't know why you need to override Csf key , what username do you get on the OSB service. Saml is good for making a trust between 2 domain . Within one domain you can use username token policies and maybe with message protection ,for this you need to configure OWSM keystores.

      Thanks

      Delete
    2. Thanks Edwin,

      I did a test. I attached a policy without message protection, the "oracle/wss_username_token_service_policy" OWSM Policy to my proxy Service. In the ADF Application this WS is invoked from a backing bean, using the code generated by a Web Service Proxy, the code is like:

      SecurityPoliciesFeature securityFeatures = new SecurityPoliciesFeature(new String[] { "oracle/wss_username_token_client_policy" });

      RequisitosService requisitosService = requisitosService_Service.getRequisitosServicePort(securityFeatures);

      requisitosService.getRequisitosProductos.doOperation();


      Im authenticathed in the ADF Application, but the credentials are not provided to the WS. In the log appears the next message "oracle.wsm.common.sdk.WSMException: WSM-00015 : The user name is missing"

      If I agreggate the credentials in the code of the backing bean:

      reqContext.put(BindingProvider.USERNAME_PROPERTY, "weblogic");
      reqContext.put(BindingProvider.PASSWORD_PROPERTY, "welcome1");

      It works; but what I need is the credentials to propagate automatically and not programatically.

      It is possible?

      Thanks in advance...

      Delete
    3. Hi,

      the trick is when you use OPSS then it should work with ADF security and OWSM see http://docs.oracle.com/cd/E21764_01/core.1111/e10043/underjps.htm#BABBFFDC

      What do you use as authentication provider, do you use the internal wls ldap one ( this is the OPSS one ) and is the adf app deployed to the soa suite server or at least the same domain. else you need to enable cross domain security and use the same domain password )

      Can you test this.

      You can add your own ldap server as authentication provider and enable ovd. this should also work.
      http://biemond.blogspot.com/2011/10/using-fmw-identitystore-for-your-user.html

      hope this helps. I will also make a testcase.

      Delete
    4. Hi,

      it looks we need to use a SAML OWSM policy, this allows us identity propagation between ADF and OWSM. I will try to make a testcase where ADF and SOA are on the same domain.

      Delete
    5. Ok,

      i got it working on the same domain or on 2 domains

      first deploy your jax-ws service or soa suite service with the following policy
      oracle/wss11_saml_token_with_message_protection_service_policy

      then deploy this to the soa server or the saml server.

      Go to the ADF app which has ADF Security
      create a adf ws datacontrol and provide the ws url. ( or ws proxy client )
      select the datacontrol.dcx file and change the security settings in the structure window. clock on the ws and use right click -> define ws security

      select the right owsm client policy -> wss11_saml_token_with_message_protection_client_policy

      and override properties
      saml.issuer.name = www.oracle.com (default ) or your own
      ikeystore.recipient.alias = samlkey when you use above example or serverkey when you use it on 1 domain.

      deploy it on the soa suite domain and log in , start it up and invoke service client

      then you see the username is passed on ( protected ) .

      I will make a blog about it.

      thanks Edwin.

      Delete
    6. Thank you very much Edwin.

      I was doing the same thing, and now it works!, I invoke the Proxy Service in 2 ways:

      1. Using the code generated by a Web Service Proxy in a backing bean in the ADF App.

      2. Using a WS Data Contorl like you explain me.

      Thanks Edwin, i hope we keep in touch!!!

      Delete