Monday, January 9, 2012

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!!

Tuesday, December 20, 2011

OAM 11g - UCM Integration

I have been involved with many customer's who are integrating OAM 11g with Universal Content Manager 11g (UCM) and I know that trying to follow the OAM documentation can be daunting. So I put together my own integration document/Blog. Not to re-invent the wheel, this post utilizes what we already have in terms of documentation. Think of this as a checklist and the steps that I implemented to get my own internal environment working.


Prerequisites

  1. Install and configure UCM
  2. Install a weblogic plug-in on OHS that fixes a bug for UCM. http://www.oracle.com/technetwork/middleware/ias/downloads/wls-plugins-096117.html

High Level Steps/Checklist

  1. Configure an OHS server to proxy all request to UCM (/cs, /adfAuthentication and /_ocsh).
  2. Register a webgate with the URL’s you want to protect.
  3. Configure an OAM Identity Asserter and LDAP/OVD provider in Weblogic.
  4. Validate users can access UCM with WLS Security.
  5. Install a webgate on OHS server and validate.

Detail Steps

  1. Follow the documentation to configure OAM Access Manager 11g with Oracle UCM, Section 5.2.3.1: http://download.oracle.com/docs/cd/E21764_01/doc.1111/e10792/c03_security.htm#CDDHGCCC

Note: The documentation is not clear whether to install the Webgate on the OHS server first. Recommend to install the webgate at the end.


5.2.3.1 - Configuring Oracle Access Manager 11g with Oracle UCM
1.
a. In our use case, we only need to protect the UCM URI’s below.

# UCM Content Server

<Location /cs>

SetHandler weblogic-handler

WebLogicHost <hostname>

WebLogicPort <portnumber>

</Location>

# UCM Content Server authentication

<Location /adfAuthentication>

SetHandler weblogic-handler

WebLogicHost<hostname>

WebLogicPort <portnumber>

</Location>

#UCM online help

<Location /_ocsh>

SetHandler weblogic-handler

WebLogicHost <hostname>

WebLogicPort <portnumber>

</Location>


b. Use the remote registration tool oamreg as follows in section 15.2.2.2:

http://download.oracle.com/docs/cd/E21764_01/core.1111/e100/osso_b_oam11g.htm#JISEC9104


15.2.2.2 - Provision with 11g Webgate
1. Acquire the tool
a. The rreg tool can be found and executed on the same box where OAM is installed. No need to un-tar.
2. Created a new UCM-Request.xml:

<OAM11GRegRequest>

<serverAddress>http://ateam-hq66.us.oracle.com:7003</serverAddress>

<hostIdentifier>UCM-INT</hostIdentifier>

<agentName>UCM-INT</agentName>

<protectedResourcesList>

<resource>/adfAuthentication</resource>

</protectedResourcesList>

<publicResourcesList>

<resource>/cs</resource>

<resource>/_ocsh</resource>

</publicResourcesList>

</OAM11GRegRequest>

3. On the command line, execute the following:

./bin/oamreg.sh inband input/UCM-Request.xml

When asked to enter the admin and password, make sure the user is part of the system store you configured for OAM (e.g testuser1/welcome1)

2. Continuing Section 5.2.3.1
Notes:

You can configure the OAM Asserter and LDAP/OVD Authenticator before installing a webgate. Once the LDAP/OVD authenticator is configured, recommend to test UCM and make sure that you can bind to a user that is created within the provider you configured.

The order of the provider’s should be as follows:


OAM Identity Asserter
The following ‘Common’ parameters should be set as:


Leave the default values for the ‘Provider Specific’ tab.

OVD Provider
‘Common’ tab:


‘Provider Specific’ tab:

Based on the backend LDAP repository, make sure that you specify the correct object class and user name attribute within the LDAP filters. In our case, we used ‘inetorgperson’ and ‘uid’ for a user object and ‘groupofuniquenames’ and ‘uniqumembers’ for groups.


3. After Installing and configuring OAM 11g……

a. Recommend installing the webgate now. No good links in the documentation to install webgate 11g. Use the following: http://download.oracle.com/docs/cd/E21764_01/install.1111/e12002/webgate.htm#CACCBCFF

Notes:
Section 20.2.4
You will need the gcc libraries. Can get them here:
http://www.oracle.com/technetwork/middleware/ias/downloads/101401-099957.html

Look for ‘GCC Libraries for Oracle Identity Federation’

Use the following cpio file to extract the gcc libraries:
cpio -idvm <cpio-file>

Section 20.4
Step 2 - Ran the command:
./deployWebgateInstance.sh –w /u0/Oracle/Middleware11.1.1.5/Oracle_WT1/instances/instance1/config/OHS/ohs1 -oh /u0/Oracle/Middleware11.1.1.5/Oracle_OAMWebgate1

Step 3 –
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/u01/Oracle/Middleware11.1.1.5/Oracle_WT1/lib

Step 5 – Ran the command:
./EditHttpConf –w /u01/Oracle/Middleware11.1.1.5/Oracle_WT1/instances/instance1/config/OHS/.ohs1

b. Next you will need to copy the artifacts that were generated in step 3 from section 15.2.2.2. Copy the ‘ObAccessClient.xml’ and ‘cwallet.sso’ located in the ‘output/UCM-INT’ directory under ‘rreg’ to the /config directory.

Webgate installation completed. Make sure that the oam managed server is running and restart the OHS server.


Trouble shooting tips:

  • Cannot login via OAM – A few things to verify:
  • Make sure that the LDAP Authentication Module in the OAM console is pointing to the correct data store.
  • Make sure that the OVD provider in WLS matches the same OAM data store configuration.
  • Login looping issue
  • In some cases we see a looping issue when using IE when the time sync of off between the webgate machine and the OAM server machine.
  • Logout not working
    • Please follow the instructions to configure UCM logout with OAM. http://download.oracle.com/docs/cd/E17904_01/doc.1111/e14770/ucm.htm#ASRLA3579

In my next post, I will continue to integrate my OAM environment to include the Image Processing Management (IPM) tool, which requires UCM.

Tuesday, December 13, 2011

Multiple Identity Providers with Oracle Identity Federation and Access Manager as Service Provider

Whew, that’s a mouthful for a title, but IdP N..1 SP [OIF+OAM] was probably too cryptic. Let me describe the use-case in a little more detail. Imagine if you will an education application that the state wants to surface to the various school districts. The districts want to manage user accounts and federate into the state’s application. In order to consolidate policy enforcement for both internal and external users, the state needs a single point of entry controlled by an access control system.

The documentation for Oracle Access Manager (OAM) and Oracle Identity Federation (OIF) integration on the service provider (SP) (http://docs.oracle.com/cd/E21764_01/doc.1111/e15740/oif.htm#CACJDDGE) implies that this can only be done with a single identity provider (IdP). By setting OIFScheme as the authentication scheme for the application, OAM can redirect to the service provider on OIF, which will trigger an SP-initiated Single Sign-On (SSO). There is no way to declare which IdP to use in this scenario, however. Thus, a different trigger mechanism is required for the multiple IdP scenario, plus we need to account for internal state users as well. One approach is to leverage OAM form authentication with hyperlinks to an IdP discovery page, or static links to each campus trigger for SP-initiated SSO. The format in OIF for this is http(s)://<oif>: <oif_port>/fed/sp/initiatesso?providerid=CAMPUS1&returnurl=<URL of destination app>. Once the IdP sends its SAML Response to the OIF service provider, OIF will make authentication & authorization request to OAM Policy Decision Point (PDP) based on the returnurl parameter. If successful, OIF will redirect client to the destination application with a token that the OAM Policy Enforcement Point (PEP) will honor.

One gotcha here is that the returnurl must be protected by the OIFScheme, not the form-based scheme used for internal users. That creates a challenge in that you essentially need two protected URLs for entry into the app, one to trigger the initial form authentication and one to map the external/federated users. If having all external users end up at the same portal site after authentication is acceptable, one can map the OIFScheme to a pseudoURL. You can then configure an OnAuthenticationSuccess redirect to the landing page. This pattern is only suitable if all external users come to the same page upon successful federation. I tried basing the federation policy on a query parameter, i.e. returnurl=/mysite?external=true, but OAM did not seem evaluate the query parameter, only the application context.

Another hitch is that I don’t think a 10g WebGate can consume the identity token set by the service provider. I haven’t tested to validate, but I suspect that only the 11g WebGate can consume the OAM_ID cookie. Thus, if you have a mixed environment, you will need an OHS 11g instance to handle external user traffic, while redirecting to other web servers only after an authentication cookie has been set.