Tuesday, February 12, 2013

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

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

Note that the sequence flows 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.

Behind the realms and master keytab file store

Referring to the diagram, starting at flow 8, OAM will get the Kerberos ticket from the client.  Below is a OAM trace log where you can see the fully qualified userPrincipalName tim.melander@FOREST2.EXAMPLE.COM.   You will also notice where it starts with “sending token = a1 81 e6, etc.….”, this is where the Kerberos ticket begins that OAM will use in the step-by-step authentication process.

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
replay cache for tim.melander@FOREST2.EXAMPLE.COM is null.
object 0: 1360098290000/33
object 0: 1360098290000/33
>>> KrbApReq: authenticate succeed.
Krb5Context setting peerSeqNumber to: 1908483992
>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
Krb5Context setting mySeqNumber to: 454832921
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 e9 30 81 e6 a0 03 0a 01 00 a1 0b 06 09 2a 86 48 86 f7 12 01 02 02 a2 68 04 66 60 64 06 09 2a 86 48 86 f7 12 01 02 02 02 00 6f 55 30 53 a0 03 02 01 05 a1 03 02 01 0f a2 47 30 45 a0

Then in flow 9, OAM will refer to the /etc/krb5.conf file and iterate through the various realms defined inside the file; i.e. FOREST1.EXAMPLE.COM, FOREST2.EXAMPLE.COM, FOREST3.EXAMPLE.COM, and so on.  At the same time OAM will also look at the master.krb5.keytab file, which contains all the keytabs that map to each service principal in each respective KDC server.  As you can see in the below OAM trace log, OAM successfully finds the key service principal HTTP/oam.server.com@FOREST2.EXAMPLE.COM.  In most cases the logs may not show all the keytab service principals, but OAM is iterating through them to find a successful match.

>>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
>>> KrbAsRep cons in KrbAsReq.getReply HTTP/oam.server.com
Found key for HTTP/oam.server.com@FOREST2.EXAMPLE.COM(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 04 01 82 37 02 02 0a a2 82 04 e1 04 82 04 dd 60 82 04 d9 06 09 2a 86 48 86 f7 12 01 02 02 01 00 6e 82 04 c8 30 82 04 c4 a0 03 02 01 05 a1 03 02 01 0e a2 07 03 05 00 20 00 00 00 a3 82 03 e2 61 82 03 de 30 82 03 da a0 03

In Part 2 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 transient trust between them, either way this will work in all cases.
TIP:  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.

         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.

Searching for the Authenticated User in the Identity Store

Now that OAM has validated the Kerberos ticket, in flow 10 there are a few things that are happening.   The OAM Kerberos module gets the Principal from the Kerberos ticket; we can see this in the following example OAM trace log.  Notice the parameter Principal:, it contains the fully qualified userPrincipalName tim.melander@FOREST2.EXAMPLE.COM.

[2013-02-07T20:15:04.649-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@FOREST2.EXAMPLE.COM 

Next the OAM Kerberos module strips the @FOREST2.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.

[2013-02-07T20:15:04.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] 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, @FOREST2.EXAMPLE.COM, and builds a search base of “dc=forest2,dc=example,dc=com”.   Notice the parameter User Domain, it will hold the namespace OAM will use to build its search against OVD.

[2013-02-07T20:15:04.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=forest2,dc=example,dc=com

Now in flow 11, OAM builds its LDAP 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 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.

[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 After.30)[[
BindDN: cn=orcladmin
Base:   dc=FOREST2,dc=EXAMPLE,dc=COM
Scope:  2
Filter: (&(samaccountname=tim.melander)(objectclass=user))
TypesOnly:      FALSE
Attrs:  [mail, cn, description, orclguid, objectclass, displayname, uid, samaccountname]!

Next in the OVD diagnostic log we can see how the LDAP entry tim.melander is successfully returned along with any required attributes.

[2013-02-06T15:38:59.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_Forest4.Dump Before.30)[[ 
DN: CN=Tim Melander,CN=Users,DC=forest2,DC=example,DC=com 
displayName: Tim Melander 
cn: Tim Melander 
sAMAccountName: tim.melander 
objectClass: top 
objectClass: person 
objectClass: organizationalPerson 
objectClass: user

Then in flow 12 to 13 OAM after successfully authenticating and finding the user, it sets the proper OAMAuthnCookie for SSO.  Then finally OAM will 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.


I hope this will help you understand how the entire OAM WNA authentication process works from end-to-end.  I feel understanding the flow helps considerably when it comes to troubleshooting.  In Part 2: How to Configure OAM11g WNA for Multiple AD Forests of this series I will go into detail of how to configure OAM11g for the WNA integration to work with multiple domains whether they are trusted or untrusted, and I will also include tips on troubleshooting.

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.