Configuring SAML Federation between Oracle Identity Cloud Services and MS Azure AD

Introduction The intent of this post is describing the mechanics for configuring very basic SAML Federation between Oracle Identity Cloud Services (IDCS) and Microsoft Azure AD. The scenario in mind is having Azure AD as an Identity Provider to IDCS. The required configuration in Azure AD is essentially the same as presented in Paulo’s excellent post, where he describes […]

OAM Protected SPAs and Same-Origin Policy

Introduction On a previous post, I described the usage of OAM’s SAML Identity Assertion in the context of SPA (Single Page Applications) and how easy it is to take advantage of it for securely propagating the end user identity from the client to the backend services. However, that post is written with the assumption that […]

Exploring OAM’s SAML Identity Assertion

Introduction OAM (Oracle Access Manager) has an interesting feature that often goes unnoticed to a considerable number of people wishing to tackle the problem of identity propagation. It’s OAM’s ability to generate a secure token embedding user information as a result of successful authentication or authorization. My colleagues Rob Otto and Simon Kissane have talked […]

Social Federation with OAM Mobile & Social in Native iOS Applications

Introduction I’ve already posted an article about Social Federation with Mobile & Social (M&S) for web applications protected by Oracle Access Manager (OAM), showing users being authenticated against social network providers, like Google and Linkedin. My coworker Chris Johnson also blogged about using Mobile & Social in a native iOS application. In his post, user […]

OAG/OES Integration for Web API Security: skin and guts

Introduction When it comes to defining a strategy for web API security, OAG (Oracle API Gateway) and OES (Oracle Entitlements Server) together present a very interesting choice and are a very powerful combination indeed. In this post we’re going to take a look at what each component brings in (the skin) and then get our […]

Identity Propagation from OAG to REST APIs protected by OWSM

Introduction This post describes the necessary configuration for propagating an end user identity from OAG (Oracle API Gateway) to REST APIs protected by OWSM (Oracle Web Services Manager). The requirements are: 1) Have a Java Subject established in the REST API implementation. 2) Prevent direct access to the REST API, i.e., only OAG should be […]

Where has your LDAP connection pool gone?

Introduction You have deployed Oracle BPM and decided to run some load tests against it. You’re concerned, among other things, about the behavior of your backend LDAP server under peak times, whether it’s going to be able to handle the load or not. You check the security providers settings in Weblogic Server and see you […]

Part 4: Kerberos Authentication, RBAC and SAML identity propagation in OAG

Introduction This post is the fourth and last one of a series by Andre Correa and Paulo Pereira on OAG (Oracle API Gateway). In the first post we introduced the use case and talked about the Kerberos authentication part. In the second post we talked about Role Based Access Control. In the third post we described how to propagate the authenticated […]

Part 3: Kerberos Authentication, RBAC and SAML Identity Propagation in OAG

Introduction This post is the third one of a series by Andre Correa and Paulo Pereira on OAG (Oracle API Gateway). In the first post we introduced the use case and talked about the Kerberos authentication part. In the second post we talked about Role Based Access Control. In this one we describe how to […]

Part 1: Kerberos Authentication, RBAC and SAML identity propagation in OAG

Introduction This post is the first one of a series by Andre Correa and Paulo Pereira on OAG (Oracle API Gateway). Throughout the series, we are going to talk about Kerberos authentication, Role Based Access Control (RBAC) and SAML identity propagation in OAG 11g, formerly known as OEG (Oracle Enterprise Gateway). What follows has been […]

Front-ending a SAML Service Provider with OHS

This is a follow-up to one of my previous posts titled Integrating OBIEE 11g into Weblogic’s SAML SSO, where I mention the following when configuring the Service Provider: “The Published Site URL field value is the base URL for federation services on the server. For SAML2, make sure the webcontext path is saml2. This is […]

Attaching OWSM policies to JRF-based web services clients

I’ve recently came across a question in one of our internal mailing lists where a person was under the impression that he would have to write code to propagate the identity when making a web service call using OWSM policies. My answer was something like: “depending on the type of your client you may have to write some very small piece of code to attach a policy, but you should not write code at all to either retrieve the executing client identity or to do the propagation itself”. Fortunately, I had an unpublished article that applied 100% to his use case. And here it is now (a little bit revamped).

OWSM (Oracle Web Services Manager) is Oracle’s recommended method for securing SOAP web services. It provides agents that encapsulate the necessary logic to interact with the underlying software stack   on both service and client sides. Such agents have their behavior driven by policies. OWSM ships with a bunch of policies that are adequate to most common real world scenarios.

Applying policies to services and clients is usually a straightforward task and can be accomplished in different ways. This is well described in the OWSM Administrators Guide. Looking from the client perspective, the docs describe how to attach policies to SOA references, connection-based clients (typically ADF-based clients) and standard Java EE-based clients using either Enterprise Manager or wlst.

Oracle FMW components (like OWSM agents) are typically deployed on top of a thin software layer called JRF (Java Required Files), providing for the required interoperability with software stacks from different vendors.

This post is a step-by step showing how to code a JRF-based client and attach OWSM policies to it at development-time using Oracle JDeveloper.

This is a 3-step process:

a) Create proxy-supporting classes;
b) Use the right client programming model;
c) Attach OWSM policy to the client;

1. Creating proxy-supporting classes

Very straightforward.
Select a project and go to File -> New and select Web Services in the Business Tier category. On the right side, choose Web Service Proxy and follow the wizard.

proxy1

2. Picking the right client programming model

For clients on 11g R1 PS2 and later, use oracle.webservices.WsMetaFactory. If your client is going to run on 11g R1 or 11g R1 PS1, use the deprecated oracle.j2ee.ws.common.jaxws.ServiceDelegateImpl. All these classes are available in jrf-client.jar file, located at oracle_common/modules/oracle.jrf_11.1.1 folder in your middleware home installation.

2.1 Code sample using oracle.j2ee.ws.common.jaxws.ServiceDelegateImpl (up to 11g PS1)

...
import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.ws.BindingProvider;
import oracle.j2ee.ws.common.jaxws.ServiceDelegateImpl;
import oracle.webservices.ClientConstants;
import oracle.wsm.security.util.SecurityConstants;
import org.w3c.dom.Element;
...
String endpoint = "http://127.0.0.1:7101/B7aFusionWebServices-Model-context-root/MyAppModuleService";
URL wsdlURL = new URL(endpoint+"?WSDL");
ServiceDelegateImpl serviceDelegate = new ServiceDelegateImpl(wsdlURL, new QName("http://xmlns.oracle.com/oracle/apps/", "MyAppModuleService"), oracle.webservices.OracleService.class);
MyAppModuleService port = serviceDelegate.getPort(new QName("http://xmlns.oracle.com/oracle/apps/", "MyAppModuleServiceSoapHttpPort"), MyAppModuleService.class );

InputStream isClientPolicy = <Your_Client_Class_Name>.class.getResourceAsStream("client-policy.xml");
Map<String,Object> requestContext = ((BindingProvider) port).getRequestContext();
requestContext.put(ClientConstants.CLIENT_CONFIG, fileToElement(isClientPolicy));
requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpoint);

// Add other properties here. For identity switching add
// requestContext.put(SecurityConstants.ClientConstants.WSS_CSF_KEY, "<AppID_csf_key>");
port.sayHello(name);
...

// Utility method to convert an InputStream into an org.w3c.dom.Element
public static Element fileToElement(InputStream f) throws IOException, Exception {
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
builderFactory.setValidating(false);
builderFactory.setNamespaceAware(true);
builderFactory.setIgnoringElementContentWhitespace(true);
builderFactory.setIgnoringComments(true);
return builderFactory.newDocumentBuilder().parse(f).getDocumentElement();
}

In this sample, MyAppModuleService is the port interface generated by JDeveloper in the step before.

The parameters to the QName object constructor are the target namespace and the service/port name, both found in the web service wsdl.

2.2 Code sample using oracle.webservices.WsMetaFactory (11g PS2 +)

...
import java.net.URL;
import java.util.Map;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.Service;
import oracle.webservices.ClientConstants;
import oracle.webservices.ImplType;
import oracle.webservices.WsMetaFactory;
import oracle.wsm.security.util.SecurityConstants;
import org.w3c.dom.Element;
...

String endpoint = "http://localhost:7101/WebServiceSample2-WebService-context-root/GreetingPort";
URL serviceWsdl = new URL(endpoint + "?wsdl");
QName serviceQName = new QName("http://sample2.webservice/","GreetingService");
QName portQName = new QName("http://sample2.webservice/","GreetingPort");


Service proxyService = WsMetaFactory.newInstance(ImplType.JRF).createClientFactory().create(serviceWsdl, serviceQName);
Greeting port = proxyService.getPort(portQName, Greeting.class);

InputStream clientPolicyStream = Servlet1.class.getResourceAsStream("client-policy.xml");
Element clientConfigElem = this.fileToElement(clientPolicyStream);

Map<String,Object> requestContext = ((BindingProvider) port).getRequestContext();
requestContext.put(ClientConstants.CLIENT_CONFIG , clientConfigElem);
requestContext.put(SecurityConstants.ClientConstants.WSS_CSF_KEY,"servlet1-key");

port.sayHello();

 

In this sample, Greeting is the port interface generated by JDeveloper in the step before.

The parameters to the QName object constructor are the target namespace and the service/port name, both found in the web service wsdl.

3. Attaching the OWSM policy

The OWSM policy is passed as an org.w3c.dom.Element to the requestContext Map. One way to come up with such Element is through an XML file that contains a reference to the actual OWSM client-side policy to be used.

InputStream clientPolicyStream = Servlet1.class.getResourceAsStream("client-policy.xml");
Element clientConfigElem = this.fileToElement(clientPolicyStream);
Map<String,Object> requestContext = ((BindingProvider) port).getRequestContext();
requestContext.put(ClientConstants.CLIENT_CONFIG , clientConfigElem);
Here are the XML file (client-policy.xml) contents. You have to create a file like this and make it available to your application CLASSPATH. It references the OWSM policy to be given to the requestContext Map.
<?xml version="1.0" encoding="UTF-8"?>
<oracle-webservice-clients>
<webservice-client>
<port-info>
<policy-references>
<policy-reference uri="oracle/wss11_saml_token_client_policy" category="security"/>
</policy-references>
</port-info>
</webservice-client>
</oracle-webservice-clients>

 

For SAML-based identity propagation, use any of the SAML client policies.

In this case, the policy retrieves the user name Principal from the Java Subject who is running the client and adds it to a generated SAML token in the SOAP call header.

3.1. Switching Identities

To propagate a new identity rather than the one executing the client, use a username token-based policy. By the way, the sample using oracle.webservices.WsMetaFactory may use oracle/wss_username_token_client_policy as the policy name in order to propagate the identity referred by the servlet1-key csf key.

Map<String,Object> requestContext = ((BindingProvider) port).getRequestContext(); 
requestContext.put(SecurityConstants.ClientConstants.WSS_CSF_KEY, "servlet1-key");

 

“servlet1-key” must match a key entry in the domain-level credential store that holds the username/password pair required for the use case implementation. Here’s how you create a key for OWSM usage in the credential store using wlst:

wls:/offline> connect()
Please enter your username :weblogic
Please enter your password :
Please enter your server URL [t3://localhost:7001] :t3://localhost:7101
Connecting to t3://localhost:7101 with userid weblogic
...
Successfully connected to Admin Server 'DefaultServer' that belongs to
domain 'DefaultDomain'.
Warning: An insecure protocol was used to connect to the
server. To ensure
on-the-wire security, the SSL port or
Admin port should be used instead.
wls:/DefaultDomain/serverConfig>
createCred(map="oracle.wsm.security",key="servlet1-key",user="weblogic",password="welcome1")

 

In this case, the policy retrieves the username/password pair from the credential store and adds it to a generated username token in the outgoing SOAP header.

What if the client is a Java SE application?

So far so good, but what happens when the client runs on a Java SE environment?

a) How do you get a hold of the OWSM policy?

Add oracle_common/modules/oracle.wsm.policies_11.1.1/wsm-seed-policies.jar, available in your middleware home installation, to the client CLASSPATH. All policy files are in it.

b) How to deal with the credential store (for identity switching) ?

You need to supply the client with 2 files:

1 – cwallet.sso, which is a file-based credential store. In order to author cwallet.sso, I recommend that you use wlst’s createCred command. Yes, you’ll need a JRF-enabled Weblogic server to create it.

2 – jps-config.xml, through -Doracle.security.jps.config Java option. In jps-config.xml, make sure there’s a credential store service instance available for the default context pointing to the folder where cwallet.sso is located, as shown in this sample jps-config.xml:

<?xml version = '1.0' encoding = 'UTF-8'?>
<jpsConfig xmlns="http://xmlns.oracle.com/oracleas/schema/11/jps-config-11_1.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.oracle.com/oracleas/schema/11/jps-config-11_1.xsd">
<property value="doasprivileged" name="oracle.security.jps.jaas.mode"/>
<propertySets/>
<serviceProviders>
<serviceProvider class="oracle.security.jps.internal.credstore.ssp.SspCredentialStoreProvider" name="credstore.provider" type="CREDENTIAL_STORE">
<description>Credential Store Service Provider</description>
</serviceProvider>
<serviceProvider class="oracle.security.jps.internal.idstore.xml.XmlIdentityStoreProvider" name="idstore.xml.provider" type="IDENTITY_STORE">
<description>XML-based IdStore Provider</description>
</serviceProvider>
<serviceProvider class="oracle.security.jps.internal.policystore.xml.XmlPolicyStoreProvider" name="policystore.xml.provider" type="POLICY_STORE">
<description>XML-based PolicyStore Provider</description>
</serviceProvider>
<serviceProvider class="oracle.security.jps.internal.login.jaas.JaasLoginServiceProvider" name="jaas.login.provider" type="LOGIN">
<description>Login Module Service Provider</description>
</serviceProvider>
<serviceProvider class="oracle.security.jps.internal.keystore.KeyStoreProvider" name="keystore.provider" type="KEY_STORE">
<description>PKI Based Keystore Provider</description>
<property value="owsm" name="provider.property.name"/>
</serviceProvider>
</serviceProviders>
<serviceInstances>
<serviceInstance provider="credstore.provider" name="credstore">
<property value="./" name="location"/>
</serviceInstance>
<serviceInstance provider="idstore.xml.provider" name="idstore.xml">
<property value="./jazn-data.xml" name="location"/>
<property value="jazn.com" name="subscriber.name"/>
</serviceInstance>
<serviceInstance provider="policystore.xml.provider" name="policystore.xml">
<property value="./jazn-data.xml" name="location"/>
</serviceInstance>
<serviceInstance provider="jaas.login.provider" name="idstore.loginmodule">
<property value="oracle.security.jps.internal.jaas.module.idstore.IdStoreLoginModule" name="loginModuleClassName"/>
<property value="REQUIRED" name="jaas.login.controlFlag"/>
<property value="true" name="debug"/>
<property value="true" name="addAllRoles"/>
<property value="false" name="remove.anonymous.role"/>
</serviceInstance>
<serviceInstance location="./default-keystore.jks" provider="keystore.provider" name="keystore">
<description>Default JPS Keystore Service</description>
<property value="JKS" name="keystore.type"/>
<property value="oracle.wsm.security" name="keystore.csf.map"/>
<property value="keystore-csf-key" name="keystore.pass.csf.key"/>
<property value="sign-csf-key" name="keystore.sig.csf.key"/>
<property value="enc-csf-key" name="keystore.enc.csf.key"/>
</serviceInstance>
</serviceInstances>
<jpsContexts default="default">
<jpsContext name="default">
<serviceInstanceRef ref="credstore"/>
<serviceInstanceRef ref="idstore.xml"/>
<serviceInstanceRef ref="policystore.xml"/>
<serviceInstanceRef ref="idstore.loginmodule"/>
<serviceInstanceRef ref="keystore"/>
</jpsContext>
</jpsContexts>
</jpsConfig>

Hope this helps some of you dear readers out there.

LibOVD: when and how

LibOVD, introduced in FMW 11.1.1.4, is a java library providing virtualization capabilities over LDAP authentication providers in Oracle Fusion Middleware. It is delivered as part of OPSS (Oracle Platform Security Services), who is available as part of the portability layer (also known as JRF – Java Required Files). In other words, if you are a JDeveloper, WebCenter, SOA or IAM customer, you already have libOVD.

LibOVD provides limited virtualization capabilities when compared to its big brother OVD (Oracle Virtual Directory), who is a full-blown server implementing the LDAP protocol with far more advanced virtualization features, including OOTB support for LDAP and database backend servers, advanced configuration for adapters, out-of-box plug-ins as well as a plug-in programming model allowing for almost limitless possibilities in transforming data and connecting to external data sources.

1. When

 

LibOVD is primarily designed to work as an embedded component for FMW components who need to look up users and groups across distinct identity providers. If you had a chance to look at this post, you already know the User/Role API can take into account only one authentication provider.

Take SOA’s Human Workflow component, for instance. Customers frequently have an external identity store, like OID or Active Directory, holding the application end users and related enterprise groups. But they also often want to keep Weblogic’s embedded LDAP server for administration accounts, like weblogic user.  Or they simply have an LDAP server in the US and another one in Brazil and want to bring all those users together. Using User/Role API alone is not enough.

That does not mean libOVD can be used only by FMW components. It is ok that your custom applications employ libOVD and that’s a given once you enable libOVD for a given domain. However, do not expect any of those features only available in OVD. A common mistake is expecting libOVD to work with a database authenticator. LibOVD is only for LDAP authenticators.

Another use case for libOVD is known as split profile, where information about the same identity exists in more than one LDAP-based identity store and your applications need a consolidated view. More information here: http://docs.oracle.com/cd/E21764_01/core.1111/e10043/apidvirtual.htm#CIHDGFIC

2. How

 

LibOVD is activated when you set the property virtualize=true for the identity store provider in jps-config.xml:

<serviceInstance name="idstore.ldap" provider="idstore.ldap.provider">
<property name="idstore.config.provider" value="oracle.security.jps.wls.internal.idstore.WlsLdapIdStoreConfigProvider"/>
<property name="CONNECTION_POOL_CLASS" value="oracle.security.idm.providers.stdldap.JNDIPool"/>
<property name="virtualize" value="true"/>
<property name="OPTIMIZE_SEARCH" value="true"/>
</serviceInstance>

It is possible to hand-edit jps-config.xml, but I recommend that you use Enterprise Manager to set it up, because the minimum mistake in jps-config.xml can get the WLS domain into a non-startable state.

Note: Unless your application makes explicit usage of a different JPS Context, this is domain-wide set up, impacting all applications deployed in that domain, both from authentication and user/group lookup perspectives.

Enabling libOVD using Enterprise Manager:

Navigate to the domain Security Provider Configuration screen and click the Configure button, as shown:

 SettingVirtualize_1

Then use the Add button to add the property.

SettingVirtualize_2

When you enable the virtualize flag, a new folder structure along with some files are created under $DOMAIN_HOME/config/fmwconfig folder.

libOVD_folders

Notice the default folder name: it refers to the default JPS context in jps-config.xml, which in turn refers to the idstore service instance for which libOVD has been configured.

These are familiar files to readers used to OVD. adapters.os_xml, for instance, lists the configured adapters for libOVD. An adapter is created for each authenticator listed in Weblogic’s config.xml.

3. Be Aware

 

Within a single adapter, in order to search across both users and groups search bases, libOVD sets the adapter’s root to be the common base between them. For example, let’s say users and groups search bases are defined as cn=users,dc=us,dc=oracle,dc=com and cn=groups,dc=us,dc=oracle,dc=com, respectively. In this case, the adapter’s root is set to dc=us,dc=oracle,dc=com.

Such configuration may cause a performance overhead if customers happen to have more users and groups distributed across other nodes that are also children of the common root but who are not necessarily required by the applications running on Weblogic. Wasted LDAP queries.

Notice the undocumented property OPTIMIZE_SEARCH in the jps-config.xml snippet presented before. It is the solution to the problem just described because it forces libOVD to search only within the users and groups search bases defined in the authenticator providers. No searches are performed elsewhere.

In order to take advantage of OPTIMIZE_SEARCH, make sure to get the appropriate patch for the corresponding release of FMW:

  • FMW 11.1.1.6: 14693648
  • FMW 11.1.1.5: 14919780
  • FMW 11.1.1.4: 14698340

4. Managing libOVD

 

libOVD can be managed via wlst.sh. When connected, type

> help(‘OracleLibOVDConfig’)

and check the available commands.

5. Debugging libOVD

 

To debug libOVD, create a logger for oracle.ods.virtualization package in your server’s logging.xml file. Here’s a snippet.

<logger name=‘oracle.ods.virtualization’ level=‘TRACE:32’>

 <handler name='odl-handler'/>
</logger>

5 minutes or less: Indexing Attributes in OID

I’ve written this short post as just a note to myself quite some time back. Since I had to rely on it quite a couple of times, I thought it would be worth sharing it with our readers.

It may be too basic to some people, but I am sure others out there had, are having or will have issues when running searches with LDAP filters against OID (Oracle Internet Directory), especially if those filters refer to custom attributes. The information presented here is certainly available in OID Administration Guide at Managing Directory Schema chapter, but it still might be a little bit scattered.

First and foremost: an attribute is only searchable in OID if it is indexed. This is definitely not the case of any your brand new custom attributes.

Any search containing a non-indexed attribute in the ldap filter will return something like:

> ldapsearch -h localhost -p 6501 -D "cn=orcladmin" -w welcome1 -b "cn=users,ou=mycompany,dc=com"–s sub "assistant=kathy"

ldap_search: DSA is unwilling to perform
ldap_search: additional info:
LDAP Error 53 : [LDAP: error code 53 - Function Not Implemented, search filter attribute assistant is not indexed/cataloged]

Second, directly from OID Administration Guide, About Indexing Attributes section:

You can index only those attributes that have:

The error message above is straightforward. But how do you create an index for the attribute?

There are 3 ways to index attributes in OID: i) using ODSM (Oracle Directory Services Manager), ii) using ldapmodify or iii) using the catalog tool.

ODSM and ldapmodify are only good if you have just defined the attribute and there’s still no data associated with it. Only values added after the index creation are indexed.

The safest approach is running OID’s catalog tool, because it indexes all existing attribute values.

1) Indexing attributes using ODSM:

 

ODSM_IndexingAttr

Here I’ve randomly picked a non-indexed attribute, assistant. The Indexed checkbox (pointed by the blue arrow) is read-only. You actually have to click on the button pointed by the red arrow first.

2) Indexing attributes using ldapmodify:

 

Create a small ldif file as the one below and run ldapmodify using the –f argument.

dn: cn=catalogs 
changetype: modify
add: orclindexedattribute
orclindexedattribute: assistant

> ldapmodify –h <host> –p <port> –D <admin user dn> –w <password> –f <ldif file>

3) Indexing attributes using the catalog tool:

 

a) Set the ORACLE_HOME environment variable to the your IDM ORACLE_HOME installation. If you’ve accepted the names given to you by the Oracle Installer, this value is typically $MW_HOME/Oracle_IDM1. The catalog tool is found under $ORACLE_HOME/ldap/bin

b) Set the ORACLE_INSTANCE environment variable to your IDM instance installation. If you’ve accepted the names given to you by the Oracle Installer, this value is typically $MW_HOME/asinst_1. Under $ORACLE_INSTANCE you should find a tnsnames.ora under the config folder. This is where the catalog tool gets your database connection details.

c) Run

$ORACLE_HOME/ldap/bin/catalog connect=”OIDDB” add=true attribute=”assistant”

 

If you want to delete an existing index:

$ORACLE_HOME/ldap/bin/catalog connect=”OIDDB” delete=true attribute=”assistant”

where OIDDB is the actual tnsname defined in your IDM instance tnsnames.ora file.

Before I forget it: HowTo SAML 2.0 IdP-initiated flow in Weblogic

I’d better do it now, otherwise I will forget the details.

Quite some people think that all an IdP-initiated flow requires is the target application URL in the consumer side. This is actually nothing more than a SP-initiated flow. In this way, you’ll hit the Service Provider with no SAML Assertion, will be redirected back to the IdP for the SAML assertion and then sent back to the Service Provider.

An IdP-initiated flow actually first needs to get a hold of a SAML assertion for the authenticated user. The assertion is then submitted along with the request to the target application URL. If the Service Provider decides to accept the assertion, the user is granted access. There’s no need to come back to the IdP for the assertion.

This short post is about how to configure Weblogic SAML 2.0 for an IdP-initiated flow.

The URL to be given to the end user for an IdP initiated flow in Weblogic is:
http://<idp-server>:<port>/saml2/idp/sso/initiator?SPName=<SP-Partner-Name>&RequestURL=<target-application-url>

where:

  • saml2/idp/sso/initiator is the IdP service responsible for processing IdP-initiated request flows.
  • <SP-Partner-Name> is the Service Provider partner name you have configured for the Identity Provider.
  • <target-application-url> is the application you want to access in SSO mode on the Service Provider side.

Here’s an example of a real URL:

http://idp.us.oracle.com:7003/saml2/idp/sso/initiator?SPName=WebSSO-SP-Partner-0&RequestURLhttp://sp.us.oracle.com:9704/analytics

The SPName parameter value actually refers to a partner you’ve configured in Weblogic for your Identity Provider. A Weblogic Identity Provider for SAML 2 requires a SAML2CredentialMapper. And the partner we’re talking about is configured (usually given as a metadata file) in SAML2CredentialMapper’s Management tab, as shown:

SP-Partner

Notice the Name “WebSSO-SP-Partner-0”. It’s the one you need to use as the SPName value in the URL.

Ok, once given the right params, saml2/idp/sso/initiator service will do some magic for us. But we still need to give it a hand. The SP Partner configuration has a parameter called “POST Binding POST Form”. It is the URL containing an HTML form that will post the SAML Response to the SAML Assertion Consumer Service on the Service Provider Side.

post-form

Here’s the post_form.jsp code. Build it into an application and deploy it to the Weblogic server running the Identity Provider.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<%@ page contentType="text/html;charset=windows-1252"%>
<html>
<head>
</head>
<%
String samlResponse = (String) request.getAttribute("com.bea.security.saml2.samlContent");
String relayState = (String) request.getAttribute("com.bea.security.saml2.relayState");
%>
<body onLoad="document.forms[0].submit();">
<FORM METHOD="POST" ACTION="http://sp.us.oracle.com:9704/saml2/sp/acs/post">
<INPUT TYPE="HIDDEN" NAME="RelayState" VALUE="<%=relayState%>"/>
<INPUT TYPE="HIDDEN" NAME="SAMLResponse" VALUE="<%=samlResponse%>">
</FORM>
</body>
</html>

 

3 things to notice:

  1. the form action: refers to the Service Provider Assertion Consumer Service for POST binding.
  2. SAMLResponse: the SAML Response generated by the IdP containing the SAML assertion.
  3. RelayState: a reference to state information maintained at the Service Provider.

That’s it.

Summarizing, the user logs in to the Identity Provider, click on a link like http://<idp-server>:<port>/saml2/idp/sso/initiator?SPName=<SP-Partner-Name>&RequestURL=<target-application-url>. The saml2/idp/sso/initiator service looks into <SP-Partner-Name> for the “POST Binding POST Form” and executes it. The form retrieves SAMLResponse and RelayState from Weblogic and auto-submits itself to saml2/sp/acs/post on the Service Provider. If the SAML assertion is accepted, the user’s browser is redirected to the <target-application-url>.

Enjoy your IdP-initiated flows.

Integrating OBIEE 11g into Weblogic’s SAML SSO

SAML is a way to convey identity information across systems. It is an industry-accepted standard and especially interesting when you need to propagate user information between different security domains, because it can overcome the HTTP cookie limitations in cross-domain scenarios (although there are ways to solve that with OAM today) and implement the concept of  transient federation (also known as virtual users), where the user base is not shared between partners.

I’ve recently came across a scenario requiring OBIEE 11g integration into SAML 2.0 SSO. The requirement was that OBIEE 11g should be able to drive its authorization decisions based on the SAML Subject as well as SAML Attribute Statements from the SAML Assertion generated by a home-built Identity Provider (IdP). This post examine what can be done (and how) in this scenario.

The exact products versions used in this demo are as follows:

  • Platform: Windows XP Server
  • Oracle Weblogic Server 10.3.5
  • Oracle Business Intelligence Enterprise Edition 11.1.1.5

OBIEE 11g (since 11.1.1.3) delegates authentication, authorization and credential management to OPSS, which means users, groups, policies and credentials are all externalized. One typical OPSS deployment mode is using an LDAP server as the general security store for all artifacts. Remember though, at the time of this writing, OID is the only one supported LDAP server for policies.

A quick look at OBIEE 11g overall architecture is necessary to understand what comes up right next. I wouldn’t dare going into the details of OBIEE architecture on this post, so I recommend you take a look at the product official documentation. A good starting point is here.

For our purposes here, the important aspect to notice is that OBIEE has some components that run on Weblogic and some components that do NOT run on Weblogic. The core BI services are provided by the BI Server and BI Presentation Services. These are C-based standalone applications indeed.
Within Weblogic, the BI Presentation Services Plugin interfaces with the standalone BI Presentation Services system component, providing the web experience for end users.

The picture below (borrowed from the product documentation) describes the OBIEE architecture.

OBIEE_Architecture

Of particular interest for our topic is the Security Services component.

In SSO mode, the BI Server components gets the authenticated userid from Weblogic and calls back the Security Services to construct an object (containing user principals, like userid and groups) that is returned back to BI server, who in turn uses it to drive authorization decisions on its internal objects. This alone allows OBIEE to consume a SAML Subject for the purpose of authorization decisions. So far, so good.

But what about using SAML Attribute Statements to drive authorization decisions within BI server? That would require SAML Attribute Statements to be persisted into OBIEE identity store once the SAML authentication request hits the server, so that Security Services could construct the necessary object when called back by BI Server. But SAML Attribute Statements are not persisted in the identity store.

Such characteristic essentially moots SAML Attribute Statements in this type of scenario. And that makes the usage of virtual users along with attribute processing irrelevant in a SAML Identity Asserter which also dismisses the need of a SAML Authenticator.

I am not saying this is something impossible to be done. It would require some custom work.

Long story short, in 11.1.1.5, out-of-the-box, OBIEE can consume the Subject out of a SAML Assertion, and that userid has to exist in the configured identity store for OBIEE.


When a SAML assertion is received by the Weblogic server hosting the target application, Weblogic’s SAML Identity Asserter parses the assertion and interacts with the ACS (Assertion Consumer Service) to validate it. If everything is ok, the identified user in the SAML assertion is passed down to the next authentication provider, who effectively authenticates the user and instantiates a Java Subject in the container. Make sure one of your authentication providers following SAML2IdentityAsserter is able to authenticate the user.

AuthenticationProviders

In my demo, the SAML assertion is produced by another Weblogic server working as the IdP (Identity Provider), via a SAML 2 Credential Mapper. A credential mapper essentially maps an existing java Subject to some credential.

From a configuration perspective, there are three main things do be done on OBIEE Weblogic server side: i) configuration of a SAML 2.0 Identity Asserter along with enabling SAML 2.0 Service Provider, ii) change of Analytics’ web.xml and weblogic.xml deployment descriptors and subsequent redeployment and iii) configuration of OBIEE for SSO in Enterprise Manager. For completion purposes, I also show how to configure a Weblogic server to be the Identity Provider.

If you already know how to configure Weblogic Federation Services and what to expect when OBIEE managed servers are in a cluster, you can safely skip the next section as well as Configuring the Identity Provider section. There’s really nothing special particular do OBIEE in them.

If you’re configuring both the SP and IdP in a single host (for testing purposes), make sure to refer to each of them using different names. For example, in my setup, the SP is sp.us.oracle.com and the idp is idp.us.oracle.com.

1. Configuring the Service Provider

Reference documentation is here. Here’s a tour and some notes over my configuration:

1) Add a SAML 2 Identity Asserter to the set of authentication providers and restart the Admin server. This is necessary for enabling configuring the server as a Service Provider (SAML 2.0 Service Provider tab in Federation Services)

2) Configure Weblogic Federation Services by filling in SAML 2.0 General tab for the Service Provider server. In the case of OBIEE, this is bi_server1. The information entered here is given to partners through a metadata file and is used as a means to establish trust across servers.

ServiceProviderGeneralInfo


Couple of important notes here:

  • The Entity ID field value determines the name of this SAML server to its partners. If you have a cluster, make sure every member of the cluster is assigned the same value. An IdP will use this value to identify the Audience to which the SAML message is addressed. As any server in the cluster should be able to process the message. By the way, when configuring a cluster of SAML servers, make sure their configuration is exactly the same. Notice you can use Weblogic’s recording capabilities to save your actions into a script and replay that in the other servers using wlst.
  • The Published Site URL field value is the base URL for federation services on the server. For SAML2, make sure the webcontext path is saml2. This is going to be used in the metadata file as the prefix to build the ACS (Assertion Consumer Service) endpoint necessary for allowing an Identity Provider to properly communicate with this Service Provider. For example, an Identity Provider would be provided the following ACS endpoint is the above Published Site URL is specified:

IdP_ACS_Configuration

  • When OBIEE managed servers are in a cluster, there’s typically an HTTP load balancer in front of the servers. In such case, make sure the Published Site URL refers to the name and port of the load balancer, because they are the ones the IdP needs to know. And also, make sure the load balancer is configured for session affinity. Reason being the SP ACS is a stateless application, that upon creating a session, redirects the browser to the requested URL (/analytics). If that redirection hits a different server in the cluster, there’ll be no session there and the user will be sent back to the IdP who will ask for credentials again.
  • Also, when Weblogic SAML services are in a cluster, you must use RDBMS as Weblogic server security store to avoid synchronization issues of SAML data across servers. Such requirement is for SAML data only, it has nothing to do with application session management, which is configured on a per application basis. And RDBMS should be set as the security store from the ground up, when the domain is first created. Trying to change the security store from embedded LDAP to RDBMS is not recommended.

3) Enable BI managed server as a  SAML2.0 Service Provider.

EnablingServiceProvider


Important Note:

  • Default URL is invoked whenever a requester hit this Service Provider without an specific target service URL.

4) Export the SP configuration to a metadata file. Notice that any subsequent changes to your SP configuration will require a new export. Click Publish Metadata button in SAML 2.0 General tab and save it to a file. Examine the file contents. Notice the presence of an X509 certificate, to be used by the partner to encrypt data targeted to this Service Provider. Yes, the certificate is obtained from the Identity keystore configured for the server.

5) Get the IdP metadata file and import it as a Web SSO partner in the Management tab of SAML 2
Identity Asserter configuration. You should end up with something like this:

IdPmetadataImport

Click the partner name and edit the configuration:

IdPmetadataConfiguration


Important Notes:

  • Notice that Virtual User and Process Attributes are not checked. They only make sense if you can use a SAML Authenticator.
  • Redirect URIs are the set of URIs that when called trigger the SAML SSO mechanism. It is a must that they are also secured by the container, otherwise Weblogic won’t trigger the authentication process. Specifically, you must make sure that those mentioned applications use CLIENT-CERT as the auth-method in theirs web.xml.

2. Changing Analytics’ web.xml for security constraint and adding weblogic.xml for role assignments

As previously mentioned, Weblogic server must be able to trigger container authentication upon an unauthenticated request for a URI specified in the set of Redirect URIs defined in the Service Provider partner configuration. Analytics application already ships with CLIENT-CERT auth-method, which is what we want. However, it does not define any security constraints about which users should be allowed access to the application.

OOTB, OBIEE defines three groups: BIAdministrators, BIAuthors and BIConsumers, who are respectively assigned to three application roles in OPSS policy store: BiAdministrator, BIAuthor and BIConsumer. Each of these roles are obviously assigned distinct permissions across the system. Look at ${BI_DOMAIN}/config/fmwconfig/system-jazn-data.xml file in a default OBIEE installation for such definitions.

We need to grant those 3 groups access to the Analytics application in the standard JavaEE way, i.e., by adding a security-constraint to any resource under the analytics web context in web.xml. Additionally, we must map the role name in the security-constraint to those 3 groups in weblogic.xml.

You’ll need to “unjar” the analytics application, make the changes, “rejar” it and redeploy the application. You find the original ear file at ${BI_HOME}/bifoundation/jee/analytics.ear

In web.xml (add <security-constraints> and <security-role> elements):

<security-constraint>
  <web-resource-collection>

    <web-resource-name>BI Analytics</web-resource-name>
    <url-pattern>/*</url-pattern>
  </web-resource-collection>
  <auth-constraint>
    <role-name>allowedGroups</role-name>
  </auth-constraint>
</security-constraint>
<login-config>
  <auth-method>CLIENT-CERT</auth-method>
</login-config>
<security-role>
  <role-name>allowedGroups</role-name>
</security-role>

weblogic.xml (it has to be created in the same folder as web.xml):

<?xml version = ‘1.0’ encoding = ‘windows-1252’?>
<weblogic-web-app xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
         xsi:schemaLocation=“http://www.bea.com/ns/weblogic/weblogic-web-app http://www.bea.com/ns/weblogic/weblogic-web-app/1.0/weblogic-web-app.xsd”
         xmlns=“http://www.bea.com/ns/weblogic/weblogic-web-app”>
  <context-root>analytics</context-root>
  <security-role-assignment>
    <role-name>allowedGroups</role-name>
    <principal-name>BIAdministrators</principal-name>
    <principal-name>BIAuthors</principal-name>
    <principal-name>BIConsumers</principal-name>
  </security-role-assignment>
</weblogic-web-app>

Notice the <principal-name>s. They refer to the groups that OBIEE expect to find in the configured identity store. They are groups, not application roles. If you decide to change those names, make sure they match the application role assignments in the policy store.

If you want any existing user accessing the analytics application,  you can map allowedGroups role-name (defined in web.xml) to the users group (instead of BIAdministrators, BIAuthors and BIConsumers) in weblogic.xml. In Weblogic, any authenticated user is automatically assigned to the users group.

3. Configuring OBIEE for SSO in Enterprise Manager

There’s still one more configuration for SSO in OBIEE. In Enterprise Manager, enable SSO and set the provider to “Generic SSO” for OBIEE’s coreapplication, as shown:

SSOEnabling_EM

The screen is reachable via clicking the “coreapplication” link on the left and then selecting “Security” from the “Business Intelligence Instance” drop down menu on the right.

4. Configuring the Identity Provider

Configuration of the IdP is straightforward, very similar to SP’s. Here, we create a SAML2CredentialMapper, enable the server as an IdP and import the SP metadata to the credential mapper configuration.

1) Add a SAML2CredentialMapper to the list of Credential Providers and restart the Admin server.

IdPCredentialProviders

2) Fill in IdP’s General Info tab.

IdP_GeneralInfo

3) Enable the server as an IdP.

IdP_Enabling

4) Get the metadata file exported from the SP and import it as an IdP partner in the SAML2CredentialMapper configuration.

IdP_Partner

Hope this can be useful to someone out there. Lots to digest, I agree. 🙂

Weblogic WS-Trust Client and OWSM interoperability

First, I’d like to take the opportunity to wish you all our readers a great 2012, with plenty of health, joy, care for each other and peace! We really appreciate your interest in our posts and hope to be truly contributing to your daily work. With that said…

Did you guys know Weblogic implements a WS-Trust client?  Did you also know that WS-Trust client can interoperate with web services protected by OWSM policies requiring message protection (signing and encryption) ? Those were very helpful to me in satisfying some important requirements for a customer in a recent proof of concept exercise.

This is a long post. It describes a bunch of things that are more or less available across several official books, but also adds some details that are not easily found, especially if you’re interested in troubleshooting.

The customer adopts OSTS (Oracle Secure Token Service) and wanted an alternative to OWSM (Oracle Web Services Manager) client. OSTS is part of Oracle IAM Suite 11.1.1.5, delivered as an OAM (Oracle Access Manager) add-on. For an introduction to OSTS, check this post.

OSTS leverages OWSM policies to protect its WS-Trust endpoints. OWSM 11.1.1.5 also delivers WS-Trust client policies. When your web services clients can leverage the OWSM WS-Trust client policies, great, it just works. In situations where they can’t, alternate solutions need to be thought. This particular customer had a considerable amount of clients running in Weblogic server 10.3.3, where WS-Trust support is not available in the OWSM runtime. We could have looked at web services frameworks like Apache’s AXIS2 or CXF, but Weblogic’s WS-Trust client was just there, waiting to rescue. As you can see if you follow this post, it saved us quite some coding.

I must say that the approach describe here is by no means a recommended architecture for everyone. Every customer scenario is different and should be thought in light of current and future requirements. I must also say that OWSM is the strategic direction and, as such, should always be the preferred approach.

This is basically what I’ve helped the customer to achieve:

scenario

Here are the interaction details:

1) The client makes an RST (Request Secure Token) using Weblogic’s WS-Trust client to the OSTS requesting for a SAML token to be sent to the ws provider. The client identifies itself to the OSTS with username token credentials in the WSS header, but requests a token on behalf of someone else. In this example, on behalf of the client application executing user.

2) OSTS’ OWSM agent validates the WSS part of the request. It needs to decrypt the message and validate the digital signature added by Weblogic’s WS-Trust client. This is where most of interoperability problems arise. The policy attached to OSTS endpoint is oracle/wss11_username_token_with_message_protection_service_policy

3) After doing some extra validation on the RST and the requestor credentials, the OSTS issues the SAML token (RSTR – Request Secure Token Response).

4) The client calls the ws provider passing the issued SAML token along. SAML confirmation method in this case is Sender-Vouches, which means the ws client signs the SAML token. The policy attached to ws provider is oracle/wss11_saml_token_with_message_protection_service_policy.

5) The ws provider sends the response.

Implementation Details

1) Web Service Proxy

Web service JAX-WS proxy is generated for the web service provider as usual. This is done by Weblogic’s clientgen tool via an ANT build script, as shown below:

<project name="ws-client" default="build">
 <property name="wls.hostname" value="localhost"/>

<property name=“wls.port” value=“9003”/>
<property name=“classes-dir” value=“classes”/>
<property name=“src-dir” value=“src”/>
<path id=“client.class.path”>
<pathelement path=“classes”/>
<fileset dir=“${mw.home}/wlserver_10.3/server/lib”>
<include name=“weblogic.jar”/>
<include name=“wseeclient.jar”/>
</fileset>
<pathelement path=“${java.class.path}”/>
</path>
<taskdef name=“clientgen” classpathref=“client.class.path” classname=“weblogic.wsee.tools.anttasks.ClientGenTask” />
<target name=“build”>
<clientgen wsdl=“http://${wls.hostname}:${wls.port}/webservices/GreetingPort?WSDL”
destDir=“${src-dir}”
packageName=“ws.client”
type=“JAXWS”/>
<javac srcdir=“${src-dir}” destdir=“${classes-dir}” includes=“**/*.java”/>
</target>
</project>

Notice that you need weblogic.jar and wseeclient.jar in the CLASSPATH to run clientgen. These files are located under $MW_HOME/wlserver_10.3/server/lib folder.

You don’t generate proxies for the OSTS endpoint. This is implicitly taken care by WLS WS-Trust client.

2) Client Code

My client is a simple servlet, that actually hides some serious heavy-lifting performed by Weblogic’s WS-Trust client. The code is commented so it explains itself. Look at how simple it is.

You get an instance of the proxy port as you would normally do and add a couple of properties to the BindingProvider object in order to make the WS-Trust client invoke OSTS (lines 35-45).

1: package trunk.interop.ws;

2: 
3: import java.io.IOException;
4: import java.io.PrintWriter;
5: import javax.servlet.*;
6: import javax.servlet.http.*;
7: import javax.xml.ws.BindingProvider;
8: import java.util.Map;
9: import weblogic.wsee.message.WlMessageContext;
10: import weblogic.wsee.jaxrpc.WLStub;
11: import weblogic.wsee.security.WSEESecurityConstants;
12: import javax.xml.soap.SOAPConstants;
13: import ws.client.Greeting;
14: import ws.client.GreetingService;
15:
16: public class TrustClientServlet extends HttpServlet {
17:
18: private static final String CONTENT_TYPE = “text/html; charset=windows-1252”;
19: private static final String TRUST_VERSION = “http://docs.oasis-open.org/ws-sx/ws-trust/200512”;
20: private static final String STS_URL = “http://dogwood.us.oracle.com:14100/sts/wss11user”;
21: private static final String STS_POLICY = “StsWss11UntPolicy.xml”;
22: public void init(ServletConfig config) throws ServletException {
23: super.init(config);
24: }
25: public void doGet(HttpServletRequest request, HttpServletResponse response)
26: throws ServletException, IOException {
27:
28: response.setContentType(CONTENT_TYPE);
29: PrintWriter out = response.getWriter();
30: out.println(“<html>”);
31: out.println(“<head><title>TrustClientServlet</title></head>”);
32: out.println(“<body>”);
33: GreetingService service = new GreetingService();
34: Greeting port = service.getGreetingPort();
35: Map<String, Object> requestContext = ((BindingProvider) port).getRequestContext();
36: // Oracle STS endpoint URL
37: requestContext.put(WLStub.WST_STS_ENDPOINT_ON_SAML, STS_URL);
38: // WS-Policy to talk to Oracle STS
39: requestContext.put(WlMessageContext.WST_BOOT_STRAP_POLICY, this.getClass().getResourceAsStream(STS_POLICY));
40: // WS-Trust version
41: requestContext.put(WSEESecurityConstants.TRUST_VERSION, TRUST_VERSION);
42: // SOAP version
43: requestContext.put(WSEESecurityConstants.TRUST_SOAP_VERSION, SOAPConstants.URI_NS_SOAP_1_2_ENVELOPE);
44: // username for whom a token will be requested
45: requestContext.put(WSEESecurityConstants.ON_BEHALF_OF_USER, request.getRemoteUser());
46: out.println(port.sayHello(request.getRemoteUser()));
47: out.println(“</body></html>”);
48: out.close();
49: }
50: }

 

 

3) OWSM Policy in the OSTS endpoint

Line 20 defined the OSTS endpoint. If you append ?WSDL to it and paste it in a browser URL, you can see the WS-Policy generated by the OWSM policy (wss11_username_token_with_message_protection_service_policy) that protects it. It can give you very good insights in case you run into interoperability issues.

In my experience, the interoperability problems are mostly due to mismatch between security bindings, encryption method mechanisms and encryption algorithms.

Here are some typical error messages. I now know how to make them happen anytime. 🙂

a) Due to security binding mismatch:

Caused by: 
oracle.wsm.security.policy.scenario.policycompliance.PolicyComplianceException:
WSM-00059 : Signature method algorithms are mismatched. Expected : http://www.w3.org/2000/09/xmldsig#hmac-sha1,
Actual : http://www.w3.org/2000/09/xmldsig#rsa-sha1.

In this case, make sure both policies use the same security binding. For instance, OWSM’s wss11_username_token_with_message_protection_service_policy is Symmetric. The security binding is NOT configurable in the OWSM policy.

<sp:SymmetricBinding xmlns:sp=“http://schemas.xmlsoap.org/ws/2005/07/securitypolicy”>

  <wsp:Policy>
...
</sp:SymmetricBinding>



b) Due to encryption reference mechanism mismatch:

[2011-09-21T16:04:27.900-07:00] [ms1] [ERROR] [WSM-00034]

[oracle.wsm.resources.security] [tid: [ACTIVE].ExecuteThread: '0' for queue: 
'weblogic.kernel.Default (self-tuning)'] [userId: <anonymous>] [ecid:
5f5492695bd28c21:-83db949:1328e2f9215:-8000-000000000000002c,0]
[WSM_POLICY_NAME:
oracle/wss11_saml_token_with_message_protection_service_policy] [APP:
InteropWebServices] Error in Encryption reference mechanism compliance :
Expected : thumbprint , Actual : ski. Ensure that a compatible policy is
attached at the client side.

This is configurable in the OWSM policy, by changing the orasp:enc-key-ref-mech property value.

<orasp:wss11-username-with-certificates orawsp:name=“WS-Security 1.1 username

with certificates" orawsp:Silent="false" orawsp:Enforced="true" 
orawsp:category="security/authentication, security/msg-protection">

<orasp:username-token orasp:password-type="plaintext"
orasp:add-nonce="false" orasp:add-created="false"/>

<orasp:x509-token orasp:enc-key-ref-mech="ski"/>

<orasp:msg-security orasp:confirm-signature="true"
orasp:sign-then-encrypt="true" orasp:include-timestamp="true"
orasp:encrypt-signature="false" orasp:algorithm-suite="Basic256">

c) Due to encryption algorithms mismatch:

Caused by:

oracle.wsm.security.policy.scenario.policycompliance.PolicyComplianceException: 
WSM-00030 : The encryption method key wrap algorithms do not match : Expected
: http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p,
Actual : http://www.w3.org/2001/04/xmlenc#rsa-1_5.

This is also configurable in the OWSM policy. In the policy snippet above, you can play with the property value of orasp:algorithm-suite and try the Algorithm Suite values as specified in the WS-SecurityPolicy specification. Make sure it matches the one in the client-side policy.

Note: In OSTS, the OWSM policies are available at $MW_HOME/Oracle_IAM1/oam/server/policy/sts-policies.jar.

4) Client-side WS-Policy for OSTS endpoint

Weblogic web service client APIs are smart enough to infer the necessary client configuration from the advertised WS-Policy in the web service WSDL. That said, we’re NOT supposed to attach any client-side policies to talk to our web service provider endpoint. However, this does NOT apply when talking to an STS using the WS-Trust client.

Notice that my client code adds StsWss11UntPolicy.xml to the BindingProvider on line 39. The xml file actually defines the WS-Policy that interoperates with OSTS endpoint protected by OWSM (once I worked through the problems showed above). Here it is:

<?xml version=“1.0”?>

<wsp:Policy xmlns:wsp=“http://schemas.xmlsoap.org/ws/2004/09/policy”
xmlns:sp=“http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702”>
<sp:SymmetricBinding>
<wsp:Policy>
<sp:ProtectionToken>
<wsp:Policy>
<sp:X509Token
sp:IncludeToken=“http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/Never”>
<wsp:Policy>
<sp:RequireKeyIdentifierReference/>
<sp:WssX509V3Token11/>
</wsp:Policy>
</sp:X509Token>
</wsp:Policy>
</sp:ProtectionToken>
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:Basic256Rsa15/>
</wsp:Policy>
</sp:AlgorithmSuite>
<sp:Layout>
<wsp:Policy>
<sp:Lax/>
</wsp:Policy>
</sp:Layout>
<sp:IncludeTimestamp/>
<sp:OnlySignEntireHeadersAndBody/>
</wsp:Policy>
</sp:SymmetricBinding>
<sp:SignedEncryptedSupportingTokens>
<wsp:Policy>
<sp:UsernameToken
sp:IncludeToken=“http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient”>
<wsp:Policy>
<sp:WssUsernameToken10/>
</wsp:Policy>
</sp:UsernameToken>
</wsp:Policy>
</sp:SignedEncryptedSupportingTokens>
<sp:Wss11>
<wsp:Policy>
<sp:MustSupportRefKeyIdentifier/>
<sp:MustSupportRefIssuerSerial/>
<sp:MustSupportRefThumbprint/>
<sp:MustSupportRefEncryptedKey/>
<sp:RequireSignatureConfirmation/>
</wsp:Policy>
</sp:Wss11>
<sp:SignedParts>
<sp:Header Namespace=“http://schemas.xmlsoap.org/ws/2004/08/addressing”/>
<sp:Header Namespace=“http://www.w3.org/2005/08/addressing”/>
<sp:Body/>
</sp:SignedParts>
<sp:EncryptedParts>
<sp:Body/>
</sp:EncryptedParts>
</wsp:Policy>



5) Required Configuration in Weblogic server

I’ve been always curious on how to define credential mappings in Weblogic to be used in the context of web services. Time has come. It turns out the system properties in the Troubleshooting section (next) came up very handy to let me know the mappings to be defined.

A credential mapping essentially maps a principal to a credential to be used when talking to external systems. This is very prevalent when the external systems are based on a JCA adapter. But it  applies to web services as well. For example, given authenticated user “andre” (known as the initiator) wants to call web service http://server:7003/webservices/GreetingPort from within a web service client running in Weblogic server, a credential mapping would tell which credentials the user would have to communicate with the web service.

A web service client running in Weblogic is “aware” of the security services provided by the server. In this case, given the WSS requirements stated by our 2 web services (OSTS and ws provider), two types of credential mappings are required in Weblogic:

A) 1 Default Credential Mapping:

Maps an initiator to a username/password pair. Required to add a username token to the outgoing SOAP request when calling the OSTS endpoint. A Default Credential Mapper is OOTB available in Weblogic. We DON’T need a mapping to talk to web service provider endpoint because that one requires a SAML token, which is going to be retrieved from OSTS.

Here’s the credential mapping (Security Realms –> myrealm –> Credential Mappings –> Default > New):

DefaultCredentialMapping

Protocol + Remote Host + Remote Port + Path makes up the web service URL being called. You don’t need to specify any value for Method. Notice that Path value must start with a /.

DefaultCredentialMapping_2

Local User is the initiator, on whose behalf the username under Remote User field is going to be retrieved. Obviously, the Remote User needs to be properly authorized in the remote system (OSTS).

B) 4 PKI Credential Mappings:

A PKI Credential Mapping maps an initiator to either a private key or a certificate. Required to perform digital signature and message encryption when calling the OSTS endpoint and web service provider endpoint. Remember, both endpoints require message protection. A PKI Credential Mapper is NOT OOTB available in Weblogic. To add one, got to Security Realms –> myrealm –> Providers –> Credential Mapping –> New (pick PKICredentialMapper). Make sure to fill in the form in the Provider Specific tab.

PKICredentialMapper

The keystore file Name is relative to the location where you start the Admin server. In my case, I’ve simply put clientkeystore.jks in $MW_HOME/user_projects/domains/<my-domain-name> folder.

Once you add it, restart the Admin Server so you can add the mappings (Security Realm –> myrealm –> Credential Mappings –> PKI –> New). Here are my 4 mappings:

PKICredentialMapping

Notice there are 2 mappings for each endpoint. One to retrieve the private key used for signing and one to retrieve the certificate used for encryption. When defining these mappings, you have the opportunity to inform the alias names in the keystore (clientkeystore.jks) holding the private key and the certificate.

6) Troubleshooting

When running into trouble, these 4 system properties will come to your rescue in the client side. Add them to EXTRA_JAVA_PROPERTIES in setDomainEnv.sh:

  • weblogic.xml.crypto.dsig.verbose=true
  • weblogic.xml.crypto.encrypt.verbose=true
  • weblogic.xml.crypto.keyinfo.verbose=true
  • weblogic.xml.crypto.wss.verbose=true

You should be able to detect, for example, why you’re not able to get a X509 token.

####<Oct 10, 2011 2:55:58 PM PDT> <Debug> <SecurityCredMap> 
<dogwood.us.oracle.com> <ms1> <[ACTIVE] ExecuteThread: '3' for
queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>>
<> <aaa1e3e54fdb4a71:63733030:132ef6e25bc:-8000-000000000000008f>
<1318283758414> <BEA-000000> <getCredentials: requestor=Subject:
1
Principal =
weblogic.security.principal.WLSKernelIdentity("<WLS Kernel>")
,
resource=type=<remote>, protocol=http, remoteHost=localhost,
remotePort=9003, path=/webservices/GreetingPort, initiator=Subject:
1
Principal =
weblogic.security.principal.WLSUserImpl("andre")
,
credType=weblogic.pki.TrustedCertificate>
####<Oct 10, 2011 2:55:58 PM PDT> <Info> <>
<dogwood.us.oracle.com> <ms1> <[ACTIVE] ExecuteThread: '3' for
queue: 'weblogic.kernel.Default (self-tuning)'>
<andre> <>
<aaa1e3e54fdb4a71:63733030:132ef6e25bc:-8000-000000000000008f>
<1318283758417> <BEA-000000> <Did not get token for token type http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3
and purpose encrypt from token
handlerweblogic.xml.crypto.wss11.internal.bst.BSTHandler@9527ee>

Thanks to those properties, the log message above tells it was not possible to get a X509 token for user andre to encrypt the message. Then adding a PKI Credential Mapping with the server certificate solves the problem.

And to troubleshoot OWSM, configure TRACE:32 logging level for oracle.wsm in $MW_HOME/user_projects/domains/<domain-name>/config/fmwconfig/servers/<server-name>/logging.xml:

<logger name=‘oracle.wsm’ level=‘TRACE:32’ useParentHandlers=‘false’>

<handler name=‘owsm-message-handler’/>
</logger>

Log messages are sent, by default, to $MW_HOME/user_projects/domains/<domain-name>/servers/<server-name>/logs/owsm/msglogging/diagnostic.log.

Happy 2012!!

5 Minutes or Less: WLS SAML2 SSO and your cookies

This is somewhat related to what Brian describes in WLS Session Cookie Overriding in an OAM/SSO Enabled Environment. Here, I want to quickly point one potential issue if you plan to implement Web SSO using Weblogic server as a SAML2.0 Service Provider (SP).

When configuring a Weblogic server instance for SAML2.0 services, you have to fill in a property called “Published Site URL”.

ServiceProviderGeneralInfo

When this instance is an SP, this property tell the partner IdP (Identity Provider) where to post SAML Responses to. In the case of SAML2.0, that URL must be http://<server>:<port>/saml2, where <server> and <port> must refer to how the IdP recognizes the SP. In other words, if you have something like a load balancer in front of Weblogic server (which is the case if you’re running a cluster), <server> and <port> would be the load balancer’s. “saml2” is the web context of Weblogic’s internal SAML2.0 servlet, whose fully qualified name is com.bea.security.saml2.servlet.SAML2Servlet.

Very well, this servlet, when called as a Service Provider, has the ability to consume a SAML assertion created by the partner IdP and instantiate an HTTP session for the browser session in the server. And it will tie it to the browser session by issuing a cookie named JSESSIONID whose cookie-path is set to “/”.  So what?

It turns out that many applications specify their own cookie-path to avoid the problem of JSESSIONID clashing, where last accessed applications by the browser override the JSESSIONID cookie value during the same browser session, thus leaving orphaned HTTP sessions in the server.

It also turns out that other applications use a different cookie name to avoid the same problem.

In both cases, the JSESSIONID cookie issued by saml2 servlet won’t be accepted by the application. You may be prompted for authentication again (this time by the application), get an HTTP 401-Unauthorized error or get into an infinite loop of redirects between SP and IdP.

The most obvious solutions to these problems is removing the cookie-path constraint from the application (in which case it defaults to “/”) and having the application using the JSESSIONID name. You may need to get the blessings of your application provider for supportability purposes before proceeding to the changes.

That said, get to know your applications’ cookies (cookie-name and cookie-path) before integrating them into WLS SAML2 SSO.

Oracle Secure Token Services 101

In this post I want to introduce our readers to the Oracle Secure Token Service (OSTS) product, Oracle’s solution for providing standards-based mechanisms for trust brokerage across different identity domains. I won’t cover the gory details in this first post, but I expect to give you a good overview on what the product is, the typical usage scenarios and a basic understanding of its main concepts.

OSTS facilitates secure communications between web services providers and consumers. In OSTS terminology, a web service provider is a Relying Party, while a web service consumer is a Requester. It works as a central hub where web services consumers come and get security tokens that are further propagated to web services providers. In this way, it frees clients from all the necessary infrastructure to generate tokens required for identity propagation. Whenever the client needs a token, it requests one from OSTS.

It’s important to make clear that OSTS is no security PEP (Policy Enforcement Point) for web services. This is up to other products like OWSM (Oracle Web Services Manager) and OEG (Oracle Enterprise Gateway). It can actually be used with both of them. OEG, for example, can act as an OSTS client when protecting web services. OSTS is a set of services that validate incoming token requests and issue security tokens. It does, however, check whether a Requester can ask for a token to access a Relying Party, but it stops right there.

OSTS supports both WS-Security and WS-Trust as the protocols for token transport.

OSTS is delivered as an OAM (Oracle Access Manager) add-on in Oracle’s IAM 11.1.1.5. Its management console is integrated into OAM’s. OSTS runs within the OAM managed server but it is out-of-box disabled. It is enabled in OAM’s Console System Configuration tab, Common Configuration –> Available Services menu option:

OSTSEnabling

Here are the main OSTS concepts.

1 – OSTS Endpoint

OSTS public interfaces are web services that basically understand WS-Security and WS-Trust. OSTS Endpoints are the actual URLs that clients and services use to communicate with OSTS. The out-of-box end points are protected by OWSM policies, which means requesting clients must attach the required token when making the RST (Request Secure Token) request.

2 – Web Service Endpoint

This is the web service URL for which a token should be acquired. It is typically defined as Relying Party and is given a reference name that can be used in OAM’s Token Issuance Policy (see corresponding item below) in order to trigger the token issuance process.

3 – Token Issuance Policies

These define who can request tokens from OSTS for specific Relying Parties. Once you define a Relying Party in OSTS, you can define a Token Issuance Policy along with some constraints determining who is allowed or denied asking tokens for the Relying Party.

The screenshot below shows a policy saying that only identities members of the Administrators group can request a token. It is also possible to create a condition taking into account the Requester identity (which typically identifies the client application).

Notice the policy is actually defined as part of a policy domain in OAM.

TokenIssuancePolicyConstraint

OSTS reserves two special Relying Parties when a mapping can’t be resolved by the Token Issuance Policy: UnknownRP and MissingRP.

OSTS obtains the Relying Party URL from the AppliesTo WS-Addressing element in the RST. If there’s an AppliesTo element, but no mapping, UnknownRP is used. If there’s no AppliesTo element, MissingRP is used.

4 – Validation Templates

Validation templates define how OSTS processes the RST for different types of tokens in the request , by specifying rules for validating incoming client credentials as well as for token mapping. The token in the request can be mapped directly to a user in the external data store or to a partner in OSTS internal store.

OSTS also supports attribute-based mappings, where attributes in the external data store are used to identify the user. In the case of SAML validation template, it is possible to map the user based on Name Identifiers available in the incoming SAML assertion.

In “On Behalf Of” scenarios, one would typically map the incoming token in the WSS header to a partner, so that OSTS can validate credentials before issuing a token on behalf of the user specified in the WS-Trust body.

5 – Partners

Partners are entities trusted by OSTS. There are 3 of them: Requester, Relying Party and Issuance Authority.

A Requester is a client that requests a token from OSTS. There are two types of clients supported by OSTS: the web service client application or the end user. It is important to understand that the end user is NOT characterized as a Requester for OSTS, but someone that might exist in the identity store. The web service client application is the one seen as the Requester.

A Relying Party is the web service for which a token is produced by OSTS.

An Issuance Authority represents an entity capable of issuing SAML tokens. OSTS must know and trust who issues an incoming SAML assertion before issuing a token. It applies in the cases where SAML is the token in the RST.

6 – Partner Profiles

Partner Profiles set the default options for the different types of partners. These options basically define the (default) templates to be applied when validating or issuing a token and any (default) attribute mappings.

There are 3 types of profiles: Requester Profile, Relying Party Profile and Issuing Authority Profile.

The Issuing Authority profile additionally defines (default) rules for SAML data.

7 – Issuance Templates

They define the rules on how tokens are created. Each type of token has a template, which is selected by OSTS based on the RST. In the case there’s no token type in the RST, OSTS defaults to the Relying Party profile configuration. A party is always associated with a profile that defines the party defaults.

For example, among the rules for a SAML 1.1 token are: whether the token should be encrypted, the encryption algorithm, assertion issuer, Name Identifier properties, whether to include the authentication statement and authorization statement, token validity period, whether to sign the assertion, the confirmation method and any attribute name or value mappings.

8 – Cryptographic Keys and Digital Certificates

As you might expect, OSTS has a lot to deal with signing and encryption. OSTS makes use of 3 different key stores that are used in different complementary ways depending on the interaction requirements.

a) .oamkeystore: holds OSTS key-pair used for assertion signing and data decryption. Type is JCEKS. Whenever you need to export OSTS certificate, use this service URL:

http(s)://osts-hostname:osts-port/sts/servlet/samlcert?id=<TEMPLATE_ID>&encoding=<ENCODING>

where <TEMPLATE_ID> is the Template Id as defined in Security Token Service Settings. It is NOT the key alias.

OSTS_Encryption_Key
<ENCONDING> is either pem or der, pem being the default.

Example: http://localhost:14100/sts/servlet/samlcert?id=osts_encryption&encoding=der

b) amtruststore: stores trust certificates, thus used to validate parties’ certificates.

c) default-keystore.jks: stores the certificate used by the OWSM agent to enable WSS between OSTS and Requesters.

OSTS also supports CRLs( Certificate Revocation Lists), who are stored as a jar file (amcrl.jar) in the file system (${DOMAIN_HOME}/config/fmwconfig folder). A notification listener detects changes to that file and reloads it at runtime, without requiring a server restart. The file is updated through OSTS Console.

All these concepts are visible in the OSTS Console, available in OAM’s Console System Configuration tab, Security Token Services menu option, at the bottom left.

OSTSConsole

I hope this brief introduction can can give you all an overview of OSTS and makes the familiarization process easier in case diving into the product becomes necessary.

OSTS official documentation is here.