Quantcast
Channel: oam 11g academy – ATeam Chronicles
Viewing all 41 articles
Browse latest View live

Logging in your OAM plug-in

$
0
0

Introduction

Logging in a custom plug-in written for OAM

 

Main Article

I’ve been playing around with the OAM plug-in API and working on putting together a very simple JDeveloper project that includes a custom login form and an OAM plug-in that demonstrates the basics of using the interface.

I’m going to get that blog post out eventually, but for right now I need to talk about logging inside your plug-in.

OAM uses the Java Logger (java.util.logging.Logger and related classes) to record all of the debugging information in an easily manageable way. When you write your first plug-in it can be a bit confusing to figure out how the heck you get your logging messages out. It’s not at all complicated, but it does mean you need to understand how OAM manages its logging.

Let’s start with the absolutely minimum amount of code you need to log:

    package com.oracleateam.iam.oamauthnplugin;  

    // a bunch of imports go here  

    public class DemoAuthNPlugin extends AbstractAuthenticationPlugIn {  
      public DemoAuthNPlugin() {  
        super();  
        LOGGER.finest(this.getClass.getName() + " constructor called.");  
      }  

      // other methods  
    }

That’s it. The bare minimum needed to get logging working.

Of course you need to do a little more work… Click through to see what else you need to do.

But in order to convince the logging layer to actually put that string into a log file we need to actually enable that logging. The OAM docs talk about this in some detail in this section, but here’s a quick recap:

Run wlst from the OAM home:

[oracle@linux OAMDomain]$ ~/Oracle/Middleware/Oracle_IAM1/common/bin/wlst.sh<br />

Then connect to the running OAM server and actually enable logging for oracle.oam.plugin (note: the docs talk about a different logger. In OAM 11.1.1.5 I know for a fact that plugins log under oracle.oam.plugin!)

wls:/offline> connect('weblogic', 'ABcd1234', 't3://localhost:7010')
Connecting to t3://localhost:7010 with userid weblogic ...
Successfully connected to Admin Server 'AdminServer' that belongs to domain 'OAMDomain'.

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:/OAMDomain/serverConfig> domainRuntime()
Location changed to domainRuntime tree. This is a read-only tree with DomainMBean as the root. 
For more help, use help(domainRuntime)

wls:/OAMDomain/domainRuntime> setLogLevel(logger="oracle.oam.plugin",level="TRACE:32", persist="0", target="oam_server1")
wls:/OAMDomain/domainRuntime> listLoggers(pattern="oracle.oam.plugin",target="oam_server1")
------------------+-----------------
Logger            | Level           
------------------+-----------------
oracle.oam.plugin | TRACE:32

Do that, upload, distribute, and activate your plug-in and you should be rewarded with something like this appearing in your log file:

[2012-02-01T16:03:38.122-05:00] [oam_server1] [TRACE:32] [] [oracle.oam.plugin] [tid: DistributedCache:DistributionCache:EventDispatcher] [userId: ] [ecid: 0000JKuP1i6DsX55nRx0iZ1FAP
9N000002,0] [SRC_CLASS: oracle.security.am.engines.common.adapters.OAMLoggerImpl] [APP: oam_server] [SRC_METHOD: finest] DemoAuthNPlugin loading

Which log file? servers/oam_server1/logs/oam_server1-diagnostic.log of course!

OK, so that’s all well and good, but what if you don’t want to log in the same place all the other OAM plug-ins log?

Easy peasy. Just make one change to your code:

    package com.oracleateam.iam.oamauthnplugin;  

    // a bunch of imports go here  

    public class DemoAuthNPlugin extends AbstractAuthenticationPlugIn {  
      private final static Logger LOGGER = Logger.getLogger(DemoAuthNPlugin.class.getCanonicalName());  

      public DemoAuthNPlugin() {  
        super();  
        LOGGER.finest(this.getClass.getName() + " constructor called.");  
      }  

      // other methods  
    }

And add a new logger to OAM’s configuration:

wls:/OAMDomain/domainRuntime> setLogLevel(logger="com.oracleateam.iam.oamauthnplugin",level="TRACE:32", persist="0",  target="oam_server1",addLogger="1")
wls:/OAMDomain/domainRuntime> listLoggers(pattern="com.oracleateam.iam.oamauthnplugin",target="oam_server1")
-----------------------------------+-----------------
Logger                             | Level           
-----------------------------------+-----------------
com.oracleateam.iam.oamauthnplugin | TRACE:32

And you will be rewarded with lines like this in your log file:

[2012-02-01T16:13:11.713-05:00] [oam_server1] [TRACE:32] [] [com.oracleateam.iam.oamauthnplugin.DemoAuthNPlugin] [tid: DistributedCache:DistributionCache:EventDispatcher] [userId: ]
[ecid: 0000JKuP1i6DsX55nRx0iZ1FAP9N000002,0] [SRC_CLASS: com.oracleateam.iam.oamauthnplugin.DemoAuthNPlugin] [APP: oam_server] [SRC_METHOD: ] DemoAuthNPlugin loading

The key here is to not go monkeying with the logging.xml file. Just let WLST take care of all of that for you!


OAM 11g Single Sign-On and OAM 10g Cookies

$
0
0

Introduction

This post is part of a larger series on Oracle Access Manager 11g called Oracle Access Manager Academy. An index to the entire series with links to each of the separate posts is available.

In an earlier post I talked about how cookies work when you’re using OAM 11g server with OAM 11g WebGates. But the OAM 11g server also works with OAM 10g WebGates and there are reasons you’d deploy 10g WebGates today. But OAM 11g and 10g have fundamentally different behavior when it comes to the cookies.

Main Article

So how do cookies work when you’re using 10g WebGates with the 11g server?

In short they work pretty much the same way. Or at least they can work nearly the same way with 10g WebGates as they do with 11g WebGates.

I setup an environment with two servers – alpha and linux.ktest.oracleateam.com. Alpha is an IIS server with an OAM 10g WebGate and one protected directory which I cleverly named /protected/. The other machine (linux.ktest.oracleateam.com) is, as you’ve guessed, a Linux box with the OAM server installed. I’d include a diagram, but it looks exactly the same as the diagram in the older post.

Here’s what the HTTP traffic looks like when I try to access http://alpha/protected/:

GET /protected/ HTTP/1.1
Accept: image/jpeg, image/gif, image/pjpeg, application/x-ms-application, application/xaml+xml, application/x-ms-xbap, */*
Accept-Language: en-US
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729)
Accept-Encoding: gzip, deflate
Host: alpha
Connection: Keep-Alive

HTTP/1.1 302 Redirect
Content-Length: 0
Location: http://linux.ktest.oracleateam.com:14100/oam/server/obrareq.cgi?wh%3Dalpha%20wu%3D%2Fprotected%2F%20wo%3D1%20rh%3Dhttp%3A%2F%2Falpha%20ru%3D%252Fprotected%252F
Server: Microsoft-IIS/7.5
Set-Cookie: ObSSOCookie=loggedoutcontinue; httponly; path=/
X-Powered-By: ASP.NET
Date: Fri, 09 Mar 2012 16:14:16 GMT

GET /oam/server/obrareq.cgi?wh%3Dalpha%20wu%3D%2Fprotected%2F%20wo%3D1%20rh%3Dhttp%3A%2F%2Falpha%20ru%3D%252Fprotected%252F HTTP/1.1
Accept: image/jpeg, image/gif, image/pjpeg, application/x-ms-application, application/xaml+xml, application/x-ms-xbap, */*
Accept-Language: en-US
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729)
Accept-Encoding: gzip, deflate
Host: linux.ktest.oracleateam.com:14100
Connection: Keep-Alive

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store
Date: Fri, 09 Mar 2012 16:16:55 GMT
Pragma: no-cache
Content-Length: 3326
Content-Type: text/html; charset=UTF-8
Expires: 0
Set-Cookie: OAM_REQ=VERSION_4~KJTasxCSm1Z1LVGtpMwu5nJ3cwSYLNx1TGFLYN7tRq3Jr1Pin693MMCJJHQ6bPQL1vSxK3En%2bFaQPCNevV3Idi1o07xN9LjfFWubXf4B98yXOGRH6fT7RaZjp2dfPyqCADEG022AZg7xWsrCjff848vcqwAzLXs2schaae8z7YLXxCNVoMUGMsHFahTPkuq31ZIaqK8lZq7glReQuZyiBGXWPr5EptvGcbWEe0X9iOoeiUGFoJt6LpOCz79%2fJPpURizXOCQej3M3eCpGw8QmzUGa5ajAsPu5M0KZPViBubQwM9dsePRYNYaFizHYla8%2ftYr%2fHpgxkNLmuZ3crkzSZES45dnWdaqZBPbAcZb9S8pdGsjxMiB18bcudXC5A4DXnPwYLu92RQKrtHHgiq1JYIfMz4ZsCK5Fks%2bH3waTnw4Ec9V6EFvWF2rHXeGjqsHNN3jdZDtUlRkYcgBffUpBVkd%2fppwds%2fRcS4RVie39kRqduhbS1qphdGdy6pH8cX%2f8LEn3QoR2GXcn8cxgDEtfTR4q2JvrhbSnSChrqX967ogq8b%2bi0HEzDwFkYbhuZudsCXRHPVeOjGe78SY5IumWqCBIxW0z9LiSOhmcBDbagRFByhcTMpHZPU%2fxJxL7vdqllS8BwRPeVZuI0yuGstbBxVgWMzPJD%2bahnJXwlNODHEBCuMtYyO7gTol9VqpJo2l40PUgQUkmtw3cNf%2btazp5uTY%2fy8MG9AAyTNMTlgvaSnNTe0fwxiVMVcjuIqYUl%2fhSy%2fh1Z0lodn0w6HZQoiIyYMiEA%2felDR38iBKP4%2b14IvKroONAhuX0Ly4XSNRqGbzKyt%2fmqkc%2bguL2OPAIFjeBGMuses6r5Ml%2fepyF%2f%2bqnXTBB%2bFweBmaxHdv1uU58kWwtTfkWJwEuALDJhAXG7ixRnkHISfizpkPKGTs5jAGDj8Lhcndl1IAKbekDS5d6g2zxSpl4RDGmZuWcVG2G8XSyBs5D317CWvx1Mq3SDZhcvGy7RscDcqy7ra66j1uS49QaKvAgdGA03RzwAfCLMD4wNnj06aAkh9BXTDv%2bgHYzCaWpXm8yjMAVPr9fhXzn3Nro3ffM8I%2bEdFq2lRLdFIo04Gc4o%2f7lS0dGZKS6%2fyB5UKCtmD%2fihmsHdCVFUcRCMdff21HGT%2f8y0j6yQHNf4X1RefEdYcjbYOEv%2bbm1Jq5zcat60maesmmiBl5n6LJFYSfG6QLs4wLqZjqEXPWU96JBQuFwDjf7ux4RTcmnLG3LbU3M6lUPqfB0k8TGee7XbtaW0Z%2b69CIsYElY1ftvszOT2uMw2yAjy8nvs7iIJVvXGb0yX57h77WiySby6ISqvIH1maMdzr6jIAL76ImMc%2bCVJzJvt4WgobY6nc4OH4MSPMg%3d; path=/; HttpOnly
X-ORACLE-DMS-ECID: bc0b467a62ba363a:-50e866c2:135cc4d3539:-8000-0000000000000ab5
X-Powered-By: Servlet/2.5 JSP/2.1

As is the case with 11g WebGates the WebGate redirects me over to the OAM server to see if I have an existing session. And since I haven’t logged on yet I don’t have a session or associated cookie. So OAM sends me off to the login page.

So far this looks remarkably like the 11g WebGate. And by “remarkably like” I mean exactly the same as!

At this point I’m staring at the login page so let me enter the username and password and POST them to the credential collector:

POST /oam/server/auth_cred_submit HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Referer: http://linux.ktest.oracleateam.com:14100/oam/server/obrareq.cgi?wh%3Dalpha%20wu%3D%2Fprotected%2F%20wo%3D1%20rh%3Dhttp%3A%2F%2Falpha%20ru%3D%252Fprotected%252F
Accept-Language: en-US
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
Host: linux.ktest.oracleateam.com:14100
Content-Length: 67
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: OAM_REQ=VERSION_4~KJTasxCSm1Z1LVGtpMwu5nJ3cwSYLNx1TGFLYN7tRq3Jr1Pin693MMCJJHQ6bPQL1vSxK3En%2bFaQPCNevV3Idi1o07xN9LjfFWubXf4B98yXOGRH6fT7RaZjp2dfPyqCADEG022AZg7xWsrCjff848vcqwAzLXs2schaae8z7YLXxCNVoMUGMsHFahTPkuq31ZIaqK8lZq7glReQuZyiBGXWPr5EptvGcbWEe0X9iOoeiUGFoJt6LpOCz79%2fJPpURizXOCQej3M3eCpGw8QmzUGa5ajAsPu5M0KZPViBubQwM9dsePRYNYaFizHYla8%2ftYr%2fHpgxkNLmuZ3crkzSZES45dnWdaqZBPbAcZb9S8pdGsjxMiB18bcudXC5A4DXnPwYLu92RQKrtHHgiq1JYIfMz4ZsCK5Fks%2bH3waTnw4Ec9V6EFvWF2rHXeGjqsHNN3jdZDtUlRkYcgBffUpBVkd%2fppwds%2fRcS4RVie39kRqduhbS1qphdGdy6pH8cX%2f8LEn3QoR2GXcn8cxgDEtfTR4q2JvrhbSnSChrqX967ogq8b%2bi0HEzDwFkYbhuZudsCXRHPVeOjGe78SY5IumWqCBIxW0z9LiSOhmcBDbagRFByhcTMpHZPU%2fxJxL7vdqllS8BwRPeVZuI0yuGstbBxVgWMzPJD%2bahnJXwlNODHEBCuMtYyO7gTol9VqpJo2l40PUgQUkmtw3cNf%2btazp5uTY%2fy8MG9AAyTNMTlgvaSnNTe0fwxiVMVcjuIqYUl%2fhSy%2fh1Z0lodn0w6HZQoiIyYMiEA%2felDR38iBKP4%2b14IvKroONAhuX0Ly4XSNRqGbzKyt%2fmqkc%2bguL2OPAIFjeBGMuses6r5Ml%2fepyF%2f%2bqnXTBB%2bFweBmaxHdv1uU58kWwtTfkWJwEuALDJhAXG7ixRnkHISfizpkPKGTs5jAGDj8Lhcndl1IAKbekDS5d6g2zxSpl4RDGmZuWcVG2G8XSyBs5D317CWvx1Mq3SDZhcvGy7RscDcqy7ra66j1uS49QaKvAgdGA03RzwAfCLMD4wNnj06aAkh9BXTDv%2bgHYzCaWpXm8yjMAVPr9fhXzn3Nro3ffM8I%2bEdFq2lRLdFIo04Gc4o%2f7lS0dGZKS6%2fyB5UKCtmD%2fihmsHdCVFUcRCMdff21HGT%2f8y0j6yQHNf4X1RefEdYcjbYOEv%2bbm1Jq5zcat60maesmmiBl5n6LJFYSfG6QLs4wLqZjqEXPWU96JBQuFwDjf7ux4RTcmnLG3LbU3M6lUPqfB0k8TGee7XbtaW0Z%2b69CIsYElY1ftvszOT2uMw2yAjy8nvs7iIJVvXGb0yX57h77WiySby6ISqvIH1maMdzr6jIAL76ImMc%2bCVJzJvt4WgobY6nc4OH4MSPMg%3d

username=weblogic&password=ABcd1234&request_id=-8330979068306697433

HTTP/1.1 302 Moved Temporarily
Connection: close
Date: Fri, 09 Mar 2012 16:17:01 GMT
Transfer-Encoding: chunked
Location: http://alpha/obrar.cgi?cookie=vBDzuSSiKglMEtxbyB1gBqe1aZvsE6WQhSF7%2Be%2FZ0DpntUvIXgPr79acpIo8FQ0V4mvuOrqn%2BGIendMpqPNgTuISUEDblFQjZKfNG4ixWaVW%2BitIr58w%2FvQ2kalnVL3zhKYAF2yU7rGyNolRifidAq7xW8%2BKQbyFq8GFAgga0Assv%2BxwGzvd%2FizmiXnx8cOD6KZBWGMtIeLBrJRBitqXoKgLZc6b2UuCc2VLkTufmlQdt0DZ7dOACr45efkrTSKgKhuqoykTsiKiGTIP4R2xe85TUfYYm%2F1i4E8p%2FdHmcD4tpJ4LRrslKI3MgDHj%2Ft1uq3ryhROxbcRBk2eM1Eo99QYNY6IOsFyo1sJA7YEkr7c%3D%20redirectto=%252Fprotected%252F%20ssoCookie=httponly
Set-Cookie: OAM_ID=VERSION_4~C7Iz5I0rodPWWPLR82CoQg==~bP8dGW/YVqe1NaHiCaZ3z6p2dbxVbpJpcSYMU6LVzUSBHp0C9OtSKbtvUlHHDsGImCi8KtAh3CLHXN+paF2+ZyxNOZOge2Mg2aH6vF8Wy2fUgIEYAVYjtVrP4bVTC0GpM7S6dt3XpjR/AHScYUdQNp5Olr5D3gSlBAnXWcyYxY9u/x620d5LHIYvBdZvqZzVsfAAV/5KovBKD/5wvhPWI/JDkYoUdT37VoaDp7BS1lOumUtTqzXkQTzMzAkLCzhS0M1NyCYTiT9904bIxfzhJw==; path=/; HttpOnly
Set-Cookie: OAM_REQ=invalid; path=/; HttpOnly
X-ORACLE-DMS-ECID: bc0b467a62ba363a:-50e866c2:135cc4d3539:-8000-0000000000000ab7
X-Powered-By: Servlet/2.5 JSP/2.1

Not terribly surprisingly I get an OAM_ID cookie and a redirect back to the protected resource, again just like with the 11g WebGate.

So we’re on our way back to the WebGate to a fake resource called obrar.cgi with some encrypted data in the query string (yes, oddly familiar!).

The browser does the HTTP GET there…

GET /obrar.cgi?cookie=vBDzuSSiKglMEtxbyB1gBqe1aZvsE6WQhSF7%2Be%2FZ0DpntUvIXgPr79acpIo8FQ0V4mvuOrqn%2BGIendMpqPNgTuISUEDblFQjZKfNG4ixWaVW%2BitIr58w%2FvQ2kalnVL3zhKYAF2yU7rGyNolRifidAq7xW8%2BKQbyFq8GFAgga0Assv%2BxwGzvd%2FizmiXnx8cOD6KZBWGMtIeLBrJRBitqXoKgLZc6b2UuCc2VLkTufmlQdt0DZ7dOACr45efkrTSKgKhuqoykTsiKiGTIP4R2xe85TUfYYm%2F1i4E8p%2FdHmcD4tpJ4LRrslKI3MgDHj%2Ft1uq3ryhROxbcRBk2eM1Eo99QYNY6IOsFyo1sJA7YEkr7c%3D%20redirectto=%252Fprotected%252F%20ssoCookie=httponly HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Referer: http://linux.ktest.oracleateam.com:14100/oam/server/obrareq.cgi?wh%3Dalpha%20wu%3D%2Fprotected%2F%20wo%3D1%20rh%3Dhttp%3A%2F%2Falpha%20ru%3D%252Fprotected%252F
Accept-Language: en-US
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
Cookie: ObSSOCookie=loggedoutcontinue
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
Cache-Control: no-cache
Host: alpha

HTTP/1.1 302 Redirect
Content-Length: 0
Location: /protected/
Server: Microsoft-IIS/7.5
Set-Cookie: ObSSOCookie=vBDzuSSiKglMEtxbyB1gBqe1aZvsE6WQhSF7%2Be%2FZ0DpntUvIXgPr79acpIo8FQ0V4mvuOrqn%2BGIendMpqPNgTuISUEDblFQjZKfNG4ixWaVW%2BitIr58w%2FvQ2kalnVL3zhKYAF2yU7rGyNolRifidAq7xW8%2BKQbyFq8GFAgga0Assv%2BxwGzvd%2FizmiXnx8cOD6KZBWGMtIeLBrJRBitqXoKgLZc6b2UuCc2VLkTufmlQdt0DZ7dOACr45efkrTSKgKhuqoykTsiKiGTIP4R2xe85TUfYYm%2F1i4E8p%2FdHmcD4tpJ4LRrslKI3MgDHj%2Ft1uq3ryhROxbcRBk2eM1Eo99QYNY6IOsFyo1sJA7YEkr7c%3D;httponly; path=/
X-Powered-By: ASP.NET
Date: Fri, 09 Mar 2012 16:14:22 GMT

Ah! There it is – the first real difference between OAM 11g and OAM 10g WebGates behavior. With the 10g WebGate I get a good old ObSSOCookie instead of a 11g’s uniquely named cookie.

I also got and a redirect back to the original resource, which I then retrieve:

GET /protected/ HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Referer: http://linux.ktest.oracleateam.com:14100/oam/server/obrareq.cgi?wh%3Dalpha%20wu%3D%2Fprotected%2F%20wo%3D1%20rh%3Dhttp%3A%2F%2Falpha%20ru%3D%252Fprotected%252F
Accept-Language: en-US
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
Cookie: ObSSOCookie=vBDzuSSiKglMEtxbyB1gBqe1aZvsE6WQhSF7%2Be%2FZ0DpntUvIXgPr79acpIo8FQ0V4mvuOrqn%2BGIendMpqPNgTuISUEDblFQjZKfNG4ixWaVW%2BitIr58w%2FvQ2kalnVL3zhKYAF2yU7rGyNolRifidAq7xW8%2BKQbyFq8GFAgga0Assv%2BxwGzvd%2FizmiXnx8cOD6KZBWGMtIeLBrJRBitqXoKgLZc6b2UuCc2VLkTufmlQdt0DZ7dOACr45efkrTSKgKhuqoykTsiKiGTIP4R2xe85TUfYYm%2F1i4E8p%2FdHmcD4tpJ4LRrslKI3MgDHj%2Ft1uq3ryhROxbcRBk2eM1Eo99QYNY6IOsFyo1sJA7YEkr7c%3D
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
Cache-Control: no-cache
Host: alpha

HTTP/1.1 200 OK
Cache-Control: no-cache,private
Pragma: no-cache
Content-Type: text/html
Content-Encoding: gzip
Vary: Accept-Encoding
Server: Microsoft-IIS/7.5
X-Powered-By: ASP.NET
Date: Fri, 09 Mar 2012 16:14:22 GMT
Content-Length: 2495

As with the 11g WebGate you probably noticed that there’s no domain= parameter on the cookie. Which means that this ObSSOCookie is specific to the one WebGate. But wait, didn’t OAM 10g WebGates use a domain-wide cookie?

Yes they did. And 10g WebGates still do if (and only if) that’s what you want.

Here’s my configuration settings for my 10g WebGate:


10WebGateSettings

In my case I left out the cookie domain setting for the WebGate. And by doing that I told the WebGate to act like the 11g WebGate and use “host only” cookies.

Filling in that setting changes the behavior. For new deployments of OAM 11g with 10g WebGates I generally would recommend leaving the setting blank because it solves a number of problems with cookies in larger deployments of OAM. But I’m going to put off discussing those problems until a later post.

Detached Credential Collector Configuration – OAM 11GR2

$
0
0
Detached Credential Collector (DCC) has been introduced in OAM 11GR2 release. And the documentation, http://docs.oracle.com/cd/E27559_01/admin.1112/e27239/register.htm#BABEGDFA, explains in detail about how to deploy it in various architecture scenarios.
 In addition to the documentation, this blog post will help clarify the configuration steps.

 
The following step presumes your deployment uses Open mode communication. It also assumes that a webgate 11G is registered with the OAM Server.

A. Enable credential operations for an existing 11G Webgate

 

Using the Oracle Access Management Console, find and open the page for the 11.1.2 Webgate that will function as the DCC:

  • Click on System Configuration tab
  • Click Access Manager
  • Expand the SSO Agents node
  • Double Click on OAM Agents
  • Click on Search
  • Click on the Webgate (say, the name is RREG_OAM11G)
  • Check the box beside Allow Credential Collector Operations.
  • Click Apply.
Here is the snapshot of the above configuration:
 
 

B.     Invoke the right perl executable

Ensure that the path name of the perl executable as mentioned in the perl scripts is correct.
For example, if the Webgate is installed $MW_HOME/Oracle_OAMWebGate1, the perl scripts for DCC-based login are located in the following path:  $MW_HOME/Oracle_OAMWebGate1/webgate/ohs/oamsso-bin.
In most of the cases, by default for Unix based system, the perl executable located at /usr/bin/perl. This can be verified by the command “which perl” in the OAM Server. However, the perl scripts themselves point to: /usr/local/bin/perl
To make sure that the scripts execute correctly, there are two choices:
  1. Create a symbolic link for /usr/local/bin/perl so that it points to /usr/bin/
  2. Or alter the first line of the scripts so that they points to the correct location for perl, that is, replace the line #!/usr/local/bin/perl by #!/usr/bin/perl.
 

C.   Configure the Authentication Scheme for DCC

Configure a new authentication scheme as follows:
  • Click on Authentication Scheme
  • Click on + on the top to add a new Authentication Scheme
  • A page will open for the new authentication scheme and then fill up the fields as follows:
    • Name: DCC AuthScheme [It can be anything]
    • Authentication Level: 2
    • Challenge Method: FORM
    • Challenge Redirect URL: http://oam.oracleateam.com:7778 [Note: This is theURL for the OHS Server where webgate is configured for DCC]
    • Authentication Module: LDAP [If the LDAP authentication module is the authentication engine]
    • Challenge URL: /oamsso-bin/login.pl
    • Context Type: Select the blank
  •  Select Apply
Here is the snapshot for the above configuration:
 

 

D.     Configure the Authentication Policy for the Protected Resource

Go to the Authentication Policy and make sure that you choose the “DCC AuthScheme” as the authentication scheme for the Protected Resource Policy.
A typical snapshot would be as follows:
 

 

 

Now restart the OAM Server and test the above configuration. Create a sample page, for example, test.html, in the OHS root location. And try to access the page as
This will redirect you to the following login page as shown below:

The above URL shows that you are directed to the Detached Credential Collector.
Now if you enter the credential correctly, you should be able to access the test.html page.

X509 Fallback to Form

$
0
0
  1. Introduction

OAM 11G does not provide an out of box solution for falling back to FORM authentication if X509 Certificate is not available or if the certificate is not accepted by the user. I have seen this requirement coming from customers and found a solution after brainstorming with my colleagues (special thanks to Chris Johnson and Brian Eidelman). The solution is not very difficult, though it needs some additional configurations and coding.

It should be noted that this solution is not for the use case where the user’s authentication is rejected due to an invalid certificate by OAM and then the user needs to fallback to a FORM for another authentication attempt.

Main Article

Overview

The solution needs configuring a X509 (Cert) Authentication Scheme and a Form Authentication Scheme. The real resource needs to be protected by the Cert Authentication scheme whereas a secondary resource needs to be protected by the Form Authentication scheme. The configuration of the Form Authentication is standard whereas the configuration of the Cert Authentication scheme is little different. The Challenge URL of the Cert Authentication scheme is a custom credential collector (different than the out of the box configuration). This custom credential collector is a servlet and needs to be deployed to the OAM managed server(s).

Prerequisites

All the necessary configurations in Weblogic and OAM are configured with SSL and make sure that the default out of box X509 Authentication is working as desired.
Make sure while configuring the SSL for the OAM Server in the Weblogic Configuration (Weblogic-Domain->Environment->Servers->oam_server->SSL->Advanced), in the Two Way Client Cert Behavior, you select “Client Certs Requested but Not Enforced”.


If the OAM server is front ended with OHS/Apache you need to offload SSL with reference to a Weblogic server.
And also make sure that the directive “SSLVerifyClient” is set to optional in the httpd.conf file.

OAM Configuration

Authentication Scheme Configuration:

Create a new Authentication Scheme, named X509CustomCred as below:

Challenge Method: X509
Challenge Redirect URL: /oam/server
Authentication Module: X509Plugin
The Challenge URL is the URL for the custom credential collector (a Servlet) and as follows: https://oam.oracleateam.com:14101/customcred/getcreds

(In this post, it is assumed that the Weblogic’s SSL port is 14101)

A snapshot of Authentication scheme will look like:


authscheme

Configure X509Plugin Authentication Module:

With this plug-in, the root and sub CA certificates must be added to the DOMAIN_HOME/config/fmwconfig/amtruststore because the X509CredentialExtractor plug-in loads certificates from this location.
Also, make sure about the following:

Go to System Configuration->Custom Authentication Module->X509Plugin

Under stepX509:

set KEY_IS_CERT_VALIDATION_ENABLED to true
set KEY_CERTIFICATE_ATTRIBUTE_TO_EXTRACT to the certificate attribute to be used to bind the public key (attributes within subject, for example: subject.DN, issuer.DN, subject.EMAIL etc. or within subjectAltName as mentioned in http://docs.oracle.com/cd/E27559_01/admin.1112/e27239/oam_set.htm ).

Under stepUI:

If the Identity Store is different than the default Identity Store, configure this as required.

Policy Configuration:

The target resource is protected by the X509CustomCred Authentication Scheme (created above).

We will configure another resource, for example, a Resource URL /form/*, protected by the default LDAPScheme. Both the X509CustomCred and the LDAPScheme should be at the same Authentication Level.

A snapshot of  the Policy for this secondary resource will look like:

ldapscheme-policy

Custom Credential Collector

Deployment descriptor:

The custom credential collector is a Servlet and deployed as a warfile. This is a Servlet where OAM redirects to collect the credentials.
For the Challenge URL as mentioned above, the servlet-mapping of the deployment descriptor (web.xml) will look like:
<servlet-mapping>
<servlet-name>GetCreds</servlet-name>
<url-pattern>/getcreds</url-pattern>
</servlet-mapping>

And the deployment descriptor for the warfile, that is, the context root of the weblogic.xml will look like:
<context-root>/customcred</context-root>

Code:

The logic of the Servlet is as follows:
If the X500Principal is available then we forward the request to “/oam/server/auth_cred_submit”. If it is not available then we redirect to a page which is protected by a default LDAPScheme with a FORM Challenge.

A typical code can be implemented like this:

 

/** Copyright 2012 Oracle Corporation. 
* All Rights Reserved. 
* 
* Provided on an 'as is' basis, without warranties or conditions of any kind,  
* either express or implied, including, without limitation, any warranties or 
* conditions of title, non-infringement, merchantability, or fitness for a 
* particular purpose. You are solely responsible for determining the 
* appropriateness of using and assume any risks. You may not redistribute. 
**/

public void doGet(HttpServletRequest request, HttpServletResponse response) 
			throws ServletException, IOException {
try {
       X509Certificate  x509Cert[] 
	  = (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate");
        String x500Prin = x509Cert[0].getSubjectX500Principal().getName();
        if(x500Prin != null) {
                doPost(request, response);  
         }  
     } catch (Exception e) {
            String target = request.getParameter("resource_url");            
            String  redirectURL = formURL  + "?TARGET=" + target;
            response.sendRedirect(redirectURL);
        } 
    }

protected void doPost(HttpServletRequest request, HttpServletResponse response) 
			 throws ServletException, IOException {
        String authCredServletPath = "/server/auth_cred_submit";               
        ServletContext sc1 = getServletContext(); 
        ServletContext sc2 = sc1.getContext("/oam"); 
        RequestDispatcher rd = sc2.getRequestDispatcher(authCredServletPath);        
        rd.forward(request, response);
    }

 


In the doGet method, the String “formURL” is the URL of the resource protected by the LDAPScheme. This resource can be a JSP (refer to Sample JSP for Redirection to Original Resource), a Servlet or may be a simple HTML with Javascript. This page will extract the TARGET from the query parameter which is the original “resource_url” and will redirect to that.
For example, if:
The original resource URL (the original target) is: http://oam.oracleateam.com:7778/test.html  (protected by the Custom Credential Collector with X509 Challenge) and the formURL  is: http://oam.oracleateam.com:7778/form/redirect.jsp (protected by the LDAPScheme with FORM Challenge) then the redirectURL will be formed as:
http://oam.oracleateam.com:7778/form/redirect.jsp?TARGET=http%3A%2F%2Foam.oracleateam.com%3A7778%2Ftest.html

Sample JSP (redirect.jsp as above) for Redirection to Original Resource:

<!-- Copyright 2012 Oracle Corporation. 
# All Rights Reserved. 
# 
# Provided on an 'as is' basis, without warranties or conditions of any kind,  
# either express or implied, including, without limitation, any warranties or 
# conditions of title, non-infringement, merchantability, or fitness for a 
# particular purpose. You are solely responsible for determining the 
# appropriateness of using and assume any #risks. You may not redistribute.
-->
<%
  String query = request.getQueryString();
  String target = null;
  String decodedTarget = null;
  int tokenN = -1;
  if (null != query) {
   tokenN = query.indexOf("TARGET=");
    if (-1 != tokenN)
    target = query.substring (tokenN + "TARGET=".length());
    if (null != target)      
     decodedTarget = java.net.URLDecoder.decode(target);
    if(decodedTarget != null) 
        response.sendRedirect(decodedTarget);    
    else
         out.println ("No Target to redirect");
  }
  else {
  out.println ("No Query found to extract Target");
  }
 %>

Results

The user tries to access the resource which is protected by the authentication scheme X509CustomCred.
If the browser has the certificate installed, the user is prompted by an X509 Certificate and if the user accepts it, the user can access the resource and this is the desired behavior with X509.

If the user does not accept it or if the browser does not have the certificate:

  1. 1. The user will be redirected to a secondary resource which is protected by a HTML Form with a TARGET query parameter of the original resource URL.
  2. 2. The user enters username and password and hits the Submit button.
  3. 3. Upon successful authentication and authorization, the secondary resource ( it may be JSP, a Servlet or a HTML page with javascript)  will extract the TARGET  query parameter of the original resource URL and will redirect to that.
  4. 4. The user can access the original resource URL.

Unsolicited login with OAM 11gR2

$
0
0

In a previous post Chris Johnson has discussed unsolicited login with OAM 11g.

In OAM 11gR2 this functionality is supported out of the box and with little effort you can implement Unsolicited Login.
 
 
This post is part of a larger series on Oracle Access Manager 11g called Oracle Access Manager Academy. An index to the entire series with links to each of the separate posts is available.

 

 
 
If you're interested to authenticate using unsolicited POST, please read on…
 
 

The complete procedure is explained in the official documentation here, but the docs are not clear on some aspects of the configuration.
 
 
To begin with, the documentation states that you have to manually edit the oam-config.xml file, but it does not say where to find it or which one to edit.
 
 
In my lab installation, I found six different oam-config.xml scattered across several folders.
 
After some trial and error I found out that the correct one to edit is OAM_DOMAIN/config/fmwconfig/oam-config.xml
 
Where OAM_DOMAIN is the WLS domain folder for the OAM domain.
 
 
Don’t forget to bounce Admin and Managed Servers after editting the oam-config.xml.
 
Note that in a distributed environment you want to make changes to the file on the admin server and it will then get pushed out to the managed servers after restarts.
 
Now all you have to do is post the login info to the endpoint https://oam_host:oam_port/oam/server/authentication.
 
 
The required information you need to post to the endpoint is:
 
  • username
  • password
  • successurl
     If the authentication succeeds, you will be redirected to the successurl you passed to the endpoint.
 
 
     In case the authentication fails, you will be redirected to the default OAM error page:
 
 
      Now, that isn’t very nice, right?
 
        If you want to get redirected to a custom error page, for instance, to the same login page with the error message displayed in it so you can try to login again, you just need to edit the Authentication Policy for the /oamDirectAuthentication resource (we will talk about this resource further on).
 
 
      To do so, go to Application Domains, IAM Suite, Resources and search for /oamDirectAuthentication.
 
        Open it and edit its Authentication Policy to include the Failure URL to the page you want to be redirected in case of authentication errors.
 
 
 
        If you don’t want to mess with the default Authentication Policy, which is used by other Resources, you can create another Authentication Policy for this resource and make the required changes.
 
        To display the errors messages, check out the docs about creating Custom Error Pages here 
 
        To test the whole thing, you can use a simple JSP to post the info to OAM:
 
 
        And for the JSP of the success URL I print all the request parameters, headers and session attributes:
 
 
         From this point on, you’re already authenticated to OAM and you can access any resources you’re authorized to.
 
        The documentation also describes how you can combine different HTTP operations (POST, GET, DELETE, etc) with different Authentication Schemes (FORM, CERT, etc).
 
        If you have specific requirements for the unsolicited login, you can create/edit the /oamDirectAuthentication Resource of IAM Suite Domain. This resource controls all the specifics of unsolicited authentication, for example, allowing only for HTTP POST and FORM based authentication.
 
        The resource /oamDirectAuthentication is a virtual resource that is defined in the system that represents the physical endpoint for unsolicited login. 
 
        So, when it comes to policy configuration you will always deal with /oamDirectAuthentication, however when it comes to the physical endpoint (the actual servlet URL for posting information) you will use /oam/server/authentication.

 

Part 1: Under the Covers of OAM11g WNA integration with Multiple AD Forests

$
0
0

Introduction

This post is part of a larger series on Oracle Access Manager 11g called Oracle Access Manager Academy. An index to the entire series with links to each of the separate posts is available.

This is the first post of a three part series that expands on a great article Matt wrote — “The (Windows) Natives Are Restless”. Matt’s article covered some configurations, browser settings, and some examples of role mapping, but I want to dive into this whole WNA solution a lot more. So Part 1 will include just what the title eludes to, Under the Covers of the WNA integration with Multiple Active Directory Forests, then Part 2 will cover the details of the WNA configuration to make it work against multiple untrusted or trusted domains, and finally in Part 3) some highlights on leveraging OVD11g to pull it all together and make sure WNA can find the correct user across multiple forests.

Main Article

 

A Quick Primer on WNA

As a quick primer if you did not read Matt’s post, WNA stands for Windows Native Authentication. The latest official Oracle document on WNA integration can be found in chapter “43 Configuring Access Manager for Windows Native Authentication”. Basically this is an integration where a client can login to their Windows Desktop, open an Internet browser, then navigate to an OAM11g protected HTTP resource, and go right in using the Kerberos Service Ticket without even being challenged. Neat, but where the mystery lies is how this all flows and magically works behind the scenes. I am a firm believer in visual illustrations to help explain a complicated process, so a good sequence diagram seems like the best way to do it for this topic. Ta da!

WNA_Sequence_Diagram

 

Behind the realms and master keytab file store

As I walk through the flow keep in mind that the hostnames and ports could be different in your environment so you will need to just extrapolate and understand I am mapping this flow to HTTP traces and logs from my example environment just for illustration purposes.  I also masked the dates and time in the logs, but the sequence of these events is accurately described based on my personal observations.

At the first login OAM will load the initial KDC servers listed in the keytab

So before I jump into the sequence steps of the diagram I wanted to point out how OAM will load the data from the master keytab the first time WNA happens. Below in the Weblogic OAM Managed Access Server log you can see OAM loading all the KDC servers listed in the keytab as it initializes the first Kerberos authentication using WNA. Notice how it iterates all the KDC servers? In my case my environment has 5 KDC servers sequenced as FOREST1, FOREST2, etc. to FOREST5.  Also note that my service principal accounts that were created in each KDC Server using KTPASS is iam.melander.us, if each of your service principal accounts are different your log will reflect that. Another way to see this list is to see my Part 2: How to Configure OAM11g WNA for Multiple AD Forests on how to use klist to list all the service principals and KDC servers in the master keytab.

OAM WEBLOGIC LOG – KERBEROS DEBUG LEVEL
——————————————————
>>> KeyTabInputStream, readName(): FOREST1.MELANDER.US
>>> KeyTabInputStream, readName(): HTTP
>>> KeyTabInputStream, readName(): iam.melander.us
>>> KeyTab: load() entry length: 75; type: 23
>>> KeyTabInputStream, readName(): FOREST2.MELANDER.US
>>> KeyTabInputStream, readName(): HTTP
>>> KeyTabInputStream, readName(): iam.melander.us
>>> KeyTab: load() entry length: 75; type: 23
>>> KeyTabInputStream, readName(): FOREST3.MELANDER.US
>>> KeyTabInputStream, readName(): HTTP
>>> KeyTabInputStream, readName(): iam.melander.us
>>> KeyTab: load() entry length: 75; type: 23
>>> KeyTabInputStream, readName(): FOREST4.MELANDER.US
>>> KeyTabInputStream, readName(): HTTP
>>> KeyTabInputStream, readName(): iam.melander.us
>>> KeyTab: load() entry length: 75; type: 23
>>> KeyTabInputStream, readName(): FOREST5.MELANDER.US
>>> KeyTabInputStream, readName(): HTTP
>>> KeyTabInputStream, readName(): iam.melander.us
>>> KeyTab: load() entry length: 67; type: 1
>>> KeyTabInputStream, readName(): FOREST5.MELANDER.US
>>> KeyTabInputStream, readName(): HTTP
>>> KeyTabInputStream, readName(): iam.melander.us
>>> KeyTab: load() entry length: 67; type: 3
>>> KeyTabInputStream, readName(): FOREST5.MELANDER.US
>>> KeyTabInputStream, readName(): HTTP
>>> KeyTabInputStream, readName(): iam.melander.us
>>> KeyTab: load() entry length: 75; type: 23
>>> KeyTabInputStream, readName(): FOREST5.MELANDER.US
>>> KeyTabInputStream, readName(): HTTP
>>> KeyTabInputStream, readName(): iam.melander.us
>>> KeyTab: load() entry length: 91; type: 18
>>> KeyTabInputStream, readName(): FOREST5.MELANDER.US
>>> KeyTabInputStream, readName(): HTTP
>>> KeyTabInputStream, readName(): iam.melander.us
>>> KeyTab: load() entry length: 75; type: 17
Added key: 23version: 3
Ordering keys wrt default_tkt_enctypes list
default etypes for default_tkt_enctypes: 23.
0: EncryptionKey: keyType=23 kvno=3 keyValue (hex dump)=
0000: 8B 23 18 52 4D 2E 3E 2E 31 88 5A FC 21 02 4C F5 .#.RM.>.1.Z.!.L.

Sequence 1 – 5: Windows Desktop Login Only

The sequence flows in the above diagram in red are basically everything that happens during the Windows desktop login, and the green sequence flows are part of the OAM authentication process when initially requesting an OAM protected HTTP resource.

Sequence 6: WebGate Interception and Browser Redirect

As the WebGate intercepts the client’s request for http://portal.melander.us/index.html it tries to determine if the browser has the OAMAuthnCookie_<web serve hostname>. If not the WebGate will immediately check with the OAM Access Server to determine how it should authenticate. In this case the OAM Access Server tells the WebGate to send a HTTP 302 and redirects the client to the Access Server authentication host http://iam.melander.us:14100/oam/CredCollectServlet/WNA to do some Windows Native Authentication steps.

HTTP TRACE
—————————————————
HTTP/1.1 302 Moved Temporarily
Connection: close
Transfer-Encoding: chunked
Location: http://iam.melander.us:14100/oam/CredCollectServlet/WNA?authn_try_count=0&spnegotoken=string&challenge_url=%2Foam%2FCredCollectServlet%2FWNA&request_id=-1010974851419667276&OAM_REQ=&locale=en_US&resource_url=http%253A%252F%252Fportal.melander.us%252Findex.html
Set-Cookie: OAM_REQ=VERSION_4~6jVb8GPbhvhBRSSlg35wrBG6NF8eYu%2bW6aUQefACCr08xA9apcyLJFSYrE2fcxDkgA2IOAholgCM42jgNnuDx15K9n0hxFfOrkAV4nMmEN4syBJL5PUFTU%2blOUznSGoEor1R%2bmFnMkO3ArJz2J%2bwUtJumR9KT3B4KUrNBIBkWSNHwx0lgQBmlItkQZdU4FanW7or1bJ9obj3uyMIzIJaJFbSP9JlNglMcL2KbCktAZzVgvWwLh7o1Nj21JmIa5Be5byF2geGS0VbAh%2fbgNkq3WV0VB7ItxETuxNOo3Z4GDAOZ8jARN47ToPsxpFjLkbxx3u7%2bCdMqJZmXkBmFTjJ1jJP7XBraVaZ9ArrHU%2bypMSjXvg8fXGKJcJFV1EYJKHYzSjVbkI44XIJb15Idhc8%2fQ%2bQMudPRyVRB3DYsQd%2fwW6ej4l8udOSxxXpp7uvz6HhLIRLpBlNsQqf9mFL0QhKneD%2bsnkCexKpZycWmdGhtv3T%2fyQnR1hjMMQcIfk8cq3d0z2f9T2FjItOC2vwfy6cYIHKHKoAx%2bTg3pyD9wii0ySsr7YAIMZDMBYWcBqjlLgUOfhQfq7wKdiwNj7H1YHH3NOoZWUKy2ILo0OwwYc5MR%2fI8ujYUp40PwJiHUXZY5DFl70mLoEh1XA7iVwy1kJrFPmBIoBiHZrEzeWrmrce0%2fvyDxwS51h6GZ83WI45jlEQmFaLF2k1V4yASwGBPG5XmQZYCgtgcCWZATKaSHX6yX8zcfVXBSDEF0KzjI4M%3d; path=/; HttpOnly

 

Sequence 7:  HTTP 401 Respond with WWW-Authenticate: Negotiate

The OAM Access Server tells the WebGate to respond with a HTTP 401 and an additional header WWW-Authenticate: Negotiate say we need to use Kerberos to negotiate authentication.

HTTP TRACE
———————————————————-
HTTP/1.1 401 Unauthorized
Cache-Control: no-cache, no-store
Date: XXX, XX XXX XXXX XX:XX:XX GMT
Pragma: no-cache
Content-Length: 0
Content-Type: text/html; charset=UTF-8
Expires: 0
WWW-Authenticate: Negotiate
WWW-Authenticate: Basic realm=”OAM 11g”

 

Sequence 8:  Browser sends the Kerberos Token over HTTP

Next the browser will send the Kerberos token to the OAM Access Server for processing. 

HTTP TRACE
—————————————————
GET /oam/CredCollectServlet/WNA?authn_try_count=0&spnegotoken=string&challenge_url=%2Foam%2FCredCollectServlet%2FWNA&request_id=684028674492683329&OAM_REQ=&locale=en_US&resource_url=http%253A%252F%252Fportal.melander.us%252Findex.html HTTP/1.1
Host: iam.melander.us:14100
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:20.0) Gecko/20100101 Firefox/20.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Cookie: OAM_REQ=VERSION_4~SpniCadlpD2uzvOHLApdZY9RgF2ZalJxlxgk58fvhFDY4i4ZMQFiBajsEYVypYr96d8bQwwKMw3NREi3c2xCzK7WEihLoUbs2AA1rk40XwXmS3ODfusGamPR2%2brYp7hNxqDQUaEtSelv1JOmEqKp0eHbRyEKkPTQ6nfxzupykWujqV55tMnwtcG7ZDu%2bvo22DwZNaFUt9OlBhYarndqU0bTi87retmEKay1bUe08UlOKrEdUuc8%2b%2fMRwSZF0SVD9c5WlsKhOyfZfEjBm34U32NIUlabpacRDJiqDTOb8m8VmdYF%2f86sTJXCHK3UvpJ8AM8HOk%2b9fOZRZvR8G%2bXzOYnN8LHJKUS06KLyC9RMjVgIRAtvC0UzFW1HrvNw0%2fkPOFNrVk1Gj%2f0Nc8uQG3jb5Wf%2fyNbFhCGf3F3wgECcp2X8DxBBLUHxlmJg%3d<removed extra length for illustration>
Connection: keep-alive
Authorization: Negotiate YIIFGwYGKwYBBQUCoIIFDzCCBQugJDAiBgkqhkiC9xIBAgIGCSqGSIb3EgECAgYKK
wYBBAGCNwICCqKCBOEEggTdYIIE2QYJKoZIhvcSAQICAQBuggTIMIIExKADAgEFo
a4W0NtIxsPHagvL8BX3+9PtsTHVNH2Yr2pjl1UH/757/st+<removed extra length for illustration>

 

Sequence 9:  Get Kerberos Token from Browser

OAM Access Server accepts the Token to use SPNEGO, more on this here http://en.wikipedia.org/wiki/SPNEGO.  Then OAM prepares to check the Keytab and validate what KDC this Token came from (Notice in the OAM log below the SPNEGO NegTokenTarg).

OAM WEBLOGIC OAM_SERVER LOG – KERBEROS DEBUG LEVEL
———————————————————-
>>> KrbApReq: authenticate succeed.
Krb5Context setting peerSeqNumber to: 1701245029
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
Krb5Context setting mySeqNumber to: 643706622
SPNEGO Negotiated Mechanism = 1.2.840.113554.1.2.2 Kerberos V5
SpNegoContext.acceptSecContext: mechanism wanted = 1.2.840.113554.1.2.2
SpNegoContext.acceptSecContext: negotiated result = ACCEPT_COMPLETE
SpNegoContext.acceptSecContext: sending token of type = SPNEGO NegTokenTarg
SpNegoToken NegTokenTarg: sending additional token for MS Interop
SpNegoContext.acceptSecContext: sending token = a1 81 eb 30 81 e8 a0 03 0a 01 00 a1 0b 06 09 2a 86 48 86 f7 12 01 02 02 a2 69 04 67 60 65 06 09 2a 86 48 86 f7 12 01 02
KeyTab instance already exists
Added key: 23version: 3
Ordering keys wrt default_tkt_enctypes list
default etypes for default_tkt_enctypes: 23.
0: EncryptionKey: keyType=23 kvno=3 keyValue (hex dump)=
0000: 8B 23 18 52 4D 2E 3E 2E 31 88 5A FC 21 02 4C F5 .#.RM.>.1.Z.!.L.

 

Sequence 10 – 11:  Find the correct KDC server by checking the Realm in the krb5.conf

Looking at the Access Server log below you see it searching for the KDC server in the krb5.conf file using the master keytab.  Using the Token it will test each keytab until it finds one that validates and once it does it should give a status KrbApReq: authenticate success.  The Access Server during this process contacts the KDC server, so it is very important that the Access Server can resolve the KDC server hostname and also reach it via UDP over TCP on port 88.   If the Access Server cannot contact the KDC or if the UDP port is blocked, authentication will immediately fail and oddly OAM returns a message “The user account is locked or disabled.  Please contact the System Administrator.”, which is misleading though the point is the authentication will immediately fail.   You should also know this process is done in real time, so for example if there are any network or DNS issues that prevents OAM from contacting the KDC at the time of any WNA authentication, it will immediately fail and the message I mentioned will be presented.  Once the KDC network or DNS issue is resolved the authentication will again work without any service restarts or changes to OAM.

 

OAM WEBLOGIC OAM_SERVER LOG – KERBEROS DEBUG LEVEL
———————————————————-
default etypes for default_tkt_enctypes: 23.
>>> KrbAsReq calling createMessage
>>> KrbAsReq in createMessage
>>> KrbKdcReq send: kdc=forest1.melander.us UDP:88, timeout=30000, number of retries =3, #bytes=166
>>> KDCCommunication: kdc=forest1.melander.us UDP:88, timeout=30000,Attempt =1, #bytes=166
>>> KrbKdcReq send: #bytes read=164
>>> KrbKdcReq send: #bytes read=164
>>> KdcAccessibility: remove forest1.melander.us
>>> KDCRep: init() encoding tag is 126 req type is 11
>>>KRBError:
sTime is XXX XXX XX XX:XX:XX CDT XXXX 1401812121000
suSec is 300663
error code is 25
error Message is Additional pre-authentication required
realm is FOREST1.MELANDER.US
sname is krbtgt/FOREST1.MELANDER.US
eData provided.
msgType is 30
>>>Pre-Authentication Data:
PA-DATA type = 11
PA-ETYPE-INFO etype = 23
PA-ETYPE-INFO salt =
AcquireTGT: PREAUTH FAILED/REQUIRED, re-send AS-REQ
>>>KrbAsReq salt is FOREST1.MELANDER.USHTTPiam.melander.us
default etypes for default_tkt_enctypes: 23.
Pre-Authenticaton: find key for etype = 23
AS-REQ: Add PA_ENC_TIMESTAMP now
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
>>> KrbAsReq calling createMessage
>>> KrbAsReq in createMessage
>>> KrbKdcReq send: kdc=forest1.melander.us UDP:88, timeout=30000, number of retries =3, #bytes=249
>>> KDCCommunication: kdc=forest1.melander.us UDP:88, timeout=30000,Attempt =1, #bytes=249
>>> KrbKdcReq send: #bytes read=1318
>>> KrbKdcReq send: #bytes read=1318
>>> KdcAccessibility: remove forest1.melander.us
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
>>> KrbAsRep cons in KrbAsReq.getReply HTTP/iam.melander.us
Found key for HTTP/iam.melander.us@FOREST1.MELANDER.US(23)
Entered SpNegoContext.acceptSecContext with state=STATE_NEW
SpNegoContext.acceptSecContext: receiving token = a0 82 05 0f 30 82 05 0b a0 24 30 22 06 09 2a 86 48 82 f7 12 01 02 02 06 09 2a 86 48 86 f7 12 01 02 02 06 0a 2b 06 01
SpNegoToken NegTokenInit: reading Mechanism Oid = 1.2.840.48018.1.2.2
SpNegoToken NegTokenInit: reading Mechanism Oid = 1.2.840.113554.1.2.2
SpNegoToken NegTokenInit: reading Mechanism Oid = 1.3.6.1.4.1.311.2.2.10
SpNegoToken NegTokenInit: reading Mech Token
SpNegoToken NegTokenInit : no MIC token included
SpNegoContext.acceptSecContext: received token of type = SPNEGO NegTokenInit
SpNegoContext: negotiated mechanism = 1.2.840.113554.1.2.2
Entered Krb5Context.acceptSecContext with state=STATE_NEW
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
Using builtin default etypes for permitted_enctypes
default etypes for permitted_enctypes: 3 1 23 16 17.
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
object 0: 1401812121000/297
object 0: 1401812121000/297
replay cache found.
>>> KrbApReq: authenticate succeed.
Krb5Context setting peerSeqNumber to: 85335024
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
Krb5Context setting mySeqNumber to: 703946614
SPNEGO Negotiated Mechanism = 1.2.840.113554.1.2.2 Kerberos V5
SpNegoContext.acceptSecContext: mechanism wanted = 1.2.840.113554.1.2.2
SpNegoContext.acceptSecContext: negotiated result = ACCEPT_COMPLETE
SpNegoContext.acceptSecContext: sending token of type = SPNEGO NegTokenTarg
SpNegoToken NegTokenTarg: sending additional token for MS Interop
SpNegoContext.acceptSecContext: sending token = a1 81 eb 30 81 e8 a0 03 0a 01 00 a1 0b……(Full token has been removed)

 

In Part 2: How to Configure OAM11g WNA for Multiple AD Forests I will cover how to setup the krb5.conf and create the master.krb5.keytab files.  I should also point out that one reason this solution works is that all the KDC server keytabs are in a single master.krb5.keytab file.  This will also work with KDC servers that have a Transitive trust between them, either way this will work in all cases.

 

If you see any Kerberos logs that show a KRBError, this is benign and does not impact anything to do with the authentication. Below is an example of this error.
>>>KRBError: sTime is Thu Feb 07 17:11:51 CST 2013 1360278711000 suSec is 568642 error code is 25 error Message is Additional pre-authentication required realm is FOREST2.EXAMPLE.COM sname is krbtgt/FOREST2.EXAMPLE.COM eData provided. msgType is 30

 

To see Kerberos logs in the OAM Server logs, it has to be turned on by inserting a couple lines in the setDomainEnv.sh file; more on this in part 2 of this series.

 

Sequence 12:  Searching for the Authenticated User in the Identity Store

Now that OAM has validated the Kerberos ticket there are a few things that are happening.   The OAM Kerberos module extracts the Principal from the Kerberos ticket; we can see this in the following example log below.  Notice the parameter “Principal:”, it contains the fully qualified user Principal Name tim.melander@FOREST1.EXAMPLE.COM.

OAM_SERVER DIAGNOSTIC LOG – TRACE:16 LEVEL DEBUG
———————————————————-
[XXXX-XX-XXTXX:XX:XX.646-06:00] [oam_server1] [TRACE:16] [] [oracle.oam.plugin] [tid: [ACTIVE].ExecuteThread: ’0′ for queue: ‘weblogic.kernel.Default (self-tuning)’] [userId: <anonymous>] [ecid: 4aaf7073ad441920:2e5d74e2:13cb78ddb56:-8000-0000000000000040,0] [SRC_CLASS: oracle.security.am.common.diagnostic.DiagnosticUtil] [APP: oam_server] [SRC_METHOD: init] Grabbed Phase event:oracle.security.am.plugin.diagnostic.PluginPhaseEvent@39cb37ff
4941,1 40%
Principal: tim.melander@FOREST1.EXAMPLE.COM

 

Next the OAM Kerberos module strips the @FOREST1.MELANDER.US off, which leaves just “tim.melander”; see the parameter Kerb User Name in the example OAM trace log below.  This will then be used to search for the user’s samAccountName in Active Directory via the identity store defined in the authentication module.  The identity store in this case is defined to use OVD, and the DIT has been designed to look like each respective Active Directory namespace; more on this in part 3 and how to best define the DIT in OVD to work with this solution.  I also want to point out that the Identity Store does not have to be configured directly to Active Directory; it could be configured to use any Directory Server that has been certified with OAM.  Active Directory is only used to accomplish the Kerberos authentication, again more on this in Part 3: OAM11g WNA Identity Store Considerations and Configurations.

OAM_SERVER DIAGNOSTIC LOG – TRACE:16 LEVEL DEBUG
———————————————————-
[XXXX-XX-XXTXX:XX:XX.646-06:00] [oam_server1] [TRACE] [] [oracle.oam.plugin] [tid: [ACTIVE].ExecuteThread: ’0′ for queue: ‘weblogic.kernel.Default (self-tuning)’] [userId: ] [ecid: 4aaf7073ad441920:2e5d74e2:13cb78ddb56:-8000-0000000000000040,0] [SRC_CLASS: oracle.security.am.plugin.authn.KerberosTokenAuthenticator] [APP: oam_server] [SRC_METHOD: process] Kerb User Name = tim.melander

 

Next OAM will use the stripped off principal name to search in OVD, but before it does there is a special parameter we set in the custom Kerberos authentication module that is defined in one of the UserIdentificationPlugin’s, it is called KEY_USERDOMAIN, and it is used to dynamically get the proper searchbase.  Shown in the OAM trace log below we can see how the Kerberos module has taken the domain it stripped off earlier, @FOREST1.EXAMPLE.COM, and builds a search base of “dc=forest1,dc=example,dc=com”.   Notice the parameter User Domain, it will hold the namespace OAM will use to build its search against OVD.

OAM_SERVER DIAGNOSTIC LOG – TRACE:16 LEVEL DEBUG
———————————————————-
[XXXX-XX-XXTXX:XX:XX.646-06:00] [oam_server1] [TRACE] [] [oracle.oam.plugin] [tid: [ACTIVE].ExecuteThread: ’0′ for queue: ‘weblogic.kernel.Default (self-tuning)’] [userId: <anonymous>] [ecid: 4aaf7073ad441920:2e5d74e2:13cb78ddb56:-8000-0000000000000040,0] [SRC_CLASS: oracle.security.am.plugin.authn.KerberosTokenAuthenticator] [APP: oam_server] [SRC_METHOD: process] User Domain = dc=forest1,dc=example,dc=com

 

Sequence 13:  OVD searches for the User account

OVD uses the LDAP search it gets from OAM to builds its search by setting the searchbase along with the LDAP filter to find the correct tim.melander.  Shown in the OVD diagnostic log we can see from the Base and Filter, it nicely sets all the proper LDAP search parameters.  If we did not use the KEY_USERDOMAIN parameter the search would start at dc=EXAMPLE,dc=COM, and the authentication would of course fail if there were duplicate tim.melander sameAccountNames found across two or more domains.

OVD DIAGNOSTIC LOG – DEFAULT DEBUG
———————————————————-
[[XXXX-XX-XXTXX:XX:XX.192-06:00] [octetstring] [NOTIFICATION] [] [com.octetstring.vde.chain.plugins.DumpTransactions.DumpTransactions] [tid: 27] [ecid: 4aaf7073ad441920:-49d5bd7a:13cb14e92f1:-8000-0000000000000232,0:2] !SEARCH Operation: (Transaction#Adapter_Forest4.Dump After.30)[[
BindDN: cn=orcladmin
Base: dc=FOREST1,dc=EXAMPLE,dc=COM
Scope: 2
Filter: (&(samaccountname=tim.melander)(objectclass=user))
TypesOnly: FALSE
Attrs: [mail, cn, description, orclguid, objectclass, displayname, uid, samaccountname]!
]]

 

Sequence 14: OVD returns the entry it searched

Next in the OVD diagnostic log we can see how the LDAP entry tim.melander is successfully returned along with any required attributes. This will validate to OAM that indeed this user also exists in the Identity Store and return any attributes that may be required to set OAM headers needed for critical business decisions.

OVD DIAGNOSTIC LOG – DEFAULT DEBUG
———————————————————-
[XXXX-XX-XXTXX:XX:XX.194-06:00] [octetstring] [NOTIFICATION] [] [com.octetstring.vde.chain.plugins.DumpTransactions.DumpTransactions] [tid: 27] [ecid: 4aaf7073ad441920:-49d5bd7a:13cb14e92f1:-8000-0000000000000232,0:2] !SEARCH Entry Before Plugins: (Transaction#Adapter_Forest1.Dump Before.30)[[
DN: CN=Tim Melander,CN=Users,DC=forest1,DC=example,DC=com
displayName: Tim Melander
cn: Tim Melander
sAMAccountName: tim.melander
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: user

 

Sequence 15 – 16:  OAM sets the OAMAuthnCookie for SSO

Then in flow 15 to 16 OAM after successfully authenticating and finding the user, it sets the proper OAMAuthnCookie for SSO and do a HTTP 302 to redirect the browser to the original requested URL, or if a Success URL were defined in the policy it would redirect the browser to that URL.

HTTP TRACE
———————————————————-
HTTP/1.1 302 Found
Date: Tue, 03 Jun 2014 18:03:33 GMT
Server: Oracle-Application-Server-11g
Set-Cookie: OAMRequestContext_portal.melander.us:80_426645=; Expires=Thursday, 01-Jan-1970 01:00:00 GMT; path=/;
Set-Cookie: OAMAuthnCookie_portal.melander.us:80=6REKqtu%2FlKImJXIqAYegptKkTUYnnjnLh2lrvZANEbwp7dMIpL6EO7sNc3Qxw1VKtpYtHeltJdy3umY6LH7LUdqL9Yl6Eg15fzDlRWP1zE0RPKwjqRdeHt7XIEwga5B8oY6nMw5bFTnlRgiPGRu07gydDa3%2BBs71t5eTbt3wkpTg3g3SWjWv8BCE4R23qDmszoiZlbTLeSswvIAKQYUp8PNR9P8L67hI94enJaG8Bz%2FgLLdJiw3aXZQTxDlLPcnuNvGKizs2ClmIxk6ead36mdUu9YAv3IOsOTClzFtEfreCKBhmSS06ZLAVUboxVfh3zGB5SEg1Vcp0rjBFJbg4S%2F7mR3mPXrbWO6I3Yxq%2F%

 

Summary

I hope this will help you understand how the entire OAM WNA authentication process works from end-to-end.  Understanding the flow helps considerably in trying to troubleshoot.  As you check out Part 2: How to Configure OAM11g WNA for Multiple AD Forests of this series to understand the detail of how to configure OAM11g for the WNA integration I would suggest referring back to Part 1 to make sure you clearly understand the flow in order to troubleshoot as you run into problems.   Part 2 covers multiple domains whether they are trusted or untrusted, and I will also include tips on troubleshooting.

Part 2: How to Configure OAM11g WNA for Multiple AD Forests

$
0
0

Introduction

This post is part of a larger series on Oracle Access Manager 11g called Oracle Access Manager Academy.  An index to the entire series with links to each of the separate posts is available.

This is the second post of a three part series.  In “Part 1: Under the Covers of OAM11g WNA integration with Multiple AD Forests“, I covered the flow of how WNA works and what was going on behind the scenes.  This article will cover the technical details on how to implement WNA in a way that will support multiple Active Directory Forests that either have no transient trust between them, or even all trusted; in either case this will work for you.

Before we get into the details on how to setup WNA for multi Active Directory domains I just want to point out that I will use a straw man of three Active Directory KDC servers so you can understand any additional steps needed to support more than one KDC.  However, this would also work for as few as one domain, or more than three domains.  All that is needed is to simply extrapolate the steps to fit your requirements; I will be sure to comment where necessary.

Main Article

Patch It Up!

Out-of-the-box the standard OAM Kerberos plugin can be used to accomplish basic WNA integration against a single domain, which works perfectly without any need to install a patch.  However this solution is about authenticating against multiple forests or domains, and for that a custom Kerberos authentication module is required.  Don’t worry, no coding necessary, this is all out-of-the-box using the OAM Console.  From my experience the custom Kerberos authentication module did not even work until OAM11gR1 was patched up to BP05, but if you are using OAM11gR2, that should work unpatched; more on that later.  You may also want to know, that using this custom Kerberos authentication module is a good thing because the standard LDAP, Kerberos, and x509 authentication modules will soon be depreciated.

So first things first, this solution requires that OAM11gR1 (11.1.1.5.0) be patched with bundle patch BP05 (patch 14760839 released on 1/15/2013).   If this is OAM11gR2 (11.1.2.0.1) there are no WNA fixes in any of the bundle patches up to the most recent BP02, but I recommend as a best practice to patch up to the latest regardless because it usually includes bug fixes, maybe some new features, and potential critical fixes for other reasons.  Just do it.  At the time this blog was written, the most current patch for OAM11gR2 is bundle patch BP02 (patch 14760806 released on 1/15/2013).

Please review the readme.html that is included in the bundle patch zip file.  As of BP04, there are now two independent steps to the patching process, 1) run “opatch apply” to install the initial bundle patch, and 2) a post patch step where a script domainAutomation.sh is run to make changes to the domain and the oam-config.xml file.

OAM11g has historically been one of the tricky components to patch.  I have found that after running “opatch apply”, it is a good idea to start up the WebLogic Admin server and the OAM Managed Server being patched to make sure they come up correctly, if so, then bring them back down and verify both are completely down.  You can use netstat –na | grep <port; e.g. 14100, 7001> to determine if each are completely down.  Then go ahead with the post step to run the domainAutomation.sh script.  For any other questions on patching I recommend this great article “Patch Management of an Oracle Identity Management Deployment” by Brian Eidelman of the A-Team.


For your information, BP05 includes some current WNA bug fixes and some additional WNA related fixes that were inherited from BP04.  Fixes include inconsistent behavior with WNA, a fix that caused failed authentications when a duplicate samAccountName was found, and some updates to the oam-config.xml that provide a new KTA (KerberosTokenAuthenticator) parameter, which we will take advantage of; so patch it up!

Create the Service Principal Account

A service principal has to be created in each KDC server that will be used by the OAM Windows Native Authentication.  This is basically a User account, and does not need any special permission or belong to any group, and the User name can be different across individual KDC servers.  However, even though this new account is created like a regular User, it should be considered a service account.  The account is not meant for a User to login to a domain, it is only meant as a service principle that is mapped and encrypted to a keytab, which OAM will use for WNA against each respective KDC server.

As a security measure, I would advice to use a strong password and to locate the account in a container that is for service accounts only.  I would also use any additional measures to protect this account from being used in any rogue way.  It should also be noted if the password expires WNA will fail to work.

 

Creating the Master Keytab File

A keytab is a file that contains an unencrypted list of service principals and their keys from which the OAM Kerberos module will use to validate the User’s Kerberos service ticket without the User needing to provide any password.  The first keytab we generate will be the seed keytab file, followed by appending additional keytab files, and the final keytab file for this solution will contain all the keytabs from each KDC server that will be used by WNA; I call it the master keytab file.  This single file is one of the keys to making WNA work against multiple untrusted Active Directory domains.

Step 1 – Generating the First Keytab File

To create a keytab file the ktpass tool is required.  This is a tool found in the Windows Support install that comes with Windows Server; later versions of Windows server like Windows 2008 R2 may already include this tool.  For more information on ktpass you can go to the Microsoft Technet site.   As a tip, if using Windows 2003 Enterprise server, the version of ktpass needs to be installed from the Support Tools that comes in SP1 or higher.  The base ktpass does not support the correct Kerberos RC4-HMAC protocol.  If this means you, Microsoft provides this as a free download from the Microsoft Download Center KB892777.

If you execute “ktpass /?” at the Windows command-line, in the list of options you should find crypto. The newer version of ktpass will display RC4-HMAC-NT, this is the version of crypto that is required to make the proper keytab. However, if using Windows 2008 R2 Server, AES-256 may be required; read further on comments about this and special syntax required.

[- /] crypto : DES-CBC-CRC : for compatibility
[- /] crypto : DES-CBC-MD5 : for compatibliity
[- /] crypto : RC4-HMAC-NT : default 128-bit encryption


So the following command will need to be run on each KDC server, but the first one will need to be run as follows.  As a Windows Domain Administrator at a command-line use the following command; you will need to modify the values per your configuration and environment.  Below are two options based on which version of Windows Server you are using; differences are highlighted in red; credit goes to Michael Storrs for catching me on missing this subtle yet important difference.  Note the syntax in red relates to a KB article “OAM 11g WNA Login Fails When Using Windows 7/2008 Clients in an Active Directory 2008 R2 Server domain [ID 1509275.1]“.  Another reason to use the Windows 2008 R2 syntax is to support clients that use Windows Vista, Windows 2007, and Windows 2008, because these clients do not use RC4-HMAC-NT encryption, instead they could be configured to use AES-256 encryption type.


Windows 2003 Server Syntax -
ktpass -princ HTTP/oam.server.com@FOREST1.SPRITE.COM /
-mapuser oamkrb5 /
-pass Oracle123 /
-out forest1.krb5.keytab


Windows 2008 R2 Server Syntax -
ktpass -princ HTTP/oam.server.com@FOREST1.SPRITE.COM /
-mapuser oamkrb5 /
-pass Oracle123 /
-ptype KRB5_NT_PRINCIPAL /
-crypto ALL /
-out forest1.krb5.keytab

ParameterDescription-princHTTP/<oam_server_hostname>@<kdc_server_hostname>-mapusersamAccountName of the service principal account-passPassword for the security principal account-ptype KRB5_NT_PRINCIPAL* This is the general principal type.-crypto ALL* Tells ktpass to output all crypto types.-outThe keytab output file name

* Syntax for Windows 2008 R2 Server

This command will generate a keytab file forest1.krb5.keytab.  The file name is arbitrary; it could be anything you want.  However in order to keep things straight, I recommend prefixing the file name with the KDC server it was generated on so that there is no question of which KDC server the keytab was last generated.  This is more important for later steps.

After you run the command you should see some screen output similar to the following.  You will see more output if using the Windows 2008 R2 syntax.

Targeting domain controller: orcl.forest1.sprite.com
Using legacy password setting method
Successfully mapped HTTP/oam.server.com to oamkrb5.
WARNING: pType and account type do not match. This might cause problems.
Key created.
Output keytab to forest1.krb5.keytab:
Keytab version: 0x502
keysize 75 HTTP/oam.server.com@FOREST1.SPRITE.COM ptype 0 (KRB5_NT_UNKNOWN) vno 3 etype 0x17 (
RC4-HMAC) keylength 16 (0x8b2318524d2e3e2e31885afc21024cf5)

 

In the bold highlighted output above, you can disregard the pType warning; this is a benign error.  Also make sure the crypto version shows an output of RC4-HMAC to show we are using the correct Kerberos crypto for Windows 2003, or AES-256 for Windows 2008.


To validate the keytab was correctly mapped to the service account, open Active Directory Users and Computers > navigate to the container the service account was created > right click on the service principal User account > select Properties > select the Account tab > you should now see in the User logon name field the value HTTP/oam.server.com has been added.  This shows that when ktpass was run it mapped this account to the keytab file properly when it was generated.

Step 2 – Appending Additional Keytabs to Create the Final Master Keytab File

Now we need to generate the remaining keytabs from each KDC server and continue to append each existing keytab to a new keytab file.  For example each additional KDC server that needs to be authenticated against, you will need to run the ktpass tool again, but with an additional parameter “-in” along with the last file <kdc_server_host>.krb5.keytab created.   This is an iterative process that will ultimately create a single file that will contain all the keytabs; the final file will be named the master.krb5.keytab file.

In the previous step I pointed out it is a good idea to prefix the keytab file name with the KDC server name; e.g. forest1.krb5.keytab, forest2.krb5.keytab, etc.  The methodology behind this approach is to help know which KDC server the keytab was run from last so that it is less likely a mistake is made as you build up all the keytabs into a single master copy.  So it would be a good idea to list all the KDC servers in some the order and follow that list to run the ktpass tool in order to build the keytab files.


As you repeat this process on each KDC server, you will need to build a new keytab file in a systematic way.  For example use the following command on the next KDC server, Forest2, but first copy the forest1.krb5.keytab file to this server to use as the input file from the previous step the first time ktpass was run.  What happens is this command will generate a keytab for Forest2, but also append the keytab from file forest1.krb5.keytab to create a new file with two keytabs.  Note if you are using Windows 2008 R2 include the additional syntax highlighted in red.

ktpass -princ HTTP/oam.server.com@FOREST2.PIXIE.COM /
-mapuser oamkrb5 /
-pass Oracle123 /
-ptype KRB5_NT_PRINCIPAL /
-crypto ALL /
-in forest1.krb5.keytab /
-out forest2.krb5.keytab

Parameter Description
-in The keytab file that contains existing keytabs


Now on the next KDC server, Forest3, copy the forest2.krb5.keytab file to the forest3 server and run the same following command, and so on. You get the point. The new keytab file is a combination of all the previous keytabs generated. The final KDC server you run the command on will be your master file.  Note if you are using Windows 2008 R2 include the additional syntax highlighted in red.

ktpass -princ HTTP/oam.server.com@FOREST3.FAY.COM /
-mapuser oamkrb5 /
-pass Oracle123 /
-ptype KRB5_NT_PRINCIPAL /
-crypto ALL /
-in forest2.krb5.keytab /
-out forest3.krb5.keytab

For the final step in this process I would copy the last keytab file created to master.krb5.keytab as follows.

copy forest3.krb5.keytab master.krb5.keytab

Now we have all our keytabs from each KDC in a single master file.  Congrats! Combining the keytabs into a single file is critical, but also a bonus because there is only one file to protect, to configured, and to manage.

Now copy the master.krb5.keytab file to each of the OAM Servers.  You can place it anywhere as long as it is accessibly by the OAM server.  I recommend the file ownership be the same as the user account that can start and stop the OAM server.

Step 3 – Validating the Master Keytab

Before you assume the master keytab file is ready, it is important to validate all the keytabs in order to verify it will work successfully before implementing it as part of the Kerberos Authentication Module. The first step is to use a Linux tool “klist”, which allows you to output the content of the master keytab. Run the following command on a Linux terminal session to see the contents of the master keytab file.  If you are not using Linux, search for the same tool that supports your platform.  I would run this same command against each master.krb5.keytab file on every OAM Server you copied it to.

klist -k -t -K -e /u01/oracle/wna/master.krb5.keytab

The output should look similar to what is shown below.   Notice it lists out each keytab line-by-line. See the HMAC/md5, this is the proper crypto.  Note that if you used the Windows 2008 R2 syntax it would output several other crypto versions of the keytabs.

Keytab name: FILE:/u01/oracle/wna/master.krb5.keytab
KVNO Timestamp         Principal
—- —————– ——————————————————–
3 12/31/69 18:00:00 HTTP/iam.acme.com@FOREST1.SPRITE.COM (ArcFour with HMAC/md5)  (0x8b2318524d2e3e2e31885afc21024cf5)
5 12/31/69 18:00:00 HTTP/iam.acme.com @FOREST2.PIXIE.COM (ArcFour with HMAC/md5)  (0x8b2318524d2e3e2e31885afc21024cf5)
3 12/31/69 18:00:00 HTTP/iam.acme.com @FOREST3.FAY.COM (ArcFour with HMAC/md5)  (0x8b2338524d2e3a2e31885afc21024cf5)

Finally each keytab needs to be validated by using the command tool kinit.  This basically forces each keytab to try and authenticate against the respective KDC server.  Since the master.krb5.keytab file will be on each OAM Server, the OAM Server must be able to reach each KDC server across the network otherwise the authentication will fail.  To validate each keytab, run the following command for each keytab using the same master.krb5.keytab file as follows.  I would do this same thing on each of the OAM Servers the master.krb5.keytab file was copied to.

kinit -V HTTP/iam.acme.com@FOREST1.SPRITE.COM /
-k -t /u01/oracle/wna/master.krb5.keytab

Authenticated to Kerberos v5

kinit -V HTTP/iam.acme.com@FOREST2.PIXIE.COM /
-k -t /u01/oracle/wna/master.krb5.keytab

Authenticated to Kerberos v5

kinit -V HTTP/iam.acme.com@FOREST3.FAY.COM /
-k -t /u01/oracle/wna/master.krb5.keytab

Authenticated to Kerberos v5

Notice that each time the above commands is run a unique service principle specific to a KDC server is used?  Each time kinit is run you should get an output that proves the Kerberos authentication was successful against the KDC.   If you get any type of error you will need to either verify that the OAM Server can reach the KDC host, make sure there is no firewall causing problems, network issues, and worse case run through the previous steps again to recreate the master.krb5.keytab file.

Realm check, the /etc/krb5.conf

The /etc/krb5.conf file contains the Kerberos configuration information including a mapping to all the KDCs and admin servers for the Kerberos realms that the OAM Server will iterate through to validate the Kerberos ticket.   The following is an example of how our straw man KDC mapping would be configured.  If additional KDCs are required, simply copy the respective sections from the [realms] and [domain_realm] as needed to add more.  Note you will need to be root to make any changes to the krb5.conf file.  I have also highlighted in bold some lines that should also be present in the krb5.conf file.  Once you create this file it can be copied to all the other OAM servers.  NOTE:  Make sure that all the letters below that are in ALL CAPS remain ALL CAPS; e.g. FOREST1.SPRITE.COM should not be forest1.sprite.com.[libdefaults]

[libdefaults]
default_realm = FOREST1.SPRITE.COM
ticket_lifetime = 600
dns_lookup_realm = false
dns_lookup_kdc = false
forwardable = yes
udp_preference_limit=1
default_tkt_enctypes = RC4-HMAC
default_tgs_enctypes = RC4-HMAC

[realms]
FOREST1.SPRITE.COM = {
kdc = forest1.sprite.com
admin_server = forest1.sprite.com
default_domain = FOREST1.SPRITE.COM
}
FOREST2.PIXIE.COM = {
kdc = forest2.pixie.com
admin_server = forest2.pixie.com
default_domain = FOREST2.PIXIE.COM
}
FOREST3.FAY.COM = {
kdc = forest3.fay.com
admin_server = forest3.fay.com
default_domain = FOREST3.FAY.COM
}

[domain_realm]
.forest1.sprite.com = FOREST1.SPRITE.COM
forest1.sprite.com = FOREST1.SPRITE.COM
.forest2.pixie.com = FOREST2.PIXIE.COM
forest2.pixie.com = FOREST2.PIXIE.COM
.forest3.fay.com = FOREST3.FAY.COM
forest3.fay.com = FOREST3.FAY.COM

This completes creating the master keytab and krb5.conf configuration for all the Kerberos details needed for WNA; the hard part is over, and now for the fun part.

Creating the Custom Kerberos Authentication Module

The authentication module does a number of things to make this all work.  It has plugins that retrieve the Kerberos ticket, it will then iterate through the keytabs to find a match that will validate the user’s service ticket, and finally based on the domain the user logged into it will provide the correct searchbase to find the user in the correct forest, so that it can identify the correct person even if there are duplicate samAccountNames.  Now let’s create the custom Kerberos authentication module.   Not one line of code is needed, this is all out-of-the-box, so don’t sweat it.

Step 1 – Create the Kerberos Authentication Module

Logged into the OAM Console as an OAM Administrator, and navigate to System Configuration > Access Manager Settings > expand Authentication Modules > select Custom Authentication module > click on the create button that has the plus sign.  Then enter a name for the module, say “wnaMultiDomainAuthnModule”, and enter a description, say “WNA Multi-domain Authentication Module”.

GeneralTab

Step 2 – Create the Steps

It is important to read this and pay close attention in this section.

During the creation of each step DO NOT click the Apply or Save button, otherwise this will cause problems when configuring the steps in the Steps Orchestration tab.  If you accidently click Apply or Save, I recommend deleting the authentication module and start from the beginning.


Select the Steps tab, then create a step by clicking the plus sign, enter the values, and click OK.

 

addStep

Repeat this process for each step in the exact order referenced in the table below.

Step Name Description Plugin Name
stepKTI KTI KerberosTokenIdentifier
stepKTA KTA KerberosTokenAuthenticator
stepUIF UIF UserIdentificationPlugin
stepUI UI UserIdentificationPlugin
stepUA UA UserAuthenticationPlugin


When completed you should have five steps that will look like the following screenshot.

StepsTab

 

Step 3 – Configure the Steps Orchestration

This section is where you order the steps created previously.

Do not click Apply until everything in this section is completed.


Select the Steps Orchestration tab > then select “stepKTI” as the Initial Step > and then configure the orchestration of the remaining steps per the table below.

Step Name On Success On Failure On Error
stepKTI stepKTA stepUI failure
stepKTA stepUIF failure failure
stepUIF success failure failure
stepUI stepUA failure failure
stepUA success failure failure


The following is a screenshot of what the Steps Orchestration panel should look like when finished.

StepOrchTab

After all the steps have been configured properly you can finally click the Apply button, and you should get a confirmation message that says, “Authentication Module created successfully”.  Now go on to Step 4 to configure the parameter values found in the Steps tab.

StepOrchConfirmTab

 

Step 4 – Fill in the Parameter Values for the Steps

We are nearly there!  Now click on the Steps tab, and for each Step Name found in the table below, enter the values for each parameter.  Make sure to click Save and then Apply after entering the values for each step to make sure the data has been saved.   Note that our straw man only has three KDC servers, but if there are more or less, simply add or subtract the values as needed in the KEY_DOMAIN_DNS2DN_MAP parameter.  For example the value should be KDC server hostname in all CAPS, then colon, and then top namespace of the KDC server.  Use a semi-colon as a delimiter to separate each KDC server, so add as many as required per your environment.  Note that you should replace the <IdentityStoreName> value with the actual name of your identity store found in the OAM Console.

Step Name Parameter Value
stepKTA KEY_KRB_CONFIG_FILE /etc/krb5.conf
KEY_PRINCIPAL HTTP/oam.server.com@forest1.sprite.com
KEY_DOMAIN_DNS2DN_MAP FOREST1.SPRITE.COM:dc=forest1,dc=sprite,dc=com; FOREST2.PIXIE.COM:dc=forest2,dc=pixie,dc=com; FOREST3.FAY.COM:dc=forest3,dc=fay,dc=com
stepUIF KEY_IDENTITY_STORE_REF <IdentityStoreName>
KEY_LDAP_FILTER (uid={KEY_USERNAME})
KEY_SEARCH_BASE_URL {KEY_USERDOMAIN}
stepUI KEY_IDENTITY_STORE_REF <IdentityStoreName>
stepUA KEY_IDENTITY_STORE_REF <IdentityStoreName>

Also don’t be concerned that the KEY_PRINCIPAL value is only the first service principal for the first domain, because OAM will iterate through the keytabs found in the master.krb5.keytab file and find the correct authentication match for the User based on what KDC they logged into.

The KEY_SEARCH_BASE_URL uses a special parameter {KEY_USERDOMAIN}.  This parameter basically tells the plugin to grab the domain the User logged in from, then uses that name space to set the searchbase when searching in OVD.  For example if the user is rey.strong@forest1.sprite.com, the plugin would grab the domain and construct (dc=forest1,dc=sprite,dc=com) as the searchbase.  This helps deal with duplicate samAccountNames across forests.

Another helpful parameter is the  KEY_LDAP_FILTER.  It is a parameter that uses a value to tell the plugin which attribute to search for the user’s samAccountName. So for example in the table above I used the value (uid={KEY_USERNAME}) to tell OAM which attribute to search with against the identity store.  I used the attribute uid because my OVD adapter is using the OAM/AD Adapter with Mapper, which maps standard inetOrgPerson attributes to Microsoft implementation of User object classes.  In this case uid would translate to sameAccountName; this is also illustrated in Part 1 of section “Searching for the Authenticated User in the Identity Store”.  So basically change the attribute to what your OVD adapter is mapping to the attribute samAccountName.

In Part 3, I will elaborate on things like using an Enterprise Directory Server instead of OVD, or including options to search for the UPN in your Identity Store if that is what you wish.  As a sneak preview I will give you a syntax value for the parameter KEY_LDAP_FILTER now; (userprincipalname={KEY_USERNAME}@{KEY_USERREALM}), more on that in Part 3.

Step 5 – Apply the new Authentication Module to an Authentication Scheme

Now that we have our required Kerberos authentication module, it needs to be applied to an authentication scheme, which can then be used in various Application Domains.

So to create an Authentication Scheme login to the OAM console as an OAM Administrator > navigate to Policy Configuration > Shared Components > Authentication Schemes > and select the KerberosScheme.  Click the duplicate button to make a copy of this scheme and fill in the values per the following table below.  Feel free to name the scheme to what ever you would like.

Parameter Value
Name WNA_AuthnScheme
Description WNA Kerberos Scheme
Authentication Level 2
Default <leave unchecked>
Challenge Method WNA
Challenge Redirect URL /oam/server/
Authentication Module wnaMultiDomainAuthnModule
Challenge Parameters <leave blank>

 

AuthnScheme

Now navigate to any of the Protected Resource Policies that require WNA and apply the new authentication scheme.

Configuring Integrated Windows Authentication

Before you can test WNA, IWA needs to be configured in each user’s browser otherwise the default NTLM will kick in, which is where you get a pop-up login prompt.  However, in some cases the browser may not be supported over a reverse proxy, so this solution is best used on Intranets.  This section contains the instructions on configuring IWA for four of the most common Internet browsers.

Internet Explorer 2+ (Windows Only)

The following steps may vary slightly for each version of IE.

  1. Open Internet Explorer.
  2. Select Tools > Internet Options.
  3. Select the Local intranet zone and click Sites > Advanced.
  4. Enter all the site hostnames that are protected including the OAM hosts where the URL goes to “http://oam.server.com:14100/oam/server” used for authentication processing.
  5. Click OK > OK.
  6. Select the Advanced tab and make sure under Security > Enable Integrated Windows Authentication option is selected.
  7. Click OK to save the changes and close the Internet Options dialog.

In step 4, if there is a common top domain for multiple hosts, for example my.sprite.com, help.sprite.com, etc. you can use an asterisks and enter “http://*.sprite.com” to cover all combinations that match that top domain.

FireFox 3+ (Windows or OSX)

The following steps may vary slightly for each version of FireFox.

  1. Open FireFox.
  2. In the address bar enter “about:config” and press enter.
  3. Click the button “I’ll be careful, I promise!”.
  4. Using the table below type in the Preference Name to find the parameter to configure and change the value according to the Value column in the table.  NOTE:  Make sure for any http(s) values you enter the all the site hostnames that are protected along with the OAM host  where the URL goes to “http://oam.server.com:14100/oam/server” used for authentication processing.
  5. Restart FireFox.
Preference Name Type Value
network.automatic-ntlm-auth.trusted-uris string http://,https://
network.negotiate-auth.allow-proxies boolean true
network.negotiate-auth.delegation-uris string http://,https://
network.negotiate-auth.gsslib string (default:empty) – Specifies alternate GSSAPI shared library
network.negotiate-auth.trusted-uris string http://,https://
network.negotiate-auth.using-native-gsslib boolean true

 

If there is a common top domain, for example my.sprite.com, help.sprite.com, etc. you can just enter “.sprite.com” to cover them all.  For multiple hosts use a comma to delimit the list of hosts.

 

Chrome 8+ (Windows or OSX)

Follow the steps in the section above for IE, and Google Chrome will automatically use the Internet Options.  No special configuration is needed beyond the computer being a domain member.

Safari 4+ (OSX Only)

Safari is enabled for IWA automatically on OSX.  No special configuration is needed beyond the OSX computer being a domain member.

Troubleshooting

Adding Kerberos Debugging to the OAM Server

The following steps will provide Kerberos debugging output from the OAM Server logs.  This is useful to review the Kerberos output and make sure there are no issues with OAM trying to map the User Principal Name to the correct user in the Domain that user is a member of.

  1. Login as the owner of the OAM11g install.
  2. Go to the <FMW_HOME>/user_projects/domains/<DOMAIN_HOME>/bin directory.
  3. Make a backup of the setDomainEnv.sh file.
  4. Using a text editor open the setDomainEnv.sh file.
  5. Search for the first line with EXTRA_JAVA_PROPERTIES
  6. Add the following two lines (Note the first line should not wrap in the file).
    EXTRA_JAVA_PROPERTIES=”-Dsun.security.krb5.debug=true -Dsun.security.spnego.debug=true ${EXTRA_JAVA_PROPERTIES}”
    export EXTRA_JAVA_PROPERTIES
  7. Save the file and restart both the Admin Server and OAM Server.
  8. You should now be able to tail the OAM Server logs and see Kerberos debug output.  The following is an example.

Entered Krb5Context.acceptSecContext with state=STATE_NEW
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
Using builtin default etypes for permitted_enctypes
default etypes for permitted_enctypes: 3 1 23 16 17.
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
object 0: 1359604847000/156
object 1: 1359604776000/152
object 2: 1359604739000/151
object 0: 1359604847000/156
object 1: 1359604776000/152
object 2: 1359604739000/151
replay cache found.
>>> KrbApReq: authenticate succeed.
Krb5Context setting peerSeqNumber to: 227772863
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
Krb5Context setting mySeqNumber to: 349851240
SPNEGO Negotiated Mechanism = 1.2.840.113554.1.2.2 Kerberos V5
SpNegoContext.acceptSecContext: mechanism wanted = 1.2.840.113554.1.2.2
SpNegoContext.acceptSecContext: negotiated result = ACCEPT_COMPLETE
SpNegoContext.acceptSecContext: sending token of type = SPNEGO NegTokenTarg
SpNegoToken NegTokenTarg: sending additional token for MS Interop
SpNegoContext.acceptSecContext: sending token = a1 81 eb 30 81 e8 a0 03 0a 01 00 a1 0b 06 09 2a 86 48 86 f7 12 01 02 02 a2 69 04 67 60 65 06 09 2a 86 48 86 f7 12 01 02 02 02 00 6f 56 30 54 a0 03 02 01 05 a1 03 02 01 0f a2 48 30 46 a0 03 02 01 17 a2 3f 04 3d e9 4b 77 88 6c ac f7 6a c6 8e 52 e0 16 66 51 fa 7b 59 da 15 ff e0 a7 ce b7 39 0f 57 3b 80 31 15 fa ed 92 b2 0c 03 2c dd 3a 54 42 52 40 ba b2 bd df b7 f5 90 af 35 aa 6b 1e ac b9 4d 04 a3 69 04 67 60 65 06 09 2a 86 48 86 f7 12 01 02 02 02 00 6f 56 30 54 a0 03 02 01 05 a1 03 02 01 0f a2 48 30 46 a0 03 02 01 17

 

Turning on OAM Server debug mode to TRACE

It is very helpful to turn the OAM server debug logs to TRACE in order to get more verbose information.  This could also be done in Enterprise Manager, but if you would rather do this from a command line, these are the steps to follow.  Some things in this mode which will provide real help are showing things like the Principal that logged in, the User Domain which shows the namespace to search, the authentication scheme used and some details about it, and other things.

  1. Make sure the Weblogic Admin Server is running.
  2. Login as the administrator that starts and stops the OAM Managed server.
  3. Change to the directory <FMW_HOME>/common/bin
  4. Run the command.
    ./wlst.sh
  5. Connect to the Admin Server by running the following command.
    connect(‘weblogic’,'<weblogic_password>’,’t3://localhost:7001′);
  6. Run this command to list the logging modules
    listLoggers(pattern=’oracle.oam.*’,target=’oam_server1′)
  7. Run the following command to set the OAM server in trace mode.
    setLogLevel(logger=’oracle.oam’,level=’TRACE:32′,persist=’0′,target=’oak_server1′);
  8. To revert back to normal run the following command.
    setLogLevel(logger=’oracle.oam’,level=’NOTIFICATION:1’, persist=’1’, target=’oam_server1’)

Verifying LDAP searches in OVD

It is helpful to tail the diagnostic logs in OVD to determine if the correct search is being made.  This should be displayed by default without needing to make any changes.  Simply do the following.

  1. Login as the administrator that starts and stops OVD.
  2. Change to the directory <FMW_HOME>/ovd1/diagnostics/logs/OVD/ovd1
  3. Either use a text editor or tail to view the diagnostic.log log file.

You should be able to see an example search as shown below.

[2013-02-06T15:38:59.192-06:00] [octetstring] [NOTIFICATION] [] [com.octetstring.vde.chain.plugins.DumpTransactions.DumpTransactions] [tid: 27] [ecid: 4aaf7073ad441920:-49d5bd7a:13cb14e92f1:-8000-0000000000000232,0:2] !SEARCH Operation: (Transaction#Adapter_Forest4.Dump Before.30)[[
BindDN: cn=orcladmin
Base:   dc=FOREST4,dc=MELANDER,dc=US
Scope:  2
Filter: (&(uid=tim.melander)(objectclass=inetorgperson))
TypesOnly:      FALSE
Attrs:  [uid, mail, cn, description, orclguid, objectclass, displayname, uid]!
]]

 

Testing the Solution

Testing the solution is pretty straightforward.

  1. Login to a desktop that is a member of one of the Active Directory domains.
  2. Open an Internet browser and browse to an OAM protected application.
  3. If working properly, you should not be challenged to login; it should immediately go in.

Summary

I hope the steps I provided are useful to anyone wanting to implement WNA.  It is without a doubt a complicated integration, but my goal was to help make this a little less painful.  Next in the final “Part 3: OAM11g WNA Identity Store Considerations and Configurations“, I will cover OVD and special configurations that will make sure the domain name space will work with the Kerberos Authentication Module you created.

Part 3: OAM11g WNA Identity Store Considerations and Configurations

$
0
0

Introduction

This post is part of a larger series on Oracle Access Manager 11g called Oracle Access Manager Academy. An index to the entire series with links to each of the separate posts is available.

This is the final post of a three part series.  In “Part 1: Under the Covers of OAM11g WNA integration with Multiple AD Forests“, I covered the flow of how WNA works and what was going on behind the scenes, and in “Part 2: How to Configure OAM11g WNA for Multiple AD Forests“, I went into detail on how to configure WNA.  In this final post I am going to go over what I think would be two of the most common scenarios that the OAM11g Identity Store would be used for WNA, and how it impacts the Kerberos authentication module configurations.

Main Article

What’s spinning under the Identity Store covers?

If you were to turn on the OAM11g Server logs to trace level, and tail the log as a User would authenticate using IWA, you would find a point in the log where the OAM Kerberos authentication module sets the LDAP filter configured in the UserIdentificationPlugin as shown in the example log below.  This basically shows exactly what we set the plugin parameter to in the stepUIF, which was defined in the authentication module.

[2013-02-16T21:03:29.944-06:00] [oam_server1] [TRACE] [] [oracle.oam.plugin] [tid: [ACTIVE].ExecuteThread: ‘1’ for queue: ‘weblogic.kernel.Default (self-tuning)’] [userId: <anonymous>] [ecid: 4aaf7073ad441920:-3df584f4:13ce5e02606:-8000-00000000000002c4,0] [SRC_CLASS: UserIdentificationPlugIn] [APP: oam_server] [SRC_METHOD: process] Un-processed LDAP Filter is (uid={KEY_USERNAME })

Then as we continue to tail the log you would see a couple methods populate the actual search base and LDAP filter.  The LDAP filter includes a value {0}, which is the first array that gets populated with the user’s principal name or userPrincipalName value depending on how you configure the parameter; more on that later.

[2013-02-16T21:03:29.949-06:00] [oam_server1] [TRACE] [] [oracle.oam.user.identity.provider] [tid: [ACTIVE].ExecuteThread: ‘1’ for queue: ‘weblogic.kernel.Default (self-tuning)’] [userId: <anonymous>] [ecid: 4aaf7073ad441920:-3df584f4:13ce5e02606:-8000-00000000000002c4,0] [SRC_CLASS: oracle.security.am.common.jndi.ldap.proxy.DirContextProxy] [APP: oam_server] [SRC_METHOD: invoke] Arg = forest1,dc=example,dc=com
[2013-02-16T21:03:29.949-06:00] [oam_server1] [TRACE] [] [oracle.oam.user.identity.provider] [tid: [ACTIVE].ExecuteThread: ‘1’ for queue: ‘weblogic.kernel.Default (self-tuning)’] [userId: <anonymous>] [ecid: 4aaf7073ad441920:-3df584f4:13ce5e02606:-8000-00000000000002c4,0] [SRC_CLASS: oracle.security.am.common.jndi.ldap.proxy.DirContextProxy] [APP: oam_server] [SRC_METHOD: invoke] Arg = (&(uid={0})(objectclass=inetorgperson))

Finally following the previous authentication events, if you were to also tail the debug log of the Identity Store of choice, we would see the actual search.  For example the following is an OVD diagnostic log, you can see the final LDAP search parameters that have been translated into something the LDAP server would understand.  Highlighted in bold you can see the same searchbase and search filter, which would then retrieve the user entry and everything would be golden.

[2013-02-16T21:35:51.439-06:00] [octetstring] [NOTIFICATION] [] [com.octetstring.vde.chain.plugins.DumpTransactions.DumpTransactions] [tid: 39] [ecid: 4aaf7073ad441920:-3df584f4:13ce5e02606:-8000-000000000000031e,0:2] !SEARCH Operation: (Transaction#Adapter_Forest3.Dump After.11)[[
BindDN: cn=orcladmin
Base:   dc=forest1,dc=example,dc=com
Scope:  2
Filter: (&(samaccountname=tim.melander)(objectclass=user))
TypesOnly:      FALSE
Attrs:  [mail, cn, description, orclguid, objectclass, displayname, uid, samaccountname]!
]]

The reason I went over all this is to build an understanding of what is happening during the WNA authentication.  Now we can come up with a couple of what I think are the most common scenarios to map the Identity Store to the backend user data, whether that be OVD or another LDAP store, and map the correct configurations needed for the OAM11g custom Kerberos authentication module UserIdentificationPlugin.

OVD or Not OVD, that is the Question?

Believe it or not, you can either use OVD or another LDAP store for WNA; really.  Before we get into it, I want to give a quick primer on OVD for those that have not heard of it.  OVD is an acronym that stands for Oracle Virtual Directory, and the title literally means what it says.  Basically in a nutshell OVD is an Oracle Middleware product that uses adapters, among many other things, to aggregate backend data into a unified front end LDAP store.   If interested, you can find out more details about OVD at the Oracle Technology Network under Identity Management titled Oracle Virtual Directory.

In Part 1 and Part 2 of this series you may have noticed I used OVD because I wanted to aggregate three Active Directory forests into a single unified LDAP store, which was then used by the OAM11g custom Kerberos authentication module.  The reason for this is that I can only define a single Identity Store because of how the steps in the authentication module plugins have to be orchestrated.  You can see the dilemma, if I did not have OVD in this case I would be stuck going against a single Active Directory domain.

Another reason I used OVD, was that I took advantage of a plugin parameter I mentioned in Part 2 named {KEY_USERDOMAIN}, which was used in the UserIdentificationPlugin to grab the User’s logged in domain to dynamically set the User’s specific searchbase namespace in order to deal with duplicate samAccountNames across multiple forests.  If you are savvy to OAM11g custom authentication modules you will probably tell me, wait a minute, you could chain several steps with separate UserIdentificationPlugins where each step could be defined with unique Identity Stores.  Sorry, not really, in this case the way the Kerberos authentication module works, things do not work as you would expect.  I know, because I tried it.

Now let’s talk about alternate Identity Stores other than OVD.  Say your Enterprise provisions a subset of data from all your Active Directory domains into a single external Non-Microsoft Enterprise Directory Server store.  OAM11g WNA could actually take advantage of this LDAP store and use it to search for the Users instead of using OVD.  Why, because after the OAM11g custom Kerberos authentication module gets through validating the Kerberos ticket, validating the service principal against the Microsoft KDC server, and extracts the data needed to build the searchbase and search filter I mentioned previously, all that is remaining is to look up the User in an LDAP store.  As long as all the Users happen to be in a single Enterprise Directory Server store, that LDAP store would qualify as an Identity Store that would work for this WNA solution.  Pretty cool right?

So if you know that all Active Directory Users are provisioned to a single Enterprise Directory Servers store, then good for you, this is the Identity Store you may want to use in OAM11g.  However if this is not true, then OVD11g is the way to go.  I know each client has very unique needs because of a list of reasons, so I hope one of these two options meet the majority of the people out there wanting to use this solution.  So enough fluff, let’s get into the weeds!

Using OVD as the Identity Store

This article will not get into the details of how to configure OVD in order to map all your Active Directory forests into a single LDAP store, but I do want to cover a few considerations on correctly designing the DIT (Directory Information Tree).  I want to leverage the straw man I used in Part 2 and describe it in the following DIT diagram.   At the top you have the rootDSE context, and under that you have three sub branches, each sub branch is configured with an adapter that references a forest.  What is critical is the structure of the DIT.

 

LDAP_DIT

In the above example let’s say the user’s fully qualified user principal name is alfred.carson@forest2.example.com.   We already mentioned that when the user logs in via WNA, the OAM authentication module uses the @forest2.example.com to dynamically set the searchbase using the {KEY_USERDOMAIN} parameter value.  So in this case the searchbase would be set to dc=forest2,dc=example,dc=com.  As long as this searchbase matches up to our DIT, OAM will easily find the user, and in fact find the unique user across multiple forests even if there is another alfred.carson in say Forest3, because their location would be under the dc=forest3,dc=example,dc=com, a completely different namespace.  As you can see, defining the DIT becomes important to making this all work.  So the key to remember is that your OVD DIT must be designed in a way that maps back to how OAM WNA would set the searchbase used from the User’s domain.

OVD Adapter Mapping Considerations and OAM11g Plugin Configurations

Using OVD involves one or many adapters.  There are several types of adapters and each one will either transpose and map attributes or do a straight pass through.  For example in Part 2, in my configuration, I used the OAM/AD Adapter with Mapper, which maps inetOrgPerson class attributes to Active Directory; e.g. uid would translate to samAccountName.  However if I had used the Active_Directory adapter, OVD would present samAccountName on the front end and pass it straight through to Active Directory as samAccountName; nothing would even change.  Therefore, the type of adapter you choose will greatly change the values used for the KEY_LDAP_FILTER parameter.  The following table shows just a couple examples, but you should at least get the idea.  If your requirement is different, then modify the values as needed.

OVD Adapter
OAM11g stepUIF Plugin Parameter Recommended Value
OAM/AD  Adapter with Mapper KEY_LDAP_FILTER (uid={KEY_USERNAME})
Active_Directory KEY_LDAP_FILTER (samaccountname={KEY_USERNAME})

 

Using an Enterprise Directory as the Identity Store

As I mentioned earlier if all of the Active Directory users are provisioned into a common Non-Microsoft Enterprise Directory Server store, then using an Enterprise Directory Store may work.   However, not so fast, there are three requirements for this to work.

 

  1. OAM11g must support your version of the Enterprise Directory Server as an Identity Store; see the OAM11g certification matrix to verify.
  2. The value OAM11g searches needs to be either the samAccountName or the userPrincipalName because these are the values the Kerberos authentication module extracts from the User’s Kerberos ticket.
  3. Finally the value that is searched in the Enterprise Directory Server store must be unique across the DIT, or at least the point at which you define the starting search base namespace otherwise the authentication would fail if there were a duplicate username.

 

DS_DIT

Requirement 2 is important, so let me elaborate.  The OAM11g custom Kerberos authentication module extracts the principal from the Kerberos ticket; I point this out with example logs in Part 1.  Let’s take for example Alfred Carson logs into the FOREST2 domain with the username alfred.carson; his userPrincipalName would look like alfred.carson@forest2.example.com.   The following table explains some possible options you could use for the stepUIF plugin parameter explained in Part 2.  As a reminder the stepUIF is one of the module plugins called UserIdentificationPlugin, which has three optional parameters, 1) KEY_LDAP_FILTER, 2) KEY_SEARCH_BASE_URL, and 3) KEY_IDENTITY_STORE_REF.  The following table relates to the values that could be used for the KEY_LDAP_FILTER parameter.

KEY_LDAP_FILTER Parameter Value Value Extracted by Plugin used for Search
{KEY_USERNAME} alfred.carson
{KEY_USERREALM} forest2.example.com
{KEY_USERNAME}@{KEY_USERREALM} alfred.carson@forest2.example.com

So extrapolating from the parameters shown in the table above, let’s say one of the values that is provisioned from all the Active Directory servers is the userPrincipalNames, which is then populated for each entry in your Enterprise Directory Store.  Then say the value is stored in the attribute “userprincipalname”.  You could use then use the following KEY_LDAP_FILTER parameter value as follows.



(userprincipalname={KEY_USERNAME}@{KEY_USERREALM})

If the same attribute in your Enterprise Directory Store is “uid” instead, then modify the plugin parameter as follows.



(uid={KEY_USERNAME}@{KEY_USERREALM})

So if we go with the above parameter value, then OAM11g would pass the search to the LDAP Identity Store as follows.



(&(uid=alfred.carson@FOREST2.EXAMPLE.COM)(objectclass=user))

As you can see making some tweaks to the parameter value could meet the needs of your Identity Store.  However before we get to excited, we still need to set the search base.

Defining the Search Base Statically or Dynamically

If you remember in Part 2 we had a plugin parameter in stepUIF called KEY_SEARCH_BASE_URL, and we used a value {KEY_USERDOMAIN}.  If we stayed with this parameter value it would use the User’s domain realm, forest2.example.com, and dynamically set the search base to dc=forest2,dc=example,dc=com.  When I talk about using OVD as the Identity Store, this would be a good thing.  However, what if we did not want it to search there because we are using our Enterprise Directory Server store instead?  Then leave the KEY_SEARCH_BASE_URL parameter value blank, and define the search base for the Users in the OAM11g Identity Store that is used for the custom Kerberos Authentication Module; remember the KEY_IDENTITY_STORE_REF parameter?  For example going with the Enterprise Directory Server DIT shown in the previous diagram, you could set the starting search base to “ou=employees,ou=internal,dc=example,dc=com”, and OAM11g would start the search there for the user.

Below is a table that shows the possible KEY_SEARCH_BASE_URL  parameter values for the UserIdentificationPlugin.  We can use the User alfred.carson@forest2.example.com as an example and see what happens.

UserIdentificationPlugin Parameter Parameter Value Plugin Result
KEY_SEARCH_BASE_URL {KEY_USERDOMAIN} dc=forest2,dc=example,dc=com
KEY_SEARCH_BASE_URL <leave this blank> <Uses the assigned Identity Store searchbase>

Summary

I have covered this topic pretty throughly, at least I hope to a point it will be useful for anyone.  My goal was to show the power of the custom Kerberos authentication module, and how flexible this solution can be by simply making some modifications to meet many needs.  I also hope both options for Identity Stores presented in this last part meet the majority of what people would use in a real world deployment.  I wish the best for anyone trying this solution, and I hope it helps with great success in your OAM11g WNA implementation.


Part 1: How To Load Test OAM11g using Apache JMeter

$
0
0

Introduction

Exciting, it is Go Live day, the system goes online, everything seems ok for a while, and then Kerplunk! Thousands of things could have happened and everyone scrambles to figure it out. What went wrong? My first question is, “Was a proper load test completed?” Yes, Load Test. Functionally the software may have worked, but under a heavy load issues can start bubbling up. If you have been there like I have many times you know what I am talking about. Situations like this could be avoided?

This is where this article comes in. I have learned the hard way that load testing can provide a lot of great feedback to determine issues whether it be the software, the design, the deployment, or the architecture. The bottom line is if you do not have fancy software like HP Load Runner, the poor mans version, Apache JMeter, can come to the rescue. JMeter is FREE, well documented (As much as any other software at least), and there are tons of blogs and articles on JMeter since it has been around for quite a while. JMeter can also do much more beyond HTTP type of load testing. I would love to cover even more about JMeter, but unfortunately I have to focus this article to a basic load test that works with OAM11g. Minimally, I hope this article at least gets you started and even excited to learn more about this great tool.

Main Article

About Apache JMeter

Apache JMeter is a free open source desktop application written in pure Java.  JMeter is used as a load testing tool to measure performance.  In addition to applying a load to a system, JMeter provides Listeners that monitor the load details so that the feedback from the listeners can be used to tune a system; e.g. OHS web servers, OAM Servers, LDAP servers, etc.

Typically HP Load Runner is the industrial strength load testing tool used by larger enterprise clients, but often I see things like the team that uses it either does not have the time nor the resources, or maybe the project did not have such a tool to complete any load testing.   To get started, first  download the latest version of Apache JMeter and get it up and running.

Learning by Example

I have written this article so that you will use an example I have provided in a zip file OAM11g_LoadTest.zip [CLICK TO DOWNLOAD], and wrote the article in a format that explains all the important elements of the JMeter plan to make this all work for OAM11g.  I may not cover every detail about the elements because there are so many things, so please explore the Apache JMEter User Manual http://jmeter.apache.org/usermanual/ and look up how some of these elements work.  The Apache JMeter site has some pretty good documentation and if you google there are also a lot of great articles that help supplement the User Manual.

The JMeter OAM11g Load Test Example

If you have not already, download the example OAM11g JMeter Load Test plan I have provided and lets get started.  Note that included in the sample JMeter plan is a supporting comma separated file (CSV) file that holds two columns, username and password, more on this later.  Once you open up the plan the screen should look like the following graphic.

JMeter_LoadTest_screenshot

The Elements of the Plan

As promised this section covers all the important parts of the JMeter Load Test plan I provided.   Note that the most critical of the elements to make this work with the OAM11g login are the elements under the Portal Request branch using either the Regular Expression Extractor or XPath Extractor; more on these later.  So without further ado…

The Thread Group

The Thread Group provides a way to configure the number of threads and Users that are load tested against your IDM and Application system.  You can tweak how fast the total number of Users makes requests by changing the value of the Ram-Up Period.  As an example if you have 1500 Users, then set the Ramp-Up Period to 150 seconds, that starts the initial requests at 5 User logins per second (1500 Number of Threads or Users / 150 Ramp-Up Period in seconds = 5).   After 150 seconds all 1500 Users will have opened up requests that were created in the load test plan.  The Number of Threads are the total number of Users the test will run though, but if you set the Loop Count to 2 the load will then be 2 times the Number of Threads though not all at once hence the term loop.   Basically it just runs through the same test twice or what ever you set the Loop Count for.  What you configure the Thread Group for is solely based on the type of metrics you are trying to simulate.  It is best to start small and work up to larger volumes.  JMeter can consume a lot of member if there are hundreds or even thousands of requests.

Common Configuration Elements

The following are what I call common configuration elements.  They are located at the top of the load test plan because they provide common settings or functionality used across all the load test elements.

HTTP Cookie Manager

This configuration helps store cookies sent by OAM so that when JMeter gets the necessary OAMAuthnCookie or ObSSOCookie depending on whether it is a 11g or 10g Webgate respectively, all the necessary cookies will be stored in JMeter so that SSO can be accomplished.  Note in the plan I provided the option Clear cookies each iteration has been checked so that each new request simulates a User closing their browser thereby requiring to get new cookies on a subsequent new thread.

HTTP Cache Manager

This configuration will cache resource elements like URLs in JMeter’s memory so that it is not always reaching out for the same URL over and over.  The purpose of this is to simulate how many browsers improve performance by caching requests.  Note I have also checked Clear cache each iteration so that cache is not reused for each new thread request.

Configurable Variables (User Defined Variables)

This configuration is used to simplify making hostname and port changes across all the HTTP Request samplers that use a host and port.  In my plan I  have a hostname for the SSO Login server and a hostname for a Portal Server, so you may need to change this including the ports to reflect your test environment.   If your environment hostname for the application and login are the same, then modify the test plan accordingly.  In any case, instead of tediously going through all the HTTP Request elements throughout the plan and updating the Server Name or IP and Port Number values individually one by one, you can easily make the change in one place.  The reason this works is because for all the HTTP Request elements those values are populated with a dynamic variable like ${sso_host} and ${app_host}, then for example the Host Variables table the variable Name “app_host” gets replaced by the actual Value you included in the configuration element.  This is a real time saver.

User Data (CSV Data Set Config)

This configuration provides a way to include an external flat file that will hold things like Usernames, Passwords, etc.  In my plan I only include the Username.  The file name is entered in the Filename field; my example uses the included Users.csv file.  The User.csv file I provided has one column, username, but you could add other columns like password, employeenumber, etc.  In my plan I know that all the passwords for each User is the same,  so I added the password as a variable in the Configuration Variables element by adding the variable Name “password” and in the Value field the actual password.  Then I added the ${password} variable in the Login Submit element.  Feel free to experiment and learn.

The Simple Controller Elements

Within the Logical Controller in JMeter is an option called the Simple Controller, which provides a way to organize all types of elements like HTTP Requests, Regular Expression Extractors, XPath Extracters, etc.  The Simple Controller really does nothing more than provide for a way to logically group elements of the load test plan.  For example I used three Simple Controllers and named them Login, AuthZ, and Logout to represent the three functional actions of my Load Test plan.   As you build the complexity of the plan you will appreciate breaking the functionality of the test plan into logical groups using this technique.   Feel free to expand on the idea and add more Simple Controllers if you feel it is necessary.  The following gives more details on each group I created to help better understand what I am trying to accomplish.

Login (Simple Controller)

The Login Simple Controller is meant for all actions that have to do with a User logging into OAM.  The following are explanations of the elements.

Portal Request (HTTP Request)

Modify the Path parameter URI to point to a protected HTTP resource.   The protected resource should redirect JMeter to the initial login page.

Extract QueryString from request_id (Regular Expression Extractor)

This comes from one of the Pre-Processors elements.  If you are using a custom form login, the Regular Expression Extractor is used to extract the OAM 11g querystring parameter called request_id; this was not required in OAM10g so if you happen to be load testing OAM10g you can disable this element.  The Regular Expression Extractor basically looks for the existence of the a HTTP querystring parameter named request_id and if found extracts the value.  The value changes on every request, which is why it needs to be extracted dynamically on every login attempt.  The request_id is a critical value required when posting to a custom form login in order to authenticate, without it the login would fail.  To learn more about this, Brian Eidelman wrote a great blog on this very topic, “External Custom Login Forms with Oracle Access Manager 11g”.

Extract Form Input from request_id (XPath Extractor)

Similar to the “Extract QueryString from request_id”, this element is used when you are using the OAM11g Out-Of-The-Box (OOTB) form login.  When the OAM11g OOTB form login is used the request_id does not present itself as a querystring variable, instead it shows up as a hidden form input field called “request_id”.  In order to get this value the XPath Extracter is used with a XPath query “//input[@name='request_id']/@value”, which grabs the value.  Then the Reference Name field is named “request_id” and used as a dynamic parameter ${request_id} in the Login Submit element to post the value.  By default I have disabled this element, but if you are using the OOTB form login, enable this element and disable the Extract QueryString from request_id element.

Extract Form Input from OAM_REQ (XPath Extractor)

Similar to the “Extract Form Input from request_id” element, this element is enabled when the serverRequestCacheType parameter in the oam-config.xml file is set to FORM.  If you are not sure what your parameter is set to look in $ORACLE_HOME/$FMW_HOME/ user_projects/domains/oam_domain/config/fmwconfig to find the oam-config.xml and search for serverRequestCacheType.  There are three optional modes, BASIC, COOKIE, or FORM.  When it is set to FORM, the request_id is sent as OAM_REQ as a hidden form input field.  So in this case the XPath query is set to “//input[@name='OAM_REQ']/@value”.  However the Reference Name is still request_id in order to keep the dynamic parameter the same to keep everything as consistent and simple as possible.

Login Submit (HTTP Request)

An important configuration for this element is the path, the value needs to be /oam/server/auth_cred_submit so that JMeter will submit all the credential parameters to the OAM11g login just like a person submitting their credentials in a login form.  Note that in the Parameters table all the additional elements required are included in the sample plan like username, password, and request_id.  Note that  displayLangSelection, and Languages are only added if required to change the local language.

Authz (Throughput Controller)

This is another type of controller that can control the number of HTTP authorization requests that happen after login.  After the Login actions happen from the Login (Simple Controller), JMeter has the proper OAM SSO cookies that are temporarily stored in the HTTP Cookie Manager.  So in this logical controller, I make all my URL requests simulating authorizations.  In the example I provided there are only three sample HTTP Requests and each Path URI is simply “/”, so be sure to modify each HTTP Request per your load test setup and in fact do not be shy, add more and even elaborate on other options to simulate a User clicking on various pages in your application.  My sample includes the following.  Note that in each of the following elements is a Server Name or IP field that has the dynamic value ${app_host} that relates to the Configurable Variables element where you would have the real application hostname.  Feel free to experiment.

      • Portal Home (HTTP Request)
      • My Account (HTTP Request)
      • Info Page (HTTP Request)

Logout (Simple Controller)

This is another Simple Controller that contains actions required to logout and also verifies the logout was successful.  Since a typical User will complete a logout, it is important to include this logical controller as part of the load test life cycle.  Not that each HTTP Request element uses the Method GET.

Logout Request (HTTP Request)

Note that the Path parameter needs to point minimally to the /oam/server/logout URI, but in my example I have used the URI value /oam/server/logout?end_url=/logout.html.  The end_url is a special parameter that tells OAM to return the User to a custom landing page after the logout.  In my setup I have a custom logout.html page on the same host as the custom login.html page.  For your setup feel free to remove this extra parameter or modify it as necessary per your setup.  It is important to check your OAM11g setup to know how it has been configured to properly logout of the application from which you can then modify the JMeter plan as needed.

Logout Landing (HTTP Request)

This element requests the final logout page URL.   Note that underneath this element is a Response Assertion, which determines if the logout was successful, more on that below.

Validate Logout (Response Assertion)

If you look at this element, it has the following configurations selected, Main Sample Only, Document (text), Contains, and Patterns to Test where the pattern match is “You are now logged out” based on what is displayed in my logout.html page.  However, in your case you may want to look for something else that is seen in the final logout page.   I would use an HTTP trace tool like Fiddler, or FireFox HTTPFox, or any other HTTP trace tool to determine what is required.  Basically the Response Assertion can look at content seen in a page and if found it returns a TRUE, which means the logout was successful.  If FALSE, it will show up as red in the View Results Tree and provide a negative response.  Take a look at the options in the Response Assertion; it could be text in the HTML page, a URL, or other.  Please modify the Response Assertion element per your environment logout page action so that it can determine if the logout was successful.  If you want, you could also disable this element.

Listeners

Listeners are elements that provide a way to monitor events during a load test.  In the load test sample I provided I just used two Listeners, but feel free to experiment with other Listeners to learn more.

View Results Tree

This element is very useful because it records the requests and responses from each Sampler event during a load test and displays exactly what the client would see in an Internet browser.

Aggregate Report

This element records a nice comprehensive table of responses like errors, throughput, median, etc. seen in each thread request.  As you review the report you can look at each column of each row to help identify bottlenecks or successes.  There is even an option to save the results to a file so that each load test can have a separate report that can be compared to determine positive and negative improvements.

Test the Load Script

Now that you have tweaked the example JMeter load test plan per your environment it is time to test.

Before running the test I want to point out some words of caution. JMeter will consume as much memory as it needs without concern of how much memory in the computer it is running on. Therefore, if you enter a high value in the Number of Threads, your desktop can potentially come to a grinding halt or worse freeze. If you want to send a high volume of requests to the system in the case you need to simulate thousands of requests, it is a good idea run several JMeter instances on more than one desktop and simultaneously run them all at the same time. Since JMeter is written in pure Java, you can run it on any platform that supports the Java JRE 1.6x or higher.

It is a good idea to run a light load from a single JMeter instance to test the plan.  Before kicking off the load test, select the View Results Tree, then click the green right arrow from the top menu to start the load test; see the illustration below.  You should now start to see requests populate the results tree.  Once the test is completed review the results in the Aggregate Report.  If you want to run the test again use the double broom button to clear everything.

As a refresher, I had mentioned early on that in the Thread Group element you can change various parameters to send all types of loads.  Unfortunately give you any general load amounts or specific settings, but just so I don’t let you down and hopefully make this article as complete as I can make it, I am including the next section that touches a bit some general guidelines.

JMeter_StartTest_screenshot

I had mentioned early on that in the Thread Group element you could change various parameters to send various types of loads.  In Part 2 I will include more details on how this can be used with multiple Thread Groups along with making the test more random.

 

Beyond Apache JMeter

I saved the boring stuff for last, so don’t say I didn’t do you any favors.  I wanted to take a step back now and talk a little bit about load testing tips in general.  The following are things I am aware of based on years of experience in regard to good load testing.  Don’t take these as golden rules, just use them as good guidelines.

1. Use Realistic Metrics

Load tests should generally be based on real traffic to provide pretty good estimations on what to expect when you go live.   Do not guess on the metrics to load test; that is simply a bad idea and where customers usually get into trouble.  Try to simulate real load pattern seen in production.  For example average page views, session duration, page size, average loads, peak loads, and basically data to help simulate what an average user would do after logging in and completing some actions.  The metrics should also determine how many concurrent logins are seen on average during peak periods.  In fact average loads in general are good to know.  One reason is that average loads are important during longevity load tests because often a system may hold up gracefully during a peak load, but act differently over longer periods of time even at average loads.  Also be realistic, for example if there are peak loads of say 5000 unique concurrent logins an hour, don’t just load test with 100 unique concurrent logins per hour even if you push the requests at a higher rate because the software caching can skew the expected results and when you go to production the difference between 100 concurrent logins per minute versus 5000 concurrent logins per hour can make a difference.   If you don’t load test using real life loads and patterns, the result is you may end up being unprepared when going live and parts of the system start toppling over because someone tried to rush and not do their homework or maybe they were lazy.  Do yourself a favor and do the homework, it will make a difference between working toward success or gambling on having the stress of dealing with firefighting.

2. Stress Test all Actions; Login, Authorization, and Logout

Stress Test all Actions; Login, Authorization, and Logout
Good load testing should simulate the full life cycle of a User using the system. For example login, authorization actions, and logout patterns. I have seen to many times where authentication patterns are only stress tested, and think that is good enough to simulate a real production system test. Based from my experience, as a general rule authorization requests account for approximately 75% percent of the load. In fact I have seen clients that have discovered authorization requests can go even higher at more than 80% percent of the load and that load can even be more compounded by things like Policy Responses in the OAM Policies that send lots of header, cookie, etc. All that additional data adds to the load of the system. Therefore load tests should be made as close to real life as possible by iterating all the basic actions of a life-cycle, logging in, accessing pages, entering data if possible, registering, and logging out. The closer to realistic load patterns that can be designed into the load test, the more chances issues will bubble up during your testing, which gives you time to correct for any problems before going live.

3. Monitor All Components

Load testing is just a part of the testing phase so don’t think that just sending a big load against your system and seeing it hums right along with flying colors it is all done.  Taking the time to monitor the components from end-to-end is very important especially in cases where you identify bottle necks that help identify defects or even the need to do some tuning.  There are always cases where certain tiers may not be scaled enough or little problems bubble up and the only way to determine that is to monitor as much as possible.  If problems arise, the solution could be as simple as tuning, and in some cases scaling up or even out.  In a worse case scenario maybe the design needs to be reworked.  The good news is that proper load testing identifies as much as possible before going live.

4. Document the Results

This may seem obvious, but documentation seems to be one of those items no one wants to do.  It is a good idea to create some type of document with tables to record necessary results in a historical manner.  For example using Excel to record results and changes.   This provides a way to present of all the negative and positive results to determine progress and if the system is ready for prime time.   The document should also have ways to record potential issues, bugs, etc. so that those things can be addressed and the load tests can be run again once the defects have been corrected.   Once all the issues are worked out you can at least show that due diligence has been done before going live.  As a benefit if issues do bubble up in production, you have a tool that can help potentially reproduce the problems in a non-production environment so that corrections can be tested versus trying to do it in a live system.

5. How Long will Load Testing Take?

This is the 10,000 dollar question.  It is also a tricky question to answer because the exercise of setting up the load test and executing can some what be estimated, but where the timeline starts dragging out is when problems bubble up during a load test.  It is difficult to determine in the future what problems will arise and even more challenging how long it will take to correct for the defect especially if it turns out to be a bug.   If possible, add enough buffer time to provide some comfort to account for future issues.  Good luck with that.  If buffer time is added in, and you are lucky enough to have very few issues (A big dream of mine.), then that time not used for testing can be gained back and you will look like a Rock Star.  My advise is to over estimate and over deliver than to under estimate and under deliver.  I realize this is easier said than done.

Summary

In summary JMeter is a really great load testing tool for OAM11g.  It can not only provide a way to simulate a realistic load test, but also a way to stress the system while making tweaks to tuning parameters to determine positive and negative results.  JMeter can also be used for other things beyond OAM like the LDAP, Web Service Calls, JDBC, JMS, etc.  Most importantly it is a load testing tool when used properly, will provide a way to identify issues that bubble up during the testing and hopefully fix those issues before going live.   I hope the sample plan provides a great start and you take the time to go beyond what I have provided.  Happy testing and good luck!

A first look at POST data preservation in OAM 11g R2 PS1

$
0
0

Introduction

In this post, we have a quick look at POST data preservation, a new feature introduced in the 11g R2 PS1 (or 11.1.2.1) version of Oracle Access Manager. We’ll explain the problem that this feature solves and walk through a simple example explaining how to configure and use the feature. This post is part of a larger series on Oracle Access Manager 11g called Oracle Access Manager Academy. An index to the entire series with links to each of the separate posts is available.

The problem we’re trying to solve

Whenever an application URL is protected by an OAM Webgate, the Webgate will intercept any request to said URL in order to ensure that a valid OAM session exists. Should the Webgate determine that there is no valid session (for instance, in the case of a session time-out), then the user will be redirected for authentication prior to to URL being served. This process is seamless from the perspective of the application, in most cases, unless the request that necessitates re-authentication contains POST data. Consider the following example:

Imagine an incredibly simple web application, comprising a single JSP page containing an input form and a servlet to display the values submitted on the form. The screenshots below demonstrate the working of such an application:

normalflow

As you can see, this really is about the simplest web app it’s possible to imagine and I’m sure its construction doesn’t need any further detailed discussion.  Now imagine that we apply an OAM protection policy to the application and simulate a session timeout before the form can be submitted.  (I have done this by destroying the session from the OAM Console). Note that the POST data entered on the form is not preserved during the authentication redirect, as shown below:

NoPOSTFlow

To clarify what the above diagram depicts, we simulate a session timeout before the “Submit” button on the form can be clicked. The user is thus prompted for re-authentication prior to the HTTP POST to the servlet but during this process, the POST data (i.e the form input values) are lost. This is clearly not ideal from a usability point of view and could potentially negatively impact application functioning as well – were it to happen in the middle of a multi-page transaction, for example.

How to preserve POST data

It turns out that enabling POST data preservation in OAM 11gR2 PS1 can be a very simple exercise. While the documentation (which I strongly encourage reading) does go into a lot of detail regarding a number of different settings and options, the goal here was to do “the simplest thing that works”, in order to make a sort of general purpose recommendation that can be refined further as needed.

The usual caveats about varying mileage do apply, of course and in particular, additional configuration may be required if dealing with particularly large POST payloads or when using custom login pages or detached credential collectors.

The configuration below was tested against the standard OAM login page with the OAM server’s embedded credential collector (ECC) and an OHS 11g Webgate. All that was required in this case to enable POST data preservation was to set a single user-defined parameter on the Webgate configuration, as shown below.

WebgateParameter

As is shown above, the parameter

PostDataRestoration=true

was added to the Webgate configuration. Once the regenerated ObAccessClient.xml file was copied to the Webgate configuration directory, it all worked as expected.

How to (correctly) make manual edits to oam-config.xml

$
0
0

Introduction

Occasionally, it is necessary to make changes to OAM 11g configuration by directly updating the oam-config,xml file, rather than using the OAM console.  In this post, we describe the correct way to make changes to this file. This post is part of a larger series on Oracle Access Manager 11g called Oracle Access Manager Academy. An index to the entire series with links to each of the separate posts is available.

Editing oam-config.xml

Correctly making durable edits to oam-config,xml involves the following steps, which must always be followed exactly.

  1. 1. Shut down the entire domain, including the WebLogic Admin Server and all OAM Managed Servers
  2. 2. Locate the correct “oam-config.xml” file. This will be located on the Admin Server node in the following location: <DOMAIN_HOME>/config/fmwconfig/oam-config.xml
  3. 3. Make a backup of the existing file prior to editing
  4. 4. When editing the file, be sure to increment the version number by 1 to ensure that the changes are not overwritten by the console. See below for details on how to do this.
  5. 5. Once the change has been saved, restart the WebLogic Admin Server, followed by the OAM Managed Servers.
  6. 6. As a verification step, check <DOMAIN_HOME>/config/fmwconfig/oam-config.xml on each of the OAM Managed Server nodes to ensure that the updated version has propagated correctly.

Incrementing the version number

The location of the version number that needs to be incremented is highlighted in the following snippet from the oam-config.xml file. The version number will occur near the top of the file.

<Setting xmlns="http://www.w3.org/2001/XMLSchema" Name="NGAMConfiguration" Type="htf:map">
...
<Setting Name="Version" Type="xsd:integer">175</Setting>
...
</Setting>

In our case, we would need to increment the number from “175” to “176” prior to saving oam-config.xml.

OAM WebGate connections through firewalls

$
0
0

Introduction

In this post, we investigate a complication that can occur if you require a firewall between your WebGate agents and your OAM 11g servers within your deployment topology. We provide some guidance related to how to configure your WebGates in this case. This post is part of a larger series on Oracle Access Manager 11g called Oracle Access Manager Academy. An index to the entire series with links to each of the separate posts is available.

The problem we are trying to solve

Imagine a fairly-typical scenario where an organisation has a number of web servers, within a demilitarized zone (DMZ) that they want to protect with OAM. WebGate plugins will, of course, need to be deployed to these web servers and those plugins will need to establish and maintain Oracle Access Protocol (OAP) connections back to one or more OAM 11g Servers.  It is quite likely that these OAP connections will need to pass through a firewall (or two) on their journey from the WebGates to the OAM servers, which is not, in itself, too much of a problem.

An issue frequently does occur, though, in the case that the firewall imposes either a maximum connection TTL (time to live) or idle timeout – and to be honest, most firewalls will do this as a matter of course. OAP, as has already been widely discussed, is a long-lived protocol and as such, the standard behaviour of an OAP client (such as WebGate) is to initially establish a number of connections to a server and then use those connections repeatedly over a long period of time. OAP clients in general (and WebGates in particular) typically do not react well to an established OAP session being “torn down” ungracefully – and this is exactly what a typical firewall will do if, according to its configuration, a connection has exceeded either its maximum TTL, or its inactive timeout.

The term “ungracefully” above simply means the scenario where the firewall does not send a TCP connection reset message to the client when invalidating the connection. Should you have a well-mannered firewall that does notify the WebGate in this way once it does close the connection, all should be fine and you can probably stop reading at this point. The reality, though, is that most firewalls will not fit into this “polite” category.

When a firewall does invalidate or tear down an OAP connection that WebGate “thinks” is still good, the first time the WebGate attempts to use that connection, the request will obviously fail, Depending on various configuration parameters and the number of connections available, the WebGate may indeed recover from this situation without any major impact to end users (apart from somewhat degraded performance as the WebGate hunts around for a good connection within its pool). It is always possible, though, that all connections could be invalid at once, such as the case of a system that sees little traffic outside of office hours having all of its connections timed out due to inactivity overnight and in this event, there will be a definite impact to end users, with requests failing until WebGate has managed to re-establish its connection pool.

 How to prevent the firewall closing connections

The way to avoid this problem is to ensure that the firewall is never given cause to close a WebGate connection – in other words, ensuring that WebGate connections never exceed the configured TTL or inactivity timeout as defined at the firewall. This is achieved by configuring a maximum connection lifespan, or TTL, at the WebGate side that is less than the firewall’s maximum TTL or idle timeout.

As an example, let’s assume that our firewall imposes an idle timeout of 30 minutes for TCP connections. In this case, we would need to configure WebGate to automatically re-establish any connection older than, say, 25 minutes in order to ensure that the firewall would never need to time out one of its OAP connections. This is done by altering a WebGate setting called “Max Session Time”.

Now, we need to have a bit of a discussion about this particular setting, for a number of reasons. The first is that it really isn’t very well named, considering what it does; it has nothing to do with sessions, but everything to do with connections back to the OAM server and how long they will be allowed to last before being re-established. It should, correctly, be called something like “Max Connection Time” and perhaps in a later version of OAM it will be. As of the time of writing, though (when OAM 11.1.2.1 is the most recent version) we will have to live with the current name.

Perhaps more confusing, though, is the fact that, over the various incarnations of the 11g OAM product, the OAM Console page that allows this WebGate parameter to be defined has been changed repeatedly – consider the screenshots below:

MaxSessionTime

As we can see above, the OAM Console UI, across several releases, has changed the expected unit of time in which this parameter is specified, starting with no unit at all, then moving to hours and then to seconds. What’s more, the default value tends to vary as well, depending on the version you are using and the mechanism that was used to create the initial WebGate profile. The reality of the situation, though, is that you can and should ignore the unit of time that is reflected in the UI, because the default unit for this setting is (and always has been) hours. That probably worth repeating and highlighting, just to be completely clear:

In all OAM 11g versions up through the current release, 11.1.2.1, the default unit for Max Session Time is hours, regardless of what is reflected in the OAM Console UI.

This means that the default maximum TTL for a WebGate connection in OAM 11.1.2.0 and 11.1.2.1 is, in fact 3600 hours! We did say it was meant to be a long-lived connection…

Understanding the default value and the default unit is great, of course, provided that your firewall is (or can be) configured to allow connections to last (or remain idle) for at least an hour. This is often not the case, though.

But what if my firewall timeout is less than an hour?

The good news that that OAM 11g WebGates support a user defined parameter that can be used to change the unit used for Max Session Time. In order to change the unit from “hours” to “minutes”, add the following to the “User Defined Parameters” section in the WebGate profile:

maxSessionTimeUnits=minutes

 Once you’ve done that, then whatever number you’ve entered in the “Max Session Time” box will be interpreted in minutes, rather than hours (again, regardless of what the UI label tells you).

When the change is reflected in the WebGate’s ObAccessClient.xml file, you should see entries similar to the following (these reflect the correct settings for our “25 minute” example above.

...
<SimpleList>
        <NameValPair
            ParamName="maxSessionTime"
            Value="25"></NameValPair>
    </SimpleList>
...

<userDefinedParameters>
<name>maxSessionTimeUnits</name>
<value>minutes</value>
</userDefinedParam>

Remember again – if the maxSessionTimeUnits parameter is not specified, then maxSessionTime will be interpreted in hours.

Seeing the effect

Once you’ve made the appropriate changes, it’s always a good idea to verify that things are working as expected. In order to do this, you should increase the log level of your WebGate to at least “INFO” and then filter out lines from the WebGate log file (oblog.log) containing the string “CONN_MGMT”.

That will allow you to monitor the connections that are opened and closed by WebGate over time. I include a log snippet from my own system (when I set the Max Session Time value to 2 minutes) to highlight the messages to look out for. Note that, just to increase confusion further, the timeout value in the log is printed in seconds, rather than minutes or hours.

2013/12/05@18:30:59.01090       15928   15999   CONN_MGMT       INFO    0x00001C04      /ade/brmohant_17700080/ngamac/src/palantir/aaa_client/src/watcher_thread.cpp:504        "Session expired"       Connection^object{ObConnectionAAA:0x7F2390019D80{_socket=object{ObSocket:0x0241C020{_sock=17}{_my_addr=}{_my_port=0}{_remote_addr=192.168.56.245}{_remote_port=5576}{_use_blocking_calls=false}{_timeout=10000}{_req_pending=0}}}{_state=ObConnUp}{_priority=1}{_debug=false}{_host=oamr2ps1.oracle.com}{_port=5576}{replyMapSize=0}{_seqno=9}{_isSpare=false}{_createTime=1386268079}{_closedTime=0}{_retries=0}}      Maximum Session Time^120        Current Time^1386268259
2013/12/05@18:30:59.01573       15928   15999   CONN_MGMT       INFO    0x00001C02      /ade/brmohant_17700080/ngamac/src/palantir/aaa_client/src/watcher_thread.cpp:474        "New connection opened to Access Server"        Connection^object{ObConnectionAAA:0x7F2390306270{_socket=object{ObSocket:0x023E8390{_sock=19}{_my_addr=}{_my_port=0}{_remote_addr=192.168.56.245}{_remote_port=5576}{_use_blocking_calls=false}{_timeout=10000}{_req_pending=0}}}{_state=ObConnUp}{_priority=1}{_debug=false}{_host=oamr2ps1.oracle.com}{_port=5576}{replyMapSize=0}{_seqno=0}{_isSpare=true}{_createTime=1386268259}{_closedTime=0}{_retries=0}}
2013/12/05@18:30:59.01584       15928   15999   CONN_MGMT       INFO    0x00001C04      /ade/brmohant_17700080/ngamac/src/palantir/aaa_client/src/watcher_thread.cpp:504        "Session expired"       Connection^object{ObConnectionAAA:0x7F239028F770{_socket=object{ObSocket:0x023D3000{_sock=18}{_my_addr=}{_my_port=0}{_remote_addr=192.168.56.245}{_remote_port=5576}{_use_blocking_calls=false}{_timeout=10000}{_req_pending=0}}}{_state=ObConnUp}{_priority=1}{_debug=false}{_host=oamr2ps1.oracle.com}{_port=5576}{replyMapSize=0}{_seqno=9}{_isSpare=false}{_createTime=1386268079}{_closedTime=0}{_retries=0}}      Maximum Session Time^120        Current Time^1386268259
2013/12/05@18:31:59.10580       15928   15999   CONN_MGMT       INFO    0x00001C02      /ade/brmohant_17700080/ngamac/src/palantir/aaa_client/src/watcher_thread.cpp:474        "New connection opened to Access Server"        Connection^object{ObConnectionAAA:0x7F239028F770{_socket=object{ObSocket:0x0241C020{_sock=17}{_my_addr=}{_my_port=0}{_remote_addr=192.168.56.245}{_remote_port=5576}{_use_blocking_calls=false}{_timeout=10000}{_req_pending=0}}}{_state=ObConnUp}{_priority=1}{_debug=false}{_host=oamr2ps1.oracle.com}{_port=5576}{replyMapSize=0}{_seqno=0}{_isSpare=false}{_createTime=1386268319}{_closedTime=0}{_retries=0}}

As a closing note, remember to reduce the log level of your production WebGates again once you’ve verified that the correct connection time setting is in force.

OAM LDAP connections through firewalls

$
0
0

Introduction

In a previous post, we discussed some of the complications that can occur when a firewall is placed between WebGates and OAM Servers in a typical deployment. This post follows on from that discussion, to explore an analogous topic- firewalls between the OAM Server and the LDAP Identity Store. This post is part of a larger series on Oracle Access Manager 11g called Oracle Access Manager Academy. An index to the entire series with links to each of the separate posts is available.

The problem we are trying to solve

Without repeating the discussion from the previous post, the problem, in a nutshell, is preventing an over-eager firewall from tearing down an LDAP Identity Store connection that OAM still needs to use. Should this happen, OAM requests sent over that connection will fail, leading to degraded performance as the LDAP connection is re-established and the operation re-tried. Once again, the solution lies in configuring OAM’s LDAP Connection Pool to refresh connections on its own accord, by appropriately setting the Identity Store’s connection TTL (time to live) as below.

This procedure works for OAM versions from 11.1.1.5 up to and including 11.1.2.1.

 

 How to prevent the firewall closing connections

The way to avoid this problem is to ensure that the firewall is never given cause to close an LDAP connection – in other words, ensuring that LDAP connections never exceed the configured TTL or inactivity timeout as defined at the firewall. This is achieved by configuring a maximum LDAP connection lifespan, or TTL, at the OAM side that is less than the firewall’s maximum TTL or idle timeout.

This is achieved by adding the MaxConnectionReuseTime setting to the Identity Store configuration in oam-config.xml, as per the below snippet. The value is specified in seconds.

<Setting Name="LDAP" Type="htf:map">
        <Setting Name="E9ABCBCF59F0CDEC56" Type="htf:map">
          .....         
          <Setting Name="LDAP_URL" Type="xsd:string">ldap://idstore.example.com:389</Setting>
          <Setting Name="ReferralPolicy" Type="xsd:string">follow</Setting>
          <Setting Name="GroupCacheSize" Type="xsd:integer">10000</Setting>
          <Setting Name="MaxConnectionReuseTime" Type="xsd:string">1740</Setting>
          <Setting Name="UserIdentityProviderType" Type="xsd:string">OracleUserRoleAPI</Setting>
        </Setting>
       .....
</Setting>

In the above example, MaxConnectionReuseTime has been set to 1740 seconds, or 29 minutes. This would be an appropriate setting for a firewall that times connections out after 30 minutes, since the OAM TTL should always be lower than that enforced by the firewall. Be sure to set MaxConnectionReuseTime to an appropriate value for your own environment.

Be sure to follow the correct procedure for making manual edits to oam-config.xml, as described in this post

 As a closing comment, be aware that you may additionally need to configure your LDAP server to enforce a connection TTL; in this case, though, the server-side timeout should be higher than that set by the firewall – and obviously also higher than OAM’s MaxConnectionReuseTime.

How To Display A Custom Error Page When the Access Server Is Down?

$
0
0

I have been asked several times over the years if there is a way to customize the following error message a User is presented in their Internet browser when the WebGate fails to contact any of the Access Servers.

Oracle Access Manager Operation Error

The WebGate plug-in is unable to contact any Access Servers.

Contact your website administrator to remedy this problem.

Though this error is without a doubt accurate, many clients would rather display something a little more friendly or have other reasons to change it.  Interestingly this error has been the same message going back to the early days of OAM when it was still Oblix.  Incidently there is a great My Oracle Support document 555137.1 that provides steps on how to customize the error message, but it refers to OAM 10g.  So this begs the question will this work with the newer OAM 11g, and more specifically 11g WebGates.  I am here to say, “Yes it does”, I have tested this and this article covers this option and a bit more.

Lets Get Some Questions Out of the Way

I have been asked if there are alternate ways of customizing the error message. For example if using Apache or OHS, why not put a customized message in the ErrorDocument 500 inside the httpd.conf file; http://httpd.apache.org/docs/2.2/mod/core.html – error document. Good question because the WebGate does use a parameter HTMLpage500 so you would think it can just be as simple as modifying the 500 error.  However I tried and this does not work and for good reasons. The WebGate becomes the main gatekeeper, so if it cannot communicate to any Access Servers to make security decisions it will basically shutdown and reject all traffic to make sure nothing is compromised hence why it immediately lets people know the OAM Access Servers are down…do something!!

Then what about telling a load balancer in front of the web servers that have the WebGates to redirect to an alternate place? One problem is the load balancer is not intelligent enough to know if the WebGate is down. Another is if you could redirect, how is security taken care of? It is not as simple as it sounds.

At this point the best option is to leverage the article I mentioned, I feel this option is the best right now and it is not that complicated to implement.  So let’s move on and find out how to do it.

 

How to Create Your Custom Error Page

As I mentioned earlier, there is an article OAM 10g: How To Display A Custom Error Page When the Access Server Is Down? / WebGate Plug-in is Unable to Contact any Access Servers (Doc ID 555137.1), which I spent a lot of time validating that it works for 11g WebGates, and as I said it does.  Though I don’t really provide any additional ways that the article shows on how to generate a custom error message, I do go a little beyond the article and explain an easy way to make the custom message.  So lets get into it now.

1. Update the WebGate.xml file message tag ErrEngineDown
The key to this customization is updating a file called WebGate.xml. It is located in the WebGate install path under <WebGate install path>/wg1_home/webgate/ohs/lang/en-us. Now I used “en-us” for English, but if your environment requires a different language, look under “/lang/” and you will see other languages and within each language is a WebGate.xml file. So make sure the correct WebGate.xml file is being updated. Use an editor and open the WebGate.xml file and search for ErrEngineDown. Now change the default ErrEngineDown message “The WebGate plug-in is unable to contact any Access Servers.” with the custom message you want. This text will be output to the error page when the WebGate cannot contact any of the Access Servers for some reason.  Be sure to make a backup of the original WebGate.xml file in case you need to revert back.

2. Make your HTML Custom Error Page
Next there is another message tag inside the WebGate.xml file called HTMLpage500.  This tag can actually hold a real HTML page that will be displayed for the end user, so it is a lot more flexible.  So the best thing is to create some basic HTML you want the custom page to display, and note if possible try to avoid images. If you require images the reference to the images will need to point to some other external web server because when the OAM servers are down, the WebGate will basically not even let the web server work because it is trying to stop anyone from getting in; this is a security feature by design. So go ahead and create the HTML page you want to display for the end user.  Note toward the end of this article there is a neat little trick you can do.

3. Convert the HTML to XML
Now in the previous step you created some custom HTML page, but before you insert this custom message into the WebGate.xml it needs to be converted to XML.  To better understand, the less than sign < needs to be converted to &lt; and a greater than sign > needs to be converted to &gt;.  This certainly could tediously be done manually, but a much easier way is take the HTML, copy and paste it into this online HTML to XML converter https://sites.google.com/site/infivivek/resourse-centre/online-resources/html-to-xml-converter,  click the Convert button, and whala you have XML. Once you have the XML version of the HTML, copy it and go to the next step.

4. Update the WebGate.xml file message tag HTMLpage500 with the new XML.
The custom HTML page created earlier that was converted to XML can now be pasted into the WebGate.xml file. Edit the WebGate.xml file and search for HTMLpage500. Just like the ErrEngineDown message value, you will replace the default message with the XML copied from the previous step. This XML will be presented by the WebGate when the Access Servers are unavailable as an HTML page.  Be sure to save the WebGate.xml file.

5. Restart the Web Server
For the WebGate.xml file to take affect restart the web server.

6. Repeat
Since each web server will have its own WebGate install, you will need to repeat the same process above and update each WebGate.xml.  Alternatively an easier option is to simply copy the WebGate.xml file to the other WebGate install locations, there is no path reference to the install so copying the file is a safe and easy option.  Your WebGate install may be installed in a common mount If using a UNIX operating system and if that is true you may not need to copy or update the WebGate.xml file across several web servers.

7. Test the Custom Message by shutting down the OAM Access Servers
Finally we need to make sure it works.  To test the custom message, login to a WebGate protected application or page. Then shut down all the OAM Access Servers so that the  WebGate will act on this error.  Once all the Access Servers are down, refresh the browser and you should see the new custom message.  If not, review the WebGate oblog.log file to see if there are any errors that can help troubleshoot, or make sure the WebGate.xml file is correct.

 

Another HTMLpage500 option

The MOS article 555137.1 has a good option that adds a little META http-equiv=”REFRESH” method redirect, which redirects in zero seconds the browser to an alternate web page all together.  This trick will work on all web browsers.  However It would require an alternate web server that is running, and that web server could not have a WebGate because if it did that web server would also stop serving up HTML content. It is a clever option and certainly something worth thinking about.

Optional Actual HTML

<HTML>
<HEAD>
<TITLE>OAM Engine Down</TITLE>
<meta http-equiv=”REFRESH” content=”0;url=http://www.oracle.com/index.html”>
</HEAD>
<BODY>
</BODY>
</HTML>

Converted HTML to XML

&lt;HTML&gt;
&lt;HEAD&gt;
&lt;TITLE&gt;OAM Engine Down&lt;/TITLE&gt;
&lt;meta http-equiv=&quot;REFRESH&quot; content=&quot;0;url=http://www.oracle.com/index.html&quot;&gt;
&lt;/HEAD&gt;
&lt;BODY&gt;
&lt;/BODY&gt;
&lt;/HTML&gt;

In summary, this solution will provide a working option to create a custom error page when the OAM Access Servers are down. Feel free to play around with different messages and most of all test them to make sure they work.  Enjoy!

Chained LDAP Authentication in OAM 11g

$
0
0

Introduction

In this post, we look at a simple way to configure a chained LDAP authentication scheme in OAM 11g R2. This post is part of a larger series on Oracle Access Manager 11g called Oracle Access Manager Academy. An index to the entire series with links to each of the separate posts is available.

The problem we are trying to solve

Consider a situation where the users that need to be authenticated by Oracle Access Manager do not all reside within the same LDAP directory. This is a fairly common situation which can arise as a result of mergers and acquisitions, or even of IT consolidation between different departments or business units within a single organisation. While it may well be desirable to consolidate all user records into a single LDAP structure over time, often the immediate needs of the business are such that this simply wouldn’t be feasible in the short term, particularly if there are challenges in terms of data consistency, format, password storage and so on that would need to be overcome as part of a migration project.

While it is possible (and quite common) to address requirements of this nature using Oracle Virtual Directory – in short, inserting OVD in between OAM and the physical LDAP repositories in order to construct a single virtual tree – one can also use OAM’s pre-built authentication plugins to accomplish essentially the same thing, in a simpler way.

The solution described below has been built and tested against OAM 11g R2 PS2 (11.1.2.2). I cannot guarantee that it will work against older versions.

Creating a Chained LDAP Authentication Module

The first step here is to ensure that all directories containing user information are correctly configured as User Identity Stores within OAM. To demonstrate the concept, I installed two separate Oracle Unified Directory instances on my test server and added both as Identity Stores using the OAM console – the below screenshot shows OUDStore and OUDStore2, which refer to distinct directory instances as can be seen from the differing port numbers:

IDStores

We then configure a custom Authentication Module, which will attempt to match the provided user ID against each of the directories in turn. In this simple example, the module will first do a lookup against the first directory (OUDStore). If that lookup succeeds, it will attempt authentication against OUDStore using the provided password. Should the intitial lookup fail, it will attempt the lookup against the second directory (OUDStore2). Again, should that lookup succeed, it will attempt authentication against OUDStore2 using the provided password. Should both lookups (or either password authentication step) fail, then the entire authentication attempt will fail.

We configure the module by including two instances of both the UserIdentificationPlugin and the UserAuthenticationPlugin. Both are standard OAM plugins that ship with the product.

The screenshots below demonstrate the configuration of our ChainedLDAP custom Authentication Module:

ChainedAuthNModule1ChainedAuthNModule2ChainedAuthNModule3ChainedAuthNModule4ChainedAuthNModule5

This next screenshot shows the orchestration flow through the various steps:

ChainedAuthNModuleOrch

Note that “OUD1ID” (User Identification against OUD 1) is the first step. On failure of this step, we execute “OUD2ID” (User Identification against OUD 2). Note also that successful completion of either of the two User Authentication steps will result in a successful result for the orchestration as a whole.

The only remaining step is to build and Authentication Scheme that uses this new module. That can be done by cloning the standard “LDAPScheme” and changing the Authentication Module, as below:

ChainedAuthNScheme

When we assign the above Authentication Scheme to a resource within an Application Domain, we see that we can successfully authenticate using credentials from either of the OUD instances.

What about Authorization?

Extending the use case a little, we can build authorization conditions that make sense in this case by specifying group membership rules across both directories. In the screenshots below, as an illustration, I’ve included separate group membership conditions for each OUD instance, with an OR rule to ensure that either will allow access.

ChainedAuthZ1

ChainedAuthZ2

ChainedAuthZ3

Some practical considerations and limitations

As with all approaches described on this site, this one is not a silver bullet. While it offers a simple way to allow OAM to authenticate users against more than one directory, it has a number of limitations, of which the below are just a few:

  • Collision of user names is not handled well. In the case where the same user ID existed in both directories, only the first would be checked. It is, of course, not possible for a single login process to handle the case where ore than one distinct user has the same user ID in any case, but it is important to be aware of this limitations regardless.
  • It is unlikely that this approach will scale particularly well beyond a handful of directories. You certainly wouldn’t want to check a user name against each of a large number of directories in sequence, for performance reasons.
  • The complexities of defining meaningful authorization policies based on group memberships across multiple directories shouldn’t be underestimated. This approach is probably best used in situations where authorization requirements are not stringent (such as allowing all users within all directories to access resources)

Understanding OAM 11g ASDK Configuration and Cert Requirements

$
0
0

Introduction

Oracle provides documentation on developing an Access Client for the OAM 11g ASDK http://docs.oracle.com/cd/E40329_01/dev.1112/e27134/as_api.htm#autoId0, but getting it to work can be challenging when running the Access Servers in Simple or Cert Mode.  In this article I will not explain how to create an Access Client, there are already good examples out there for that.  What I want to cover is the correct structure of the Access Client configuration including all the required files and code snippets to hopefully save you a lot of time.

What is an Access Client?

An Access Client is basically a way to developed a custom WebGate using the OAM Access Server SDK — AKA ASDK.  The SDK and API can be used to develop anything from your own custom authentication web service, a way to validate a Users token, to a simple mechanism to enhance a User’s login with additional session information.

At the time of this article the latest ASDK 11.1.2.2.0 can be downloaded by going to
http://www.oracle.com/technetwork/middleware/id-mgmt/downloads/oid-11gr2-2104316.html. The newer ASDK is backward compatible with 10g, but also provides many new features:
* Enumerating sessions for the given user
* Terminating the given session
* Setting attributes in the given user session
* Retrieving attributes set in the given session
* ++ Validating user credentials without establishing a session
* ++ Validating user credentials without establishing a session and performing authorization in the same request
————————————————————————————————————————————————–
++ The last two functions are also provided with the com.oblix.access package in the Access Manager 11g Access SDK. Additionally, the Access SDK provides a modified implementation of the user logout functionality for removing the server side session. This functionality is not supported with 10g OAM Server.

Step 1 ) Creating the Configuration Structure

The latest 11.1.2.2.0 OAM Development Guide provides a section 2.52. Configuration Requirements http://docs.oracle.com/cd/E40329_01/dev.1112/e27134/as_api.htm#autoId26, which provides plenty of information on various configuration requirements, but it lacks information on how to properly structure the configuration directories and where each required file related to OAP communication should come from. Knowing this information is key to getting an Access Client to work in SIMPLE or CERT mode, and even parts of it is required just to get it to work in OPEN mode. Below illustrates the directory structure of where the configuration files are stored, which files go where, and what exactly is needed for either OPEN, SIMPLE, or CERT modes. Start by creating this directory structure in your Java project along with copying or importing the appropriate files into your project as follows. See Table 1 to learn where to get all the required files found in the Access Client Configuration structure.

 

Access Client Configuration Certificate Structure -

config/
|
|– cwallet.sso (Get from WebGate – **)
|– jps-config.xml (Get from ASDK Sample – **)
|
`– oblix/
|
|– config/
|   |– password.xml (Get from WebGate – **)
|   |
|   `– simple/
|       |– oamclient-keystore.jks (Get from OAM Domain – **)
|       `– oamclient-truststore.jks (Get from OAM Domain – **)
`– lib/
     `– ObAccessClient.xml (Get from WebGate – *)

 Important Information -
*  - Required for All modes
** - Required for 11g Simple or Cert Mode
NOTE: If using Cert Mode then aaa_cert.pem and aaa_key.pem would be replaced by a third party CA 
(Certificate Authority) generated certificate along with importing the CA certificate into the 
OAM trust store.

As a side note If you need to switch your Access Servers from OPEN to SIMPLE mode, the following link provides the basic steps
http://docs.oracle.com/cd/E40329_01/admin.1112/e27239/keytool.htm#AIAAG5632.

 

Step 2) Setting the credstore location in the jps.config.xml

In OAM 11g the jps-config.xml file is used for a variety of things, but for the 11g ASDK it is used to let the ASDK know where the configuration structure is located. The jps-config.xml file is found within the OAM 11g ASDK download file. In the previous config structure you can see that the jps-config.xml file is under the root folder, in this case “config”. Since all the required files are below this the location parameter only needs to be set to the current directory. So below you can see location=”.” for current directory. This should already be default as “.”, if so no changes are required.

<!– Specify agent key wallet location relative to this jps-config.xml location –>
<serviceInstance name=”credstore” provider=”credstoressp” location=”.”>
     <description>File Based Credential Store Service Instance</description>
</serviceInstance>

 

Now we can set a variable that references the cred store following snippet line of code and should be placed toward the top of the Access Client where all the variables are defined. I used “./config” because in my example the top directory path for the certificate files is “config”, and as long as the compiled Java Access Client is placed in the path of ./config it will find all the right files as long as the lower part of the tree is structured as mentioned earlier.

// Declaring variables
public static final String m_configLocation = “./config”;

 

Step 3) Creating the Access Client Instance

Now that the structure is created in your project, the correct files are imported, the jps-config.xml is correctly set, and a static string has been defined to reference the configuration location, we can now create the Access Client instance.

Just below the main area of the Access Code an instance of the Access Client is normally created.  You will need to include the public static variable from earlier as a parameter.  The following code snippet is an example has the m_configuration variable, which is of course the variable pointing to the configuration. Using m_configuration without additional parameters tells the ASDK to default to a 11g Access Client which requires a 11g WebGate profile. This is in contrast to using ac = AccessClient.createDefaultInstance(m_configLocation, AccessClient.CompatibilityMode.OAM_10G); which would only be used if using a WebGate 10g profile. In our case we are better off using 11g. Another option is to us ac = AccessClient.createDefaultInstance(m_configLocation, AccessClient.CompatibilityMode.OAM_11G), but leaving it to just plain m_configLocation is fine and what is recommended.

// Creating an Access Client instance
ac = AccessClient.createDefaultInstance(m_configLocation);

Now build your code to see if it works.

 

Reference Table of Configuration Files with Explanations

To further help I am providing a table that includes all the important files used within the config directory along with explanations on the purpose behind these configuration files. For additional information on the files you can also see section 2.5.2 Configuration Requirements documentation http://docs.oracle.com/cd/E40329_01/dev.1112/e27134/as_api.htm#autoId26. The table also provides locations on where to get all the required files, which you would then place into the config structure that was described earlier.

File Name Explanation
cwallet.sso Created when registering a 11g WebGate and contains the secret key needed by the OAM Access Server when encrypting a token sent from the agent (Access Client is the agent).  Found in the $ORACLE_HOME/user_projects/domains/<oam_domain>/output/ <RREG_WEBGATE> directory.
jps-config.xml This is required for an 11g Access Client and used to read the cwallet.sso, but also contains a parameter location=”.”  to reference the location of the config folder.
aaa_cert.pem Generated when registering a 11g WebGate in Simple mode.  Found in the $ORACLE_HOME/user_projects/domains/<oam_domain>/output/ webgate-ssl directory.
aaa_key.pem Generated when registering a 11g WebGate in Simple mode.  Found in the $ORACLE_HOME/user_projects/domains/<oam_domain>/output/ webgate-ssl directory.
oamclient-truststore.jks Generated when using SIMPLE or CERT mode for OAM 11g and found in the $ORACLE_HOME/user_projects/domains/<oam_domain>/output/ webgate-ssl directory.  This file is more or less like an internal CA for OAM.  If using CERT mode the third party CA would need to be imported into this file.
oamclient-keystore.jks The private keystore for the oamclient-truststore.jks file.  Also found in the $ORACLE_HOME/user_projects/domains/<oam_domain>/output/ webgate-ssl directory.
password.xml Contains the Global Passphrase used by OAM 11g for the aaa_cert.pem and aaa_key.pem files.  Also found in the $ORACLE_HOME/user_projects/domains/<oam_domain>/output/ <RREG_WEBGATE> directory.
ObAccessClient.xml Holds all the configuration information for the Access Client in order too not only communicate with the Access Server(s), but also defines the behavior the Access Client will abide.  Found in the $ORACLE_HOME/user_projects/domains/<oam_domain>/output/ <RREG_WEBGATE> directory.

 

Tips on Validating the TrustStore and PEM Certificate

There may be times where you get complaints about the certs or keys, but hopefully if you take the following steps it will work out the first time.

1) Configure SIMPLE mode if not already done using http://docs.oracle.com/cd/E40329_01/admin.1112/e27239/keytool.htm#AIAAG5632 that was already mentioned earlier.

2) Register the 11g WebGate in SIMPLE mode from the OAM Console and get the following files from $ORACLE_HOME/user_projects/domains/<oam_domain>/output/<RREG_WEBGATE> to the respective config location.
• cwallet.sso
• ObAccessClient.xml

3) Copy the following files from $ORACLE_HOME/user_projects/domains/<oam_domain>/output/webgate-ssl to the respective config location.
• oamclient-truststore.jks
• oamclient-keystore.jks
• aaa_cert.pem
• aaa_key.pem
• password.xml

4) Get the jps-config.xml file from the ASDK download http://www.oracle.com/technetwork/middleware/id-mgmt/downloads/oid-11gr2-2104316.html and copy it to the respective config location.  Leaving the default config location in the jps-config.xml file should be fine unless you find a reason to change it.

5) For CERT mode the only changes would be following section 2.5.4.2 Cert Transport Security Mode http://docs.oracle.com/cd/E40329_01/dev.1112/e27134/as_api.htm#autoId30 and making sure you import the third party CA certificate into the oamclient-truststore.jks file.

If you still find errors relating to the certs, you can validate your truststore and cert using some common tools. For the oamclient-truststore.jks file run the keytool command as follows.

keytool –list –keystore oamclient-truststore.jks –v

You will get a prompt for a password, but you can just press enter to continue which should present you with something similar to this. Pay attention to the Owner and Issuer. This is the built in OAM CA and should also be present in the WebGate aaa_cert.pem file.

***************** WARNING WARNING WARNING *****************
* The integrity of the information stored in your keystore *
* has NOT been verified! In order to verify its integrity, *
* you must provide your keystore password. *
***************** WARNING WARNING WARNING *****************
Keystore type: JKS
Keystore provider: SUN
Your keystore contains 1 entry
Alias name: oam.simple.ca
Creation date: Jul 7, 2014
Entry type: trustedCertEntry
Owner: CN=NetPoint Simple Security CA - Not for General Use, OU=NetPoint, O="Oblix, Inc.", L=Cupertino, ST=California, C=US
Issuer: CN=NetPoint Simple Security CA - Not for General Use, OU=NetPoint, O="Oblix, Inc.", L=Cupertino, ST=California, C=US
Serial number: 0
Valid from: Wed Apr 01 07:57:22 CDT 2009 until: Thu Mar 28 07:57:22 CDT 2024
Certificate fingerprints:
      MD5: 05:F4:8C:84:85:37:DB:E3:66:87:EF:39:E0:E6:B2:3F
      SHA1: 97:B0:F8:19:7D:0E:22:6B:40:2A:73:73:1B:27:B2:7B:8D:64:82:21
      Signature algorithm name: MD5withRSA
      Version: 1
*******************************************
*******************************************

 

If you run the keytool command and get the following error “keytool error: gnu.javax.crypto.keyring.MalformedKeyringException: incorrect magic”, that means the keytool being used is probably incorrect.  Use the keytool found in the JAVA home under $JAVA_HOME/bin directory.

Just in case you are using the aaa_cert.pem file you can use OpenSSL to list the certificate chain to make sure the CA matches the truststore. Run the following command openssl command; OpenSSL should be part of Linux.

openssl –x509 aaa_cert.pem –text

 

 If openssl command is not found you can use the openssl that is included in the WebGate or AccessServerSDK install under the <Install Path>/oblix/tools/openssl directory.

 

You should see the beginning of the output that similar to below.  The CA should be found in the Issuer, but in a reverse order of what you saw from the oamclient-truststore.jks output.   If this is CERT mode then you would verify that the CA matches the third party certificate that was imported into the oamclient-truststore.jks file.

Certificate:
  Data:
     Version: 1 (0x0)
     Serial Number: 10 (0xa)
     Signature Algorithm: md5WithRSAEncryption
     Issuer: C=US, ST=California, L=Cupertino, O=Oblix, Inc., OU=NetPoint, CN=NetPoint Simple Security    CA - Not for General Use
     Validity
        Not Before: Jul 7 23:27:28 2014 GMT
        Not After : Jul 4 23:27:28 2024 GMT
     Subject: CN=oam.simple.cert
     Subject Public Key Info:
        Public Key Algorithm: rsaEncryption
        RSA Public Key: (1024 bit)
           Modulus (1024 bit):
           00:b6:61:b1:d6:1e:50:98:1e:03:05:b5:9f:2d:61:
           a8:ce:a0:c2:02:04:bd:ec:fe:2a:be:29:1d:98:74:
           38:49:79:1a:51:69:c5:8b:6e:15:32:a4:a9:5e:3a:

 

Summary

Though this article does not provide all the information in creating an Access Client, nor could it, it should still provide some key information that is missing in the official Oracle Developer’s Guide for OAM that can certainly save you a lot of frustration in getting an Access Client to work especially when running in SIMPLE or CERT mode. Using what has been covered along with the existing documentation and the basic sample Access Client found in section 2.2.3 Sample Code: Simple Access Client http://docs.oracle.com/cd/E40329_01/dev.1112/e27134/as_api.htm#autoId10 should help get you up and running in no time. Good luck!

Logging made easy in OAM 11g with this simple trick!

$
0
0

INTRODUCTION

 

This post is part of a larger series on Oracle Access Manager 11g called Oracle Access Manager Academy. An index to the entire series with links to each of the separate posts is available.

Logging is extremely helpful when trying to troubleshoot issues and normally when you see instructions to log in OAM 11g there is documentation on using WLST commands with several steps or Enterprise Manager that can be used to set various log levels, but in both cases this can be a bit tedious.  Wouldn’t it be great if you could just update some file like in the old OAM 10g days using the oblog_config.xml or something similar; see  http://docs.oracle.com/cd/E12530_01/oam.1014/b32419/log.htm.  Well I am going to give you a little known trick that can provide you this very thing.  Welcome to updating the logging.xml file and it does this in real time without any restarts needed to add or remove logging!!  Read on….

How to Configure Logging using a simple XML file.

There is a little known secret where you can update the logging.xml file.  The following steps will show you how to add logging that is persistent even if you restart the managed server.  NOTE: Now in 11.1.2.2.0 or later in Enterprise Manager there is an option to make logging persistent by using a check box.

 

  1. 1. Go to $IAM_DOMAIN/config/fmwconfig/servers/<ServerName>/; where <ServerName> is the server name to change logging like oam_server1.
  2.  

  3. 2. Make a backup of logging.xml
  4.  

  5. 3. Edit logging.xml
  6.  

  7. 4. Search  for “loggers”, you should find the first line below <logger name=” level=’WARNING:1′>.
  8.  

  9. 5. You can add one or more lines as needed above <logger name=” level=’WARNING:1′> as follows; below are a couple examples showing two loggers.
    <logger name=’oracle.oam.user.identity.provider’ level=’TRACE:16’/>
    <logger name=’oracle.ods.virtualization’ level=’TRACE:16’/>
  10.  

  11. 6. NO RESTART — Once you save the change logging should start after a few seconds.
  12.  

  13. 7. Follow this link to learn more details on various modules you can use in the logging.xml file http://docs.oracle.com/cd/E40329_01/admin.1112/e27239/logging.htm#CHDIBAHF.
  14.  

  15. 8. To stop the logging simply remove the lines that were added from the logging.xml and save, or revert the logging.xml backup file.
  16.  

The key is adding the proper module to the name=’<MODULE>‘ value and the logging level=’<LEVEL>‘ for the logging level where <MODULE> is something like oracle.ods.virtualization and <LEVEL> is the logging level like TRACE:16; note TRACE:32 may also been required to get more fine grain detail depending on the problem you are troubleshooting.  Be careful when updating the logging.xml file for formatting and using the correct loggers.  To be safe use the examples I give as a template along with finding the right module to log.  If you do not feel comfortable doing this I would highly recommend using Enterprise Manager because there is no room for error.

Summary

This trick may not be for everyone.  For example in a production environment there may be security lock downs for good reason to prevent updating or even accessing certain files, so Enterprise Manager still may be the best choice.  However for those that may be working in a non-production environment that have access to this configuration file, this trick may be your very best friend.  Happy logging!!

Part 1: Getting under the covers of Detached Credential Collector (DCC)

$
0
0

Introduction

This post is part of a larger series on Oracle Access Manager 11g called Oracle Access Manager Academy. An index to the entire series with links to each of the separate posts is available.

The Detached Credential Collector (DCC) feature was introduced with the release of OAM 11gR2 — 11.1.2.0.0.   DCC brought some very interesting changes in the authentication model that in my opinion are very welcome; more on that later.  There is already Oracle documentation out there on this feature, along with an A-Team blog article Debasish Bhattacharya created (Detached Credential Collector Configuration – OAM 11GR2) , which adds some more insight on configuring DCC.  This blog is to enlighten everyone with some more information on what is going on with DCC, both for login and logout.  Then in Part 2 – Custom Login and Logout with Detached Credential Collector, I want to clear up some confusion on how many may think using DCC can only be done with the Oracle supplied login.pl and logout.pl Perl scripts; that is far from the truth.   So let’s dig in and expose some of the mysteries of the Detached Credential Collector.

 Main Article

About DCC (Detached Credential Collector)

As I mentioned in the introduction, Detached Credential Collector is a capability that came with the release of OAM 11gR2 (11.1.2.0.0), and note this is for 11g WebGates only.  If you login to the OAM Console and look at an 11g WebGate profile you will see the checkbox option “Allow Credential Collector Operations”.  See the graphic below that highlights the option.  This checkbox is the only difference that makes a DCC WebGate what it is from a configuration standpoint.

 

DCC WebGate Agent Profile

The term Detached Credential Collector (AKA Authenticating WebGate), relates more to the way credentials are collected when submitting the login.  For example with DCC the login credentials are collected at the DCC WebGate versus ECC (Embedded Credential Collector) where the credentials are collected directly by the OAM Server.  This is a key difference between DCC and ECC, which greatly changes the authentication model.

How the DCC and ECC Authentication Model differ?

The Oracle documentation Administrator’s Guide for Oracle Access Management
11g Release 2 (11.1.2) in section 16.5.2 Comparing Embedded Credential Collector with Detached Credential Collector has a very nice table comparing DCC to ECC.  If you compare each row side by side you will find that DCC compares pretty much the same as ECC, but one big difference is the method of where the credentials are collected, as I mentioned earlier.  I like to use illustrations to explain something because I think it helps make a complicated subject easier to understand.  Just keep in mind the diagram is very simplified, so there are certainly other request and response trips between the WebGates and OAM Servers, but I really wanted to keep it high level to capture the essence of DCC vs ECC authentication model.

 

ECC vs DCC Authentication Model

The diagram above is trying to illustrate at a high level the differences between the DCC and ECC authentication model.  The DCC flow is in blue and you can see in sequence 2 the User submits their login credentials directly to the DCC WebGate.  In the ECC model the User submits the credentials to the OAM Server, which is located in the mid tier — very interesting.

So the big “Ah Ha” moment here is that the DCC model completely separates the client from the OAM Servers in the Mid Tier, a model which many consider to be more secure!    Particularly for internet-facing deployments of OAM, where the ECC-model requirement to allow HTTP access to the OAM server (for credential submission) can present challenges in terms of ensuring adequate security.

There are, of course, ways to mitigate security concerns in the ECC model such as a firewall and or a load balancer to setup rules to prevent any malicious traffic being sent directly to the OAM Servers.  This is security 101 that should be incorporated into a good architecture anyway; doing it for the OAM Servers using ECC should be done by default.  In addition, OAM already has built in features to help mitigate things like buffer overflows and such, so don’t be too alarmed.

That said, you can see how much simpler security could be using the DCC model.  DCC makes security a little less complicated by separating the WebGates in the Web Tier from the OAM Servers all together.  In a way the DCC model is similar to the old OAM 10g model where your login credentials are submitted directly to the WebGate, and the WebGate communicates back to the OAM Servers over OAP which mitigates any chance that a rogue user will send direct requests to the OAM Servers in the mid tier.  So DCC is something to really consider.  In my opinion this is a very welcome feature of DCC.

Let’s look at some HTTP Traces

I like to start by capturing some HTTP traces to see what is going on, so let’s dive down a couple layers and see what is going on.  Before I do, I first want to point out that for the DCC HTTP Traces I am presenting I used the out of the box login.pl and logout.pl scripts.  However I want to let you know that it is completely possible – and perhaps even advisable – to replace these scripts with custom functionality.  So for illustration and to build on Debasish Bhattacharya’s Detached Credential Collector Configuration – OAM 11GR2  blog I wanted to start by keeping things simple; in Part 2 I will expand in more detail on how to create a custom login and logout which does not use the Perl scripts and includes very important information needed to make it all work perfectly.

Below is a sequence diagram that shows a flow of a user logging into the Acme Portal, but also requesting a second completely different domain (Globex Portal) where the user is not challenged again because of SSO, and finally the logout of all domains.   I will try to keep this interesting, but then in Part 2 I will go further to show all the details for a custom login and logout.

DCC Sequence DiagramSEQ 1 – Initial HTTP Request

Sequence 1 shows that the initial request is to http://acme.melander.us/.  This sequence is pretty normal and looks exactly the same for ECC.  Below you can see the GET to acme.melander.us, but in sequence 2 things change a bit and start to differ between DCC and ECC.

GET / HTTP/1.1
Host: acme.melander.us
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8

SEQ 2 – Redirect to DCC Login Response

In sequence 2 the Resource WebGate realizes the browser does not have an OAMAuthnCookie SSO token so then tells it to do a HTTP 302 and redirects it to the DCC WebGate web server.  In the HTTP trace below it shows a HTTP 302 along with the obrareq.cgi, which is really no different than what is seen in an ECC HTTP Trace.

HTTP/1.1 302 Found
Connection: Keep-Alive
Content-Length: 595
Content-Type: text/html; charset=iso-8859-1
Date: Fri, 12 Sep 2014 12:03:59 GMT
Keep-Alive: timeout=5, max=100
Location: http://sso.melander.us/obrareq.cgi?encquery%3DShtPLKTcR3ddwuuVUNKCo8d1wy5tSOb7qqKXkir9P40L6lyHvskOs%2FzhPfjjuTJ2f43Dj7tU2NDKk27tII2zKcEznG%2FiojLgapQxWTrH5yxVNo9Dusv6sHSQdkHasWnyX6W5TAeoS7Hvp6ViajGsusRxEClG%2BuDJWEmPz%2BkUYwDHcdFFXFcy98QlU37r6EL3NS0IAPqSY%2FUVaFRdpflMLO2YTjbLKFmHN2KbanzgMfLiG716VxGMEXTFNJsMdkdyrle%2BF1Q155cDfRVQKk4qCg%3D%3D%20agentid%3DACME%20ver%3D1%20crmethod%3D2
Server: Oracle-Application-Server-11g
Set-Cookie: OAMAuthnHintCookie=0@1410523439; httponly; path=/; domain=.melander.us
Set-Cookie: OAMRequestContext_acme.melander.us:80_696f34=io4lVtGlkrIosz2NHpKjEA==;max-age=300; httponly; path=/

The main reason for the redirect to the DCC WebGate is because the authentication scheme is configured for DCC.  Refer to the graphic below that shows side-by-side screenshots of a DCC authentication scheme (On the Left), and an ECC Authentication Scheme (Default LDAPScheme On the Right).  Notice the differences between the Challenge Redirect URL and Challenge URL?  In the DCC Authentication scheme the Challenge Redirect URL points to the hostname where the DCC WebGate is located which could also be a Virtual hostname for a Load Balancer.  The Challenge URL for the DCCAuthnScheme points to the location of the out-of-the-box login.pl.

DCC vs ECC Authentication SchemeSEQ 3 – Set DCCCtxCookie and redirect to login page

In sequence 3 this is where things get a little more interesting.  In the HTTP trace a new type of cookie is created, this is the DCCCtxCookie cookie.  In my trace the DCCCtxCookie is set for the sso.melander.us domain; the DCC WebGate host configured in the DCC Authentication Scheme.   The DCC WebGate looks for a DCCCtxCookie and if not present will generate one.  The DCCCtxCookie is basically used by the DCC WebGate to save context information during authentication.   More details on this cookie can be found in section 15.6.2.5 DCCCtxCookie of the OAM Administration Guide 11gR2 release.   Something else that shows up in the HTTP trace is a resource_url query string parameter that contains the last requested URL. This lets the DCC WebGate know where to redirect the browser after successful authentication.

HTTP/1.1 302 Found
Connection: Keep-Alive
Content-Length: 277
Content-Type: text/html; charset=iso-8859-1
Date: Fri, 12 Sep 2014 12:03:18 GMT
Keep-Alive: timeout=5, max=100
Location: /oamsso-bin/login.pl?resource_url=http%3A%2F%2Facme.melander.us%2F
Server: Oracle-Application-Server-11g
Set-Cookie: DCCCtxCookie_sso.melander.us:80=encdata%3DEKHXNSVKumgJQBImv1RLbxh8kT8E23bIKJeEmH87GvOrWLXD6YLv8adLGuGA%2FymjsB03bbu45t3%2FBJl17Xc5nBAHAsGt%2BoFbzTwwNRXvMI2TyAiKYFPI3gDXKjeA9SabxjC2UpDJe0DQ6yD0xwaezuoDZiLUbrMKe6B0otlfjvayuxK0yqDReA8F3pE6nNElH2Ln31hKt1W2dHKI%2BPzEJW8bdcYzCNLZ%2BPxGBTj%2FdN6E8uV32Yp8C%2BZemDusLFpFt6RhQdQheZUFRTyvYKPsralO3UGmFPW9T7r5Weo3nxU%3D; httponly; path=/oam/server/auth_cred_submit

SEQ 4 – Submit Credentials

This sequence is where the login page submits the username and password.  There are some very important points to know here.

  1. 1) In this example my authentication scheme is very simple; I only require a username and password.  In the POST you would see the username and password input fields along with the actual values.  Normally using ECC you would also post the OAM_REQ or request_id.  However if the DCC Authentication Scheme was setup to do multi step authentication, the OAM_REQ would actually show up and it would also be required at the time of posting the credentails.
  2. 2) Notice that the credentials are directly posted at the DCC WebGate host? This is quite different than ECC where the post is sent directly to the OAM Servers. The DCC WebGate becomes the credential collector; hence the name Detached Credential Collector. Also notice that the URI that is posted is /oam/server/auth_cred_submit, which is the same as ECC – the major difference is that this URI is served to the DCC WebGate, rather than the OAM Server.

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store
Connection: Keep-Alive
Content-Language: en
Content-Type: text/html; charset=UTF-8
Date: Fri, 12 Sep 2014 12:03:18 GMT
Expires: 0
Generated-By: login.pl
Keep-Alive: timeout=5, max=99
Pragma: no-cache
Server: Oracle-Application-Server-11g
Transfer-Encoding: chunked

POST /oam/server/auth_cred_submit HTTP/1.1
Host: sso.melander.us
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip,deflate
Accept-Language: en-US,en;q=0.8
Content-Type: application/x-www-form-urlencoded
Cookie: DCCCtxCookie_sso.melander.us:80=encdata%3DEKHXNSVKumgJQBImv1RLbxh8kT8E23bIKJeEmH87GvOrWLXD6YLv8adLGuGA%2FymjsB03bbu45t3%2FBJl17Xc5nBAHAsGt%2BoFbzTwwNRXvMI2TyAiKYFPI3gDXKjeA9SabxjC2UpDJe0DQ6yD0xwaezuoDZiLUbrMKe6B0otlfjvayuxK0yqDReA8F3pE6nNElH2Ln31hKt1W2dHKI%2BPzEJW8bdcYzCNLZ%2BPxGBTj%2FdN6E8uV32Yp8C%2BZemDusLFpFt6RhQdQheZUFRTyvYKPsralO3UGmFPW9T7r5Weo3nxU%3D; OAMAuthnHintCookie=0@1410523439
Origin: http://sso.melander.us

SEQ 5 & 6 – OAM Server evaluates the Credentials

In these two sequences the DCC WebGate sends the credentials to the OAM Server over OAP on port 5575 and you can see in the following OAM diagnostic trace log the authentication is successful.  The success is sent back to the DCC WebGate so it can continue to finish setting the next cookie and redirecting the browser back to its original requested URL.

[2014-09-12T12:04:00.488-04:00] [oam_server1] [TRACE] [OAMSSA-20097] [oracle.oam.user.identity.provider] [tid: [ACTIVE].ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)'] [userId: <anonymous>] [ecid: 4228756130348ab3:7de41016:1487a914541:-8000-0000000000003cd0,0] [APP: oam_server#11.1.2.0.0] [SRC_CLASS: oracle.security.am.engines.common.identity.provider.impl.ids.IDSUserProviderImpl] [SRC_METHOD: authenticateUserByName] User abarnes in idstore OUDIdStore authenticated successfully

 SEQ 7 – Now Redirect back and include the Session Token

In this sequence the DCC WebGate sends a HTTP 302 back to the originally requested URL, http://acme.melander.us, but also notice it includes the obrar.cgi?encreply= value.  The obrar.cgi contains the encrypted session token which we will need when we get back to the acme.melander.us Resource WebGate.

HTTP/1.1 302 Found
Connection: Keep-Alive
Content-Length: 1194
Content-Type: text/html; charset=iso-8859-1
Date: Fri, 12 Sep 2014 12:03:21 GMT
Keep-Alive: timeout=5, max=98
Location: http://acme.melander.us/obrar.cgi?encreply=n8OSU11hQvFoB44j/eb8hUbwsopUla62fbjmZtMP8J+fSQTJsyOLfHZnSjul4Z+kj08e5xiYARwuk4RwtIW7Hbj5/SgeUoPo62EtEiKLgmE76OQUFo3hRzSdhwG0w/fEAvLOSSjMrn7CB/hIIips27FksoQTbIrtt1aQ54mFsXRrViQSleRlQcVhHFCMo5nDhljHEH/IYVkaXzFEB8PwkoosKs7G7doqSlFgubxAYYID+6ZfxyLYpzWbNsRLBgMWqMe6pKnDQ2Bq1jPHdy1F6Ye8gMdfSzKHKVfeY2Y9RnBmV+jEeAS2yDevuIOP3/18jTAcfHYtS7rZvaZApFb3AYrwWNGeL1aY7SxLvEZWK7kdIZfqifwxjWZHHp9PMIQ2KfmR5ij9ovi8W+k72TN9uJDLZV/iWvJHiRKR84HMGjjj/QwNkgygtxslILimy8Qqfcpt5lECT3nbdTTsF82hzZnxCvCA1cP3SaVHjR8dQCiS4np1rr//bxgyAwX7gxnLJt7OBB9QbUcasfOoH1uIp5zcPYamTyIrqX64YEzXtGk2eIJl6KWbeV7xsWbs31U4B09HawJa420hveUO0wKdEmTKMZIYBggsRHN7rVyovIUf6fp/rat8n2rqsdb5nlLAAEI7GxfXi0G206iEK+7vZ1inioY9YPLa+TocaGJe7/fgDGkk3Wsxj6cidIAyRVLi5Dy2OdZ6tSKfpaH6Y7iJptFKrdkoRGoeELYOANIzSRyW/wi+9C/DIvwypgnHfuv5/BpPAEnm2jHBwkS4ZPQFNw00t2H4nxv1x115j6ToDa0PJaqwsUwOFUE4GCyGshD/42BlqF3Ycnbsgeie5VJ2xNCMg+p2h3gwD9tExJCa1jNo3dn7h2yAKLTMq4vc7MyOUMfCjDDu3JILOM3epT51OFkGRRqAyfx/vZbHdbLe1CM=
Server: Oracle-Application-Server-11g
Set-Cookie: OAMAuthnCookie_sso.melander.us:80=XiuQpggJbUzLaMtekqbd8HH6jtIcoNDmrzCkMBO0pf6SN3I1Pfnh8kfkzDAV3CHAMvcfjBZmAZLcef1G5tmTk51Nv664AO4mxKR9SCk07nCMPZdnUkZJldEL%2FP3N%2B18Ms3pZS%2Bm9kERpFCbBKCJf19%2FXjXWf%2B5VyLFOO3P88pHD6Rwcklfbcw6s2Oq5RR32UFZcpfVS79EWv8wocT4isczlTv5QkAVF0SpDocuEzhPE52GAxOSz%2Fjew5Q2pStKCF%2BA%2ByMR2pD2I3JFqAmt%2BZvxWlInEwOCCAC2RzMQzjPKvgy3EFv5iFLkd0ym1pXbkwR115I0lGQhRC9QM2vrQOyMd2Fmpmn%2BUpi9iT7juia0W5iJfd7MrpJPtebbNfBkTTnFJxGw5yVcecEOLPrGj1ubsNhtsKHwsP%2Bh18D4F6FsW2GoUx95X4NpxtG4MoORaYYGODr7roS7axEZSqBJzNRYBPZEMlPfz%2BQDxy3MicS6A%3D; httponly; path=/
Set-Cookie: DCCCtxCookie_sso.melander.us:80=;expires=thursday, 01-jan-1970 01:00:00 gmt; httponly; path=/

SEQ 8 – Set the OAMAuthnCookie for acme.melander.us

In this sequence the Resource WebGate for acme.melander.us gets the session token and then sets the OAMAuthnCookie for the acme.melander.us domain.  We now finally have SSO and the WebGate then grants the access to the content served up by the application server in sequence 9.

HTTP/1.1 302 Found
Connection: Keep-Alive
Content-Length: 212
Content-Type: text/html; charset=iso-8859-1
Date: Fri, 12 Sep 2014 12:04:02 GMT
Keep-Alive: timeout=5, max=99
Location: /
Server: Oracle-Application-Server-11g
Set-Cookie: OAMRequestContext_acme.melander.us:80_696f34=;expires=thursday, 01-jan-1970 01:00:00 gmt; httponly; path=/
Set-Cookie: OAMAuthnCookie_acme.melander.us:80=KeXCJKNeD4%2BKHMDKkBVFYrsZ94DcSb4JAbxuaCaUuvwoBDm3ljelAGlA30YsNi30IBGq4o8oRsTsTHkgity88Fl%2BvmSXHKCIhV5Ud0kyb3yErIWjjymaUWlbktnDhZaxvsq3we9viOESHKPCz6TZblUmLgnLbRxBLZmH0QvS32S5NexWSylBKlcHDBPOr78irmnE2S1Q1Bpp%2FmaFk6X3oE%2FP8LNRe0FVN4h7HNLz7q%2FUERIQbsulch8dsFdl2z97xWrz2PsUifvtlF5jG72xWLyaZbnRE8ERWxkotWD8wyDQha7xaBXIhWpOBnR5O5nRCvUUyzRTxE%2FnrNQRPucF%2F%2F9P2NaEazAEXWfAzf1cWKQ8GC1gjG%2BzN7E0BroGEPwaQ4EOI66mSbAA%2BVJ7QWvkIQt%2F7FHSbQGHFizqjC%2FJiueFRU6mFsO%2FwYUQ%2B6TeYzqoXZ03Xe%2F07ru5%2BBrdGbRzFoitRFCSwrFMtP0O5wm%2BGZQ%3D; httponly; path=/

 

Keep that Session Going with Multi-Domain SSO

Let’s keep going using the SSO Session and try to request globex.idfocus.com, which also is using the same DCC Authentication Scheme.  So using the same sequence diagram we can continue our learning.

SEQ 10 – Request globex.idfocus.com application

Much like sequence 1, this sequence is just a GET for the globex.idfocus.com.  No frills or thrills in the HTTP trace below, just as expected.

GET / HTTP/1.1
Host: globex.idfocus.com
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8

SEQ 11 – Encrypt and send the session token to the DCC WebGate

In this sequence something familiar happens just like in any multi-domain SSO configuration with OAM.  The Resource WebGate for domain globex.idfocus.com does not have a valid session yet to satisfy authentication, so similar to sequence 2 it redirects the browser back to the DCC WebGate at sso.melander.us for authentication and includes the original requested URL and some other information encrypted in the encquery parameter value as seen below in the HTTP trace.

HTTP/1.1 302 Found
Connection: Keep-Alive
Content-Length: 623
Content-Type: text/html; charset=iso-8859-1
Date: Fri, 12 Sep 2014 12:04:05 GMT
Keep-Alive: timeout=5, max=100
Location: http://sso.melander.us/obrareq.cgi?encquery%3DR9T1bzgn2ARi3h9h6fS4x0brZ2JTAeoaEy7uzqo5YA%2FGai0y%2B4xpJ%2B1%2BoqVxziO1YZ2jFd9IHLeEBmJkasL5GG4Yw1B%2FIzR%2Fzahx4FV3pbntKMYL%2BdfHxsIgrf1MCUTwrMsL8zuzmXUgj6SwuzeFOF606C6SlNoGehhgXnRhD88zvXnMsdnvCnaGy7Q%2F8W5SNQf8QHt9zN2wzMVhQn%2BGvGexLAwclWZthZbKgpUbMsnQ5tpTTtua%2B0dYt2XuhYn5q09ihY3gozRoTGyTY3riS7DzjMPiwr9TK4SMgdMJv6U%3D%20agentid%3DGLOBEX%20ver%3D1%20crmethod%3D2
Server: Oracle-Application-Server-11g
Set-Cookie: OAMAuthnHintCookie=0@1410523445; httponly; path=/; domain=.idfocus.com
Set-Cookie: OAMRequestContext_globex.idfocus.com:80_783376=x3vA+i4lAGQmfHXaX0XW6A==;max-age=300; httponly; path=/

SEQ 12 – Encrypt and Send the Session Token back to globex.idfocus.com

In sequence 11 we saw some encrypted data and now the DCC WebGate intercepts it and determines that needs to now encrypt the token in the obrar.cgi encreply parameter string, which is basically the authentication response from the 11g WebGate.

HTTP/1.1 302 Found
Connection: Keep-Alive
Content-Length: 1202
Content-Type: text/html; charset=iso-8859-1
Date: Fri, 12 Sep 2014 12:03:24 GMT
Keep-Alive: timeout=5, max=97
Location: http://globex.idfocus.com/obrar.cgi?encreply=vQrCrUuQgsRYwGM3ttT22vAsZ6S1aYVO2oqKEgmd+WDJV8heYYJ8BSWMFxYarlUE+ku2+dFzgoTka6YFkTN7k2Cksc7jbL/WPOJSH9kv15y/HrJ2TUeQZzsvxKgQ+QbTpQLWqA4RuUAssgF3BhSvpeE9SNYTIdmMWl7cnk2iykuH2nwqbfmHTeFnazby8ueaNghwSMabgaLQWQCGwkYQc1WFOGa46SPPJHH6mmf1RUZFXdKPaEsBRuD9gf/rJ8mSCjTXbzRax/dM825r53yno5l3claGFY4BTTVPLtcfQpT5ihwbAIJZNGZZp60jdK9NlpIwXlW9USLDwlAJKqvAtMvJApeb1e2kfqdWk3l88p4FHfJAUD/EwjQJW/oESYVbIoPWr4p82FueprzqZnQcUO8SUovFzgjWh/2OaV4XXdzXwLFzkC7iVQLFxUpBwyC7jILDk5wHoCVuJgpAmwIawIo/BCmkcInFiem9UbpyezqhPVvf6vO1k6exG3htluiXFCO0FhmU+LuSjlR0ajX0Esp91YB4uZMpAR0JBA+aEcICkQNFKl/gveIAxBx9RbIdBRHwzwROOxn0NWr2mRxhvkcEKIoqk05ygethfLx7n5vENk6bhU2PJGsEP8EmPVV0XLuy00z58NpWN2x6XvVlUKE2sMu8jTmr3X8IOTFAgJcbWYP+JxOmXh2thhmlarFAShAiUqT1AXmKcAoHLx+Z/X+2ZQbAGbJtWhtAOWzd8oqj2QiN97M3s4I6ifC38cQ7GaJ9hG0g5Q7/Ton8Be87G+cerTNHZ5ZnYSSpVtyhcOIyCqafSf4C4pkmusNSRA9KVnkbcUeSHud/1AGAAipCMxur8FUR9JqLFdEiThlM4ZqUtecb21YAHz2v07qLzArjUisOrw1wU2mEqVwwQxaiZoQST/97jJc35qi54Vpgqfo=
Server: Oracle-Application-Server-11g

SEQ 13 – Resource WebGate globex.idfocus.com sets OAMAuthnCookie

The browser gets a HTTP 302 to go back to http://globex.idfocus.com/ and when the Resource WebGate gets the encrypted token it validates that this is a valid session.  At this point an OAMAuthnCookie for globex.idfocus.com is generated and now the browser has a token set for both globex.idfocus.com and acme.melander.us.  So the browser is never challenged a second time.  Surprisingly this functionality is nothing special to do with DCC, it is a normal way that the 11g WebGates work together in a multi-domain SSO fashion.  But I wanted to point this out so that there are misconceptions that DCC is special in this regard.

HTTP/1.1 302 Found
Connection: Keep-Alive
Content-Length: 212
Content-Type: text/html; charset=iso-8859-1
Date: Fri, 12 Sep 2014 12:04:05 GMT
Keep-Alive: timeout=5, max=99
Location: /
Server: Oracle-Application-Server-11g
Set-Cookie: OAMRequestContext_globex.idfocus.com:80_783376=;expires=thursday, 01-jan-1970 01:00:00 gmt; httponly; path=/
Set-Cookie: OAMAuthnCookie_globex.idfocus.com:80=vh4qf6d43e5MU0UVWdzO%2BZ43786Zl1C%2F3kHaW6XM%2Bz%2BrLD%2F%2FKC4sJQdZZYLcrcM7WnYjZCQFRqM5YvGypLkxDyQMuFxdQcrltEseZC1FNErkGHaL5HDR8FJxxf%2B3KP5XPL6z882pWt2P4IaHe3V630%2BaHePEabNeL%2BtU6VD5hgFXPxJRo9tM6FZB%2BRy47QkWhBqqWlI1opTk8r71M8q5mi7tG3VeayG1eT1nj1FjGC1dRn0Py280pMQf9BR6WKKW5De%2BblW0PE3b4aa%2BWuC2Dxc1hzzjTQzIbuaxTsaGIGoY13Ri2uxwY%2BMvhTk0rMtl9u2QSmJwX4cmwKRdvM47wRCxvZ%2BaMTU8UhcdIOZWHh4S2A77jwMr2507SYdPXOwXMUwksSlF4WyjIQSkksmhr3ZbMVYMxP3QLfFwqN19Q05OT8ZM1lNtYF3L%2FPD3orcwBb9OjJ%2FiMsfhSUZsfNB9ngaFBrNbR49FI2HkLgVPW9g%3D; httponly; path=/

Let’s exit this party with multi-domain Logout

The reason I dragged you through sequence 13 where we got to http://globex.idfocus.com/ via the SSO session is so I can get into the multi-domain logout.  A lot of focus seems to always be on the login, but I feel the logout is often forgotten because frankly —- it’s not as sexy.  I aim to change that.  Logout can also be a bit tricky and especially multi-domain logout.  In this section I want to continue with the same sequence diagram to close this article and give some important bits on this type of logout, but again in Part 2 I will get into more detail with the configuration needed to accomplish it.

SEQ 15 – Request the logout.pl page to logout!

This sequence shows the browser sitting at the globex.idfocus.com domain and then requests a logout.  Logout is configured in the WebGate profile, which is fairly normal.  However with DCC the logout is a bit different and it requires some configuration on both the Resource WebGate and DCC WebGate profiles.   In addition the logout.pl has to be on the DCC WebGate and does some tricks of its own, more on that in sequence 17.   So in this HTTP trace you can see that the logout request is for the relative URL /sso/logout; this triggers the logout sequence and is the actual value found in the Logout URL parameter of the Resource WebGate.  Then the end_url is the Logout Target URL parameter that holds the landing page the browser needs to go to after it has completed destroying all the session cookies and the session in OAM.

GET /sso/logout?end_url=http://sso.melander.us/sso/logout.html HTTP/1.1
Host: globex.idfocus.com
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Cookie: OAMAuthnCookie_globex.idfocus.com:80=vh4qf6d43e5MU0UVWdzO%2BZ43786Zl1C%2F3kHaW6XM%2Bz%2BrLD%2F%2FKC4sJQdZZYLcrcM7WnYjZCQFRqM5YvGypLkxDyQMuFxdQcrltEseZC1FNErkGHaL5HDR8FJxxf%2B3KP5XPL6z882pWt2P4IaHe3V630%2BaHePEabNeL%2BtU6VD5hgFXPxJRo9tM6FZB%2BRy47QkWhBqqWlI1opTk8r71M8q5mi7tG3VeayG1eT1nj1FjGC1dRn0Py280pMQf9BR6WKKW5De%2BblW0PE3b4aa%2BWuC2Dxc1hzzjTQzIbuaxTsaGIGoY13Ri2uxwY%2BMvhTk0rMtl9u2QSmJwX4cmwKRdvM47wRCxvZ%2BaMTU8UhcdIOZWHh4S2A77jwMr2507SYdPXOwXMUwksSlF4WyjIQSkksmhr3ZbMVYMxP3QLfFwqN19Q05OT8ZM1lNtYF3L%2FPD3orcwBb9OjJ%2FiMsfhSUZsfNB9ngaFBrNbR49FI2HkLgVPW9g%3D; OAMAuthnHintCookie=1; oam_cn=Anne-Louise Barnes; oam_email=abarnes@acme.com; oam_userid=abarnes
Referer: http://globex.identityfocus.com/

SEQ 16 – Process logout.pl to logout

This sequence shows the browser getting the HTTP 302 to redirect to the logout.pl page along with the URL encoded value for the end_url.  Notice the Expires -1, this is basically the Resource WebGate on globex.idfocus.com killing the session cookie for the OAMAuthnCookie_globex.idfocus.com.  However we are not over yet because we need to destroy the sessions for all the other domains, in this case acme.melander.us and globex.idfocus.com.

HTTP/1.1 302 Found
Cache-Control: no-cache, no-store
Connection: Keep-Alive
Content-Length: 311
Content-Type: text/html; charset=iso-8859-1
Date: Fri, 12 Sep 2014 12:04:08 GMT
Expires: -1
Keep-Alive: timeout=5, max=96
Location: http://sso.melander.us/oamsso-bin/logout.pl?end_url=http%3A%2F%2Fsso.melander.us%2Fsso%2Flogout.html
Pragma: no-cache
Server: Oracle-Application-Server-11g
Set-Cookie: OAMAuthnCookie_globex.idfocus.com:80=;expires=thursday, 01-jan-1970 01:00:00 gmt; httponly; path=/
Set-Cookie: OAMAuthnHintCookie=;expires=thursday, 01-jan-1970 01:00:00 gmt; httponly; path=/; domain=.identityfocus.com

SEQ 17 – Kill those OAM Login Sessions now!

This is in my opinion one of the most interesting sequences of them all.  That is the sequence that makes a call to /oam_logout_success.  This URI is triggered because of the Logout Callback URL configuration in the WebGate profile.  It is responsible for killing all the remaining OAM SSO sessions.  In fact to verify all one does is logout and make sure the oam_logout_success is called as I explained, and then go into the OAM Console and go into the Session Management tab to search for the Username.   Before logout you would see the account session and then after the logout it should disappear.   In Part 2 I will get into more detail on logout configuration and how to customize the logout.

HTTP/1.1 200 OK
Date: Fri, 12 Sep 2014 12:04:08 GMT
Server: Oracle-Application-Server-11g
Pragma: no-cache, no-cache
Expires: -1, 0
Cache-Control: no-cache, no-store, no-cache, no-store
Generated-By: login.pl
Set-Cookie: OAMAuthnHintCookie=;expires=thursday, 01-jan-1970 01:00:00 gmt; httponly; path=/; domain=.melander.us
Set-Cookie: OAMAuthnCookie_sso.melander.us:80=;expires=thursday, 01-jan-1970 01:00:00 gmt; httponly; path=/
Keep-Alive: timeout=5, max=96
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8
Content-Language: en
----------------------------------------------------------
http://acme.melander.us/oam_logout_success

SEQ 18 & 19 – Redirect to the logout landing page.

If you remember from sequence 15, there was an end_url, which basically was the parameter that held the value for where the browser will end up after the logout process is complete.  This value could be anything you want and in my case I decided to have it land at /sso/logout.html on the sso.melander.us DCC WebGate; just make sure this URL is unprotected or excluded in the policy.  So this ends the logout.

HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, no-cache, no-store
Connection: Keep-Alive
Content-Language: en
Content-Type: text/html; charset=UTF-8
Date: Fri, 12 Sep 2014 12:03:28 GMT
Expires: -1, 0
Generated-By: login.pl
Keep-Alive: timeout=5, max=96
Pragma: no-cache, no-cache
Server: Oracle-Application-Server-11g
Set-Cookie: OAMAuthnCookie_sso.melander.us:80=;expires=thursday, 01-jan-1970 01:00:00 gmt; httponly; path=/
Set-Cookie: OAMAuthnHintCookie=;expires=thursday, 01-jan-1970 01:00:00 gmt; httponly; path=/; domain=.melander.us
Transfer-Encoding: chunked

GET /sso/logout.html? HTTP/1.1
Host: sso.melander.us
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Referer: http://sso.melander.us/oamsso-bin/logout.pl?end_url=http%3A%2F%2Fsso.melander.us%2Fsso%2Flogout.html

What have we learned?

So what we have learned from the HTTP Traces is that both ECC and DCC submit credentials to the URI /oam/server/auth_cred_submit, but DCC submits those credentials directly to the DCC WebGate host.   The DCC WebGate creates its own unique DCCCtxCookie and all other Resource WebGates still create OAMAuthnCookie SSO tokens whether they are used for DCC or ECC scenarios.  At the end of the day the biggest difference we can gather is that DCC makes it easier to secure the OAM Server, as I mentioned earlier, because there is no point where requests from the browser are sent to the OAM Server and therefore mitigates any risk of exposing the Mid Tier in regard to OAM.   However logout is a bit different in regards that it has to run from the DCC WebGate and if you have a multi-domain SSO configuration like I had oam_logout_success is required to be configured and called by the logout.pl or possibly another way using a custom logout.  Until Part 2, I hope you have a little deeper understanding of what is going on under the covers of DCC.

OAM11g — The Redirect Infinite Loop

$
0
0

INTRODUCTION

This post is part of a larger series on Oracle Access Manager 11g called Oracle Access Manager Academy. An index to the entire series with links to each of the separate posts is available.

I recently was working on one of my virtual environments that had three servers, which included OAM 11gR2PS2, though this could happen with pretty much any version of OAM. It started with my browser requesting a protected resource, and I was presented with the login page as expected, but after logging in I was issued a HTTP 404 right at the page I wanted to get to. So I ran a HTTP Trace and realized it was in an infinite loop that abruptly stopped. I was able to quickly get this fixed, but I know for many this can be very puzzling because it is very difficult to determine what the problem is even though it is pretty simple. If this has ever happened to you let me explain what is going on, how to fix it, and how to prevent this behavior along with other problems that can be a result of the root cause.

MAIN ARTICLE

What is the root cause?

To get to the crux of it the root cause was that one of the system clocks of the OAM or the WebGate servers was out of sync. In my example one server was accidently on a different time zone, but this could very well happen if the clocks are out of sync by even a minute.

What is happening to cause this?

When the time is out of sync on a WebGate or OAM Server, the time stamp in the OAMAuthnCookie token is basically expired and thereby causes OAM to reject the token and redirect the browser back to the OAM server to get a new one, and again, and again, and again; hence the infinite loop.

How to Fix the Problem

This fix is pretty simple. All that is required is to reset all the dates and time on the WebGate and OAM Servers to make sure they are all in sync within 60 seconds. It may require restarting the web server for the WebGates or the OAM Servers, but it is fairly painless to solve.

But there is more…

When the system clocks are out of sync on any of the WebGate or OAM Servers other odd behavior can bubble up such as:

  • High CPU usage at both Webgate agent and OAM Server.
    User experiences a hang.  Agent keeps going back to Server to re-issue the token because the Agent issued by the token thinks it is invalid.  I.E. OAM 11g: Redirect Loop Between OAM and WebGate Instance (Doc ID 1335301.1)
  • Login failure.
    Errors are thrown in OAM logs when trying to authenticate.  Token is rejected because the OAM server rejects the time difference between the Agent and OAM Server.  I.E. [OAMSSA-20005] Error Thrown In OAM 11g When Attempting To Authenticate (Doc ID 1394157.1)
  • Webgate is unable to contact an Access Server OR Webgate initialization error.
    Part of the OAP protocol is to check the time differences between the Agent and OAM Access Server.  If time is outside of 60 seconds failures can start happening, which will fail logins and even shutdown access to resources being protected by the Webgate agents.  I.E.  OAM 11g: Webgate initialize error – apache2entry_web_gate.cpp:592 – The AccessGate is unable to contact any Access Servers. raw_code^301 (Doc ID 1471768.1)

How to prevent this problem

Setting up NTP (Network Time Protocol) on all the WebGate and OAM Servers is one way to ensure the clocks are all in sync. Even if you would setup OAM for MDC (Multi Data Center) syncing the clocks across the data centers is critical. You may think that there is some product defect, but actually OAM is doing its job to be certain a rogue user is not replaying an old token in order to try and get in. Basically part of the SSO token in the OAMAuthnCookie contains a time stamp and the WebGates and OAM Servers pay very close attention to this time stamp because if it gets something that seems to look like it is old, OAM will automatically reject it; hence all the symptoms I described.

 

Part 2: Custom Login and Logout with Detached Credential Collector (DCC)

$
0
0

INTRODUCTION

This post is part of a larger series on Oracle Access Manager 11g called Oracle Access Manager Academy. An index to the entire series with links to each of the separate posts is available.

In Part 1: Getting under the covers of Detached Credential Collector (DCC), I spent time talking about DCC in general and walked through a sequence diagram explaining what is happening with DCC, to try and explain how it works including contrasting it with ECC. So in this blog, Part 2, I want to expand into a more practical angle on the requirements of a totally custom login and logout. Creating a custom login and logout does not require the Perl scripts login.pl or logout.pl, though these are perfectly great options and can also be customized. If you do want to take the route of using the OAM out-of-the-box Perl scripts you can find more information about it and its implementation in the Oracle Developer Guide for OAM 11g (11.1.2) in section 4.4 Developing User the Detached Credential Collector or see Debasish Bhattacharya’s blog article Detached Credential Collector Configuration — OAM 11gR2. Moving forward, and as promised, I am going to guide you on how to create a totally custom login and logout using DCC without requiring any hardcore developer skills — I promise.

MAIN ARTICLE

Getting Started

To keep everything less confusing I am going to break out two main sections of this blog into the “Login” and “Logout”. I will provide enough detail for you to gain the knowledge of making a functional customized login and logout. The operative word is “functional”, which basically means I will show you the mechanics on how to make it work, but it is up to you to add the bling. Fair enough? So let’s get started.

How to Create a DCC Custom Login

Though DCC will work with several types of authentication schemes I want to keep everything simple so we can understand the basic concepts. Form Login is one of the most common types of authentication customers use, so this is a good one to cover. I want to cover a simple Custom Form Login authentication scheme, which coincidently is similar to an External Form Login authentication scheme. This should help understand the concepts and then give the foundation on how to expand into other authentication scheme options.

STEP 1: The DCC Custom Form Authentication Scheme Requirements

The foundation is to start with the authentication scheme itself. A good way to understand our authentication scheme for DCC is to compare how it is configured versus the OOTB (Out-Of-The-Box) ECC form authentication scheme. The table below compares the two authentication schemes and includes each parameter with some examples. I have highlighted DCC parameter values in red that stand out from ECC, so pay attention to the highlighted values; more details on the highlighted parameters coming up.

Table 1 – DCC Custom Form Authentication Scheme Comparison

Authn Parameter ECC Authn Scheme DCC Authn Scheme
Authentication Level 2 2
Challenge Method FORM FORM
Challenge Redirect URL  /oam/server https://dcc_hostname: port
e.g. https://sso.melander.us
Authentication Module <Select a Module> <Select a Module>
Challenge URL /pages/login.jsp  <Relative DCC Login Page URI>
e.g. /sso/login.html
Context Type  default  <select blank>
 Context Value  /oam  <Not Available>
 Challenge Parameters  <empty>   <empty>

 

As an additional visual aid I am including a screenshot of a DCC Custom Form Authentication Scheme from the OAM Console. You can compare the configuration in the screenshot to the table above to solidify how the scheme is defined and how it varies from a Form Login using ECC.

Figure 1 – Example DCC Custom Form Login Authentication Scheme
AuthnScheme_DCC

Getting into the details of DCC vs ECC Authentication Scheme differences

I wanted to expand a little more on the more critical parameters that I highlighted in red to understand why the values are set that way and how you may want to change some of them for your own needs.

Challenge Redirect URL

The Challenge Redirect URL must hold the URL that includes the hostname and port of the DCC WebGate. In a High Availability (HA) configuration, the hostname would be a virtual IP of the load balancer, and of course the load balancer would then send requests back to all the DCC WebGate hosts. In my example sso.melander.us is the hostname of my DCC WebGate, and therefore in my case the actual value for this parameter is https://sso.melander.us. This is a big contrast from ECC because with ECC the hostname dynamically comes from the Access Manager Settings > Load Balancing > OAM Server Host and OAM Server Port values. I have mentioned this before, but to recap the reason we send the browser to the hostname and port of the DCC WebGate is because 1) we need to get the DCCCtxCookie, and 2) the credentials need to be posted to the DCC WebGate either directly or through the load balancer virtual host as I mentioned.

Challenge URL

The Challenge URL will be the relative URI of the custom login page that is served up from the DCC WebGate. This is similar to how you would configure a custom external Form Login. I want to add that where the page is located is not as important as long as the URI goes through the DCC WebGate. For example the login page could be a JSP hosted on WebLogic, and the web tier OHS web server that has the DCC WebGate on it could be configured with the weblogic_module that points the URI back to the WebLogic application server. In my case I just used a simple static login.html page served up from the web tier OHS server. Basically what happens is the Challenge Redirect URL combines with the Challenge URL to point the browser to the login page. Using my example from the previous table values, the browser would be redirected to login at https://sso.melander.us/sso/login.html.

Context Type

DCC does not use this. This parameter tells OAM how to build the final URL after being redirected to the login page. Notice that with DCC, the selection is blank. This means that OAM will not do anything special to build the final URL except provide the original requested URL. If you refer to sequence 3 in my Part 1: Getting under the covers of Detached Credential Collector (DCC) notice that the URL is very clean on the final login destination, and only includes a single query string parameter “?resource_url=” which contains a URL encoded value of the original requested URL used to tell OAM where to send the browser back to its original requested HTTP resource after a successful login.

Context Value

DCC does not use this. Since nothing is selected for the Context Type, the authentication scheme will not even make this an available option.

Challenge Parameters

The Challenge Parameter field is to provide any required special credential input, but if this field is left blank, the default values for the login form minimally require username and password. In my authentication scheme I left this field blank, so the form login only included the minimum username and password as follows.

<input id="username" maxlength="25" name="username" type="text" />
<input id="password" name="password" type="password" />

STEP 2: The DCC Custom Login Form Page Requirements

Now that we have created the DCC authentication scheme, let’s create the DCC Form Login page.

Credential Input Fields

The credential input fields are actually similar to ECC in many ways. By default as mentioned earlier, username and password are minimally required if the Challenge Parameters field in the authentication scheme is left empty. However there are other special parameters options that can be used for various reasons. Please refer to the OAM Administration Guide for 11g Release 2 (11.1.2) section Table 16-22 User-Defined Challenge Parameters for Authentication Schemes, which lists a number of parameters, and some dedicated specifically to DCC like like “creds=” or “extracreds=”. However, in the context of this blog, I am keeping it simple (KISS — Keep It Simple Stupid) to mitigate complexity and confusion. So my input fields for the login page are simply username and password. The following is an example of the HTML source code of the credential input fields for a login form.

<input id="username" maxlength="25" name="username" type="text" />
<input id="password" name="password" type="password" />

OAM_REQ Hidden Field

The OAM_REQ stores the OAM Server state. I am sure for those that have created custom logins before the OAM_REQ parameter is already something familiar. DCC is not much different, but if your custom login only uses username and password, the WebGate will not return an OAM_REQ parameter at all and therefore you need not bother to submit this input with the credentials. However, if the custom DCC authentication uses a multi-step authentication, the OAM_REQ will show up and therefore the login page needs to handle the OAM_REQ parameter and submit it with the form in order for authentication to work properly. The value comes across as a header, so you will need some way to dynamically grab OAM_REQ header whether it be JSP, ASP, PHP, etc. Then once retrieved the input field should then be hidden, the value populated in the hidden input field, and then submitted with the other credentials. The following is an example source code to retrieve the OAM_REQ using Java Server Pages (JSP).

<input name="OAM_REQ" type="hidden" value=”<%= request.getHeader("OAM_REQ”) %>“>

Form Method

The form method is almost always POST. There may be cases where POST could be a GET, but from a security stand point POST is generally always used. My simple example uses the POST method. I mentioned this earlier, it is important that the form be submitted whether POST or GET to the DCC WebGate. This could either be directly to a single web server that has the DCC WebGate or the Load Balancer virtual host that sends the requests to the DCC WebGates, but the main point is the form has to be submitted to the DCC WebGate(s). The following is an example HTML source code of the form action. Maybe mention SSL here….

<form action="/oam/server/auth_cred_submit" method="post" name="form">

Form Action

The ACTION URI can be the default “/oam/server/auth_cred_submit”. This is exactly what an external custom form login uses. However if you do not want to use the default ACTION URI, there is a special parameter “action=” that is specifically designed for DCC that can be added in the “Challenge Parameters” field of the Authentication Scheme to change it; for more details on this parameter and others see the OAM Administration Guide for 11g Release 2 (11.1.2) section Table 16-22 User-Defined Challenge Parameters for Authentication Schemes. The following is an example of the HTML source code of the form action.

<form action="/oam/server/auth_cred_submit" method="post" name="form">

TempStateMode

Last but not least I want to mention a parameter named “TempStateMode”. This User-Defined parameter can be configured in the Authentication Scheme “Challenge Parameters” field. Oracle provides details on this parameter in the OAM Administration Guide for 11g Release 2 (11.1.2) section Table 16-22 User-Defined Challenge Parameters for Authentication Schemes. TempStateMode controls how the DCC stores the OAM server state, whether it is cookie or form depending on what serverRequestCacheType is configured. The serverRequestCacheType parameter is found in the oam-config.xml configuration file of the OAM Server. Basically the TempStateMode can tweak how the DCCCtxCookie stores the OAM Server state. The relevance of this parameter is in case the server state cookie value size explodes beyond its limit, which in that case the default value TempStateMode=form should prevent this. If this parameter is not set in the User Defined Parameters the default is “form” and should be fine for nearly every case.

Example Login Form

So to put it all together the following is an example JSP Login Form. Remember if you are doing a very simple login form that does not use multi-step authentication, you can exclude the input field OAM_REQ.

Code Example 1 – My Simple DCC Custom JSP Login Form

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head></head>
<body>
<h2> Enter your credentials </h2>
<form action="/oam/server/auth_cred_submit" method="post" name="form">
Username: <input name="username" type="text" maxlength="25">
Password: <input name="password" type="password">
<input name="OAM_REQ" type="hidden" value=”<%= request.getHeader("OAM_REQ”) %>“>
<input type="image" name="login" src="images/login.png" onclick="document.form.submit();"/>
</form>
</body>
</html>

 

STEP 3: Applying the Custom DCC Login Form

Now that the authentication scheme has been created, and the login page has been built, all that remains is to change the authentication scheme in the Application Domain and test it. So go into the OAM Console > open the Application Domain > Authentication Policy > Protected Resource Policy and change the authentication to the new DCC Authentication Scheme. Once changed give it a test to see if everything functionally works as expected.

If authentication it is not working please refer to my first blog on DCC, Part 1: Getting under the covers of Detached Credential Collector (DCC), and read through the sequence diagram to understand what should be happening. You may want to install or use some HTTP Trace on your browser to make sure you are getting the right cookies, redirected to the correct hosts, etc. Another troubleshooting tip is to set the WebGate oblog to TRACE along with setting the OAM Server module “oracle.oam.proxy.oam“ to TRACE.

This pretty much covers it for DCC login; it is fairly straightforward. I hope this helps understand the special needs of DCC Login. Now let’s continue to the logout, which is a bit more complicated. We need to make sure the login form is unprotected, too?

How to Create a DCC Custom Logout

The logout is often neglected because, well, it is not quite as sexy as single sign-on (SSO). In fact sometimes it can be even more complicated that the login. For example with multiple domains there are OAMAuthnCookies that need to be terminated, there could be backend application sessions that also need to be terminated, and don’t forget about session timeouts. If an application session ends before the OAM session, the user could experience a partial logout, which can create odd unwanted behavior. Unfortunately it is outside the scope of this article to answer all the logout nuisances and recommendations, so minimally I want to focus on the DCC logout requirements only.

There are two distinct types of WebGates in the context of this article, the DCC and the Resource WebGates. Each WebGate profile will require slightly different logout configurations. We already know about the “Allow Credential Collector Operations” option in the WebGate Agent profile to make it a DCC WebGate. However when it comes to logout there are also special considerations when it comes to a DCC WebGate. As a quick preview summary, the following table shows the difference between the DCC and Resource WebGate logout configurations.

Table 2 – DCC vs Resource WebGate Profile Logout Configuration

Agent Parameter DCC WebGate Resource WebGate
Logout URL e.g. /sso/signout.jsp /sso/logout
Logout Callback URL /oam_logout_success /oam_logout_success
Logout Redirect URL <dcc_host:port>/
e.g. https://sso.melander.us/sso/signout.jsp
Logout Target URL end_url end_url

 

As you can tell from the above table the DCC WebGate includes the URI of the logout page, /sso/signout.jsp, where as the Resource WebGate contains a different URI all together and actually not even a real location. Also the DCC WebGate does not even contain a value for the Logout Redirect URL where the Resource WebGate does, and points the absolute URL of the DCC Logout page. So let’s get into the differences and explain the configurations.

STEP 1: The DCC WebGate Agent Profile Logout Setting Requirements

The following table lists the parameters and values required for the DCC WebGate. I have provided important comments in, you guessed it, the “Comments” column. In the next step for the Resource WebGate Agent profile I will tie together how important the DCC WebGate Agent logout configurations are and why it is really important that the settings all be intelligently configured to work together and successfully make the logout work properly.

Table 3 – DCC Agent Profile Logout Configurations

Agent Parameter Agent Value Comments
Logout URL e.g. /sso/signout.jsp This should be the URI only that points directly to the logout page, which would be coming from the DCC WebGate host or Load Balancer virtual hostname.
Logout Callback URL /oam_logout_success Use this value. This is a constant value used to terminate all domain sessions.
Logout Redirect URL DCC does not use this. The purpose of the DCC WebGate is for central login and logout, so no value is required here; leave it empty.
Logout Target URL end_url OPTIONAL: This is a query string parameter, which can hold a URL to redirect the browser after the logout process is finished.

 

The following screenshot shows my DCC WebGate Agent profile.

Figure 2 – DCC WebGate Agent Profile

AgentProfile_DCC

STEP 2: The Resource WebGate Agent Profile Logout Setting Requirements

The Resource WebGate is all other WebGates that do not use the “Allow Credential Collector Operations” checked like with the DCC WebGate; this was mentioned in my Part 1: Getting under the covers of Detached Credential Collector (DCC) blog.  The following table lists the parameters and values required for each Resource WebGate.

 

Table 4 – Resource Agent Profile Logout Configurations

Agent Parameter Agent Value Comments
Logout URL /sso/logout This URI is not a real page, it is only used to trigger the logout process and terminate the OAMAuthnCookie for this WebGate.
Logout Callback URL /oam_logout_success Use this value.  This is a constant value used to terminate all domain sessions.
Logout Redirect URL <dcc_host:port>/<logout page>e.g. http://sso.melander.us/sso/signout.jsp The absolute URL to the same logout page set in the DCC WebGate profile Logout URL. The logout page URI must match exactly. This is where the browser will be sent after triggering the Resource WebGate Logout URL, i.e. /sso/logout.
Logout Target URL end_url OPTIONAL: This is a query string parameter, which can hold a URL to redirect the browser after the logout process is finished.

 

The following screenshot shows what my Resource WebGate Agent profile looks like.  Notice the Logout Redirect URL points directly to the same DCC WebGate Logout URL; e.g. the absolute URL is https:/sso.melander.us/sso/signout.jsp; this is important to understand how this works.

Figure 3 – Resource Agent Profile

AgentProfile_Resource

So for example the logout link is on the application page, the HREF link is really just the URI defined in the Resource WebGate Agent Logout URL, in my case it is “/sso/logout”.  When the user clicks on the logout link or button, the browser requests the relative URI “/sso/logout”.  The WebGate knows about this special URI, which triggers the logout process.  The Resource WebGate will then expire the OAMAuthnCookie for that domain, and next send the browser to the Logout Redirect URL https://sso.melander.us/sso/signout.jsp defined in the Resource WebGate Agent.  Once the browser lands on the logout page https://sso.melander.us/sso/signout.jsp, it also expires the OAMAuthnCookie for the DCC WebGate host.  However, if we have gone to multiple domains, the show is not over.  We still need to deal with all the other domain cookies to complete our logout because at this point we are only logged out of the DCC WebGate and the Resource WebGate domain we clicked the logout link or button from.  This is where the Logout Callback URL comes in, and I want to spend time talking about this next in its own section.

 

STEP 3: Using the Logout Callback URL to terminate remaining OAMAuthnCookies

Normally when using ECC, OAM automatically makes a call back to one of the OAMAuthnCookie domains with a special URI named “/oam_logout_success”; remember this value defined in the Logout Callback URL parameter of the WebGate profile?  When a logout process is requested using ECC, OAM begins to make callback requests to all the domains a browser accessed in the form of a HTTP request; e.g. request 1) http://app.domain1.com/oam_logout_success, request 2) http://app.domain2.com/oam_logout_success, and so forth until all the OAMAuthnCookie hosts are expired.  If this were not done, the browser would only be logged out of the current domain it clicked the logout from.

The DCC WebGate is unique because it puts all the interaction with the browser at the front end where normally with ECC the browser can have all this interaction with the OAM server to make all these callbacks to terminate the session.  So DCC does it a little differently.  Let’s take a look at a WireShark TCP trace taken from the DCC WebGate to better understand what is going on.

Figure 4  – WireShark Trace showing HTTP_OAM_LOGOUT_CALLBACK_URLS Header

WireShark Trace Header highlighted

The above WireShark trace was captured when using the out-of-the-box logout.pl configuration.  So what we find is during the logout using DCC there is a special HTTP Header called “HTTP_OAM_LOGOUT_CALLBACK_URLS“ that shows up at the point of accessing the logout.pl.  The header HTTP_OAM_LOGOUT_CALLBACK_URLS can hold multiple callback URLs that come from all the domains the browser has been to (see the highlight in yellow).  Notice the header value http://acme.melander.us/oam_logout_success?

In the next WireShark screenshot trace we see that the logout.pl uses this header to dynamically build an image tag and uses the Logout Callback URL from the header as the source of the image.  But WAIT, this is not really an image is it!! Cleverly even though this source is not an image, it forces the browser to load what it thinks is an image, but in reality makes the browser do a HTTP request to the Logout Callback URL, which ultimately expires the OAMAuthnCookie session for that domain.

Figure 5 – Dynamic Invisible Image Tag
WireShark Trace oam_logout_success

Notice there is only one image tag for the Logout Callback URL in the WireShark trace?  If the browser accessed multiple domains the OAM_LOGOUT_CALLBACK_URLS header would store a delimited list of Logout Callback URLs and the logout.pl is designed to iterate through them to build multiple image tags.   Making multiple HTTP requests using these invisible image tags expires all the OAMAuthnCookie domains; pretty clever right?

If there is a case where only one of which should be many Logout Callback URLs AKA Partners are not presented in the OAM_LOGOUT_CALLBACK_URLS header, the Partner logouts may not be complete.  Meaning, post DCC logout, the OAMAuthnCookies for the other domains may not get cleared.  However, not to worry, because on the server side these sessions get cleared as a result of the logout leaving the uncleared OAMAuthnCookies obsolete.  So if this happens the risk is low and the browser will ultimately be logged out.

How to Leverage the OAM_LOGOUT_CALLBACK_URLS Header

I spent all this time to help you understand the importance of the Logout Callback URL and how the logout.pl leverages the OAM_CALLBACK_URLS header so that I can now show you how to use this same trick to complete your logout successfully using a custom logout page.  So the question is, how do we take advantage of this magical OAM_LOGOUT_CALLBACK_URLS header?   There are four things;

1. Configure the Logout URL URI value in the DCC WebGate profile to point to the final logout page; e.g. /sso/signout.jsp.  This is very critical!!
2. Make sure the Logout Redirect URL value for the Resource WebGates point directly to the DCC WebGate host and Logout URL; e.g. https://sso.melander.us/sso/signout.jsp.  This is also very critical!!!
3. Based on #1 above, the header OAM_LOGOUT_CALLBACK_URLS we are looking for will show up the first time the browser hits the signout.jsp (Or whatever name you give the logout page), and will contain a list of all the absolute Logout Callback URL values like what we observed in the WireShark trace.
4. We will then leverage Java Server Pages to get the header and dynamically build the same clever invisible image tags in the logout page we saw the logout.pl script do in the WireShark trace.  You could also do this with PHP, ASPX, or some other dynamic web programing language.

 

To help kick start you, the following is an example Java Server Pages logout page to do the job.  So when you are redirected to the signout.jsp, it grabs the OAM_LOGOUT_CALLBACK_URLS header, iterates through the Logout Callback URLs, and dynamically inserts invisible image tags in the logout page.

Code Example 2 – Java Server Pages signout.jsp page

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<!-- COPYRIGHT (c) 2014 ORACLE A-TEAM -->
<!-- THIS SAMPLE CODE IS PROVIDED FOR EDUCATIONAL PURPOSES OR     -->
<!-- TO ASSIST YOUR DEVELOPMENT OR ADMINISTRATION EFFORTS AND     -->
<!-- PROVIDED "AS IS" AND IS NOT SUPPORTED BY ORACLE CORPORATION. -->
<%@ page contentType="text/html;charset=UTF-8"%>
<%@ page import="java.util.Enumeration" %>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <title>OAM DCC Logout</title>
  </head>
  <body>
       
    <h1 align="center">
      You have successfully logged out!
    </h1>
    <% 
    String imgBeg="<img border=\"0\" width=\"0\" height=\"0\" src=\"";
    String imgEnd="\"/>";
    Enumeration e = request.getHeaders("OAM_LOGOUT_CALLBACK_URLS");
    while (e.hasMoreElements()) {
        String headerVal = (String) e.nextElement();
        out.write(imgBeg+headerVal+imgEnd);
    }
    %>
  </body>
</html>

 

Based on the Java Server Pages signout.jsp page above, you can see in the figure below an example of what the HTML source output of the page would look like after it renders.  As the page loads the Logout Callback URL are requested, cleverly as invisible images, but despite not being a real image it makes the necessary HTTP request for each Logout Callback URL domain and completes the expiration of the remaining cookies — Nifty right?

Code Example 3 – HTML source output of the signout.jsp page

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<!-- COPYRIGHT (c) 2014 ORACLE A-TEAM --> 
<!-- THIS SAMPLE CODE IS PROVIDED FOR EDUCATIONAL PURPOSES OR     --> <!-- TO ASSIST YOUR DEVELOPMENT OR ADMINISTRATION EFFORTS AND     --> <!-- PROVIDED "AS IS" AND IS NOT SUPPORTED BY ORACLE CORPORATION. -->   <html>
   <head>
     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
     <title>OAM DCC Logout</title>
   </head>
   <body>
        
     <h1 align="center">
       You have successfully logged out!     </h1>
          
<img border="0" width="0" height="0" src="http://acme.melander.us/oam_logout_success"/>
   </body>
 </html>

Note if you are using Java Server Pages, you will need to configure your web server for the WebLogic module.  Of course if you are using some other dynamic web programming language, the same would apply per your choice of web technology.  In my example I modified the following Oracle HTTP Server (OHS) mod_wl_ohs.conf file though your configuration would be a little more robust to also include a cluster.

<IfModule weblogic_module>
      WebLogicHost weblogichost.com
      WebLogicPort 7001
      WLLogFile /tmp/weblogic.log
      MatchExpression *.jsp
</IfModule>

What if I don’t have a dynamic logout page to get the HTTP header?

Since the OAM_LOGOUT_CALLBACK_URLS does only show up on the server side, getting the header can present a big challenge if you don’t have some type of dynamic web language technology. If this is your situation and you don’t have a way to use a web technology like Java Server Pages (JSP), PHP Hypertext Preprocessor (PHP), Active Server Pages eXtension (ASPX) or something similar for any reason; not to worry, you can still get the logout job done, but at a cost.

Let’s say you know that you will only have two domains a browser will ever be accessing, say portal.acme.com and sales.oceanicair.com, then you can hard code the two invisible image tags in the page as follow.

Code Example 3 – Example HTML source output of a static logout page

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<!-- COPYRIGHT (c) 2014 ORACLE A-TEAM --> 
<!-- THIS SAMPLE CODE IS PROVIDED FOR EDUCATIONAL PURPOSES OR     --> <!-- TO ASSIST YOUR DEVELOPMENT OR ADMINISTRATION EFFORTS AND     --> <!-- PROVIDED "AS IS" AND IS NOT SUPPORTED BY ORACLE CORPORATION. -->   <html>
   <head>
     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
     <title>OAM DCC Logout</title>
   </head>
   <body>
        
     <h1 align="center">
       You have successfully logged out!     </h1>
          
<img border="0" width="0" height="0" src="http://portal.acme.com/oam_logout_success"/>
<img border="0" width="0" height="0" src="http://sales.oceanicair.com/oam_logout_success"/>

   </body>
 </html>

 

Let’s say you know that you will only have two domains a browser will ever be accessing, say portal.acme.com and sales.oceanicair.com, then you can hard code the two invisible image tags in the page as follow.

First, the bad news…each time a domain changes whether it be added, changed, or removed, you will need to update the logout page across all environments.  Something to keep in mind, if your WebGate preferred hostname is say “.acme.com”, then if you go to portal.acme.com and sales.acme.com, both are different OAMAuthnCookie domains, so a Logout Callback URL will be required for both.  The earlier approach would take care of this automatically, but the approach of hard coding the image tags in a static logout page as you can see will become unwieldy.  This approach can be error prone and additional administration overhead is required to manage changes each time one is made.  The good news, although not the most elegant method, it will get the job done and you can be sure your logout is successful from all domains.

 

WARNING: THE LOGOUT PAGE NAME IS IMPORTANT
If by any chance you use logout.jsp, this is a special logout page name that OAM looks for.  If the name of your logout page is logout.jsp, OAM will probably catch this,  and OAM will cough it up and act like the normal ECC logout process and send you to the default out-of-the-box logout page.  This is probably not what you would like to happen.  Therefore to be safe, use some other logout page name other than logout.jsp, and for insurance host it on some other application server other than the one OAM is using.  You may have noticed in my example I used signout.jsp.  In my example I happen to host my JSP on the same WebLogic server OAM was hosted, but in the AdminServer instance.  However, I only did this for development and experimentation.  I would recommend hosting the login and logout pages in either a completely different WebLogic instance or at minimum a different managed domain.

 

Summary

So now you have some idea of the requirements that encompass how to create a custom login and logout page that works with DCC.   For those that want to use the DCC feature, I hope this article alleviates the concern of thinking you are stuck using the Oracle OAM DCC Perl scripts, login.pl and logout.pl.  The Perl scripts are certainly a viable option, but I would think most customers are more oriented to creating their own customized branded login and logout pages.  Good luck!

Viewing all 41 articles
Browse latest View live