Tuesday, August 17, 2010

Kerberos and WebLogic Server - decisions, decisions

I've been away from the blog for a while - I took some vacation time and I've been working on a customer that I can't really talk about. Have you missed me?

No? I didn't think so.

I got a call yesterday asking me to help a customer trying to get SPNEGO/Kerberos working between Windows desktops and WebLogic server. Yes, Kerberos again. After talking through what they're trying to accomplish today I found that they may have started out on the wrong foot to begin with.

Here's (more or less) what they told me they're trying to accomplish:
We have an app deployed in WebLogic and we want users that are in the domain to be able to access that app without being prompted for credentials.
That's it.

There are three ways that I can think of right away to address that requirement:
  1. Use WebLogic's SPNEGO Identity Asserter to have WebLogic verify the Kerberos ticket
  2. Use IIS to do the Kerberos bits and then use a simple HTTP header Identity Asserter to get the identity into WebLogic
  3. Use Oracle Access Manager
Each of the solutions have their own plusses and minuses. The point of this post is to try to get them written down to help you (or someone else) make a sensible decision about which one to pick.

Before I get into it let me just say that Kerberos/SPNEGO is one of those technologies that when it works it's awesome, and when it doesn't it's incredibly frustrating to figure out what's gone wrong. Add to the mix the fact that so much of what's happening is automatic and so few people actually understand what's really happening under the covers/on the wire and you have a recipe for pain, frustration, annoyance and lots of hair being pulled out.

With that said...

WLS + SPNEGO Identity Asserter
WebLogic includes an the necessary bits that allow WebLogic to verify a Kerberos ticket if you want. I've blogged about it before and there are official docs as well as oodles of threads on Oracle forums where people are struggling to get it working. It definitely works and it has gotten easier over the years, but it's still harder than flipping a switch and being done.

The requirements basically amount to getting a Kerberos service principal registered, getting the necessary secret key onto the box running WebLogic and then getting WebLogic and IE to agree to do SPNEGO. Each of those steps is manual and it's easy to make a mistake.

Plusses: baked into WebLogic so there are no dependencies on any other software, Kerberos ticket is verified inside WebLogic itself and is thus about as secure as possible.
Minuses: can be difficult to setup & troubleshoot

Use IIS to do the hard stuff

One of the great things about Microsoft embracing Kerberos is that some very difficult, very complicated things have been reduced to a checkbox. To enable Kerberos in IIS you add the web server to the domain, then you go into the IIS console, edit the Security properties of a directory or of the server and check one box - "Integrated Windows Authentication". Windows and IIS do all the hard stuff for you including setting up the Kerberos principal.

Yes, I'm glossing over a few things, but not many.

Once you've got IE and IIS doing the Kerberos/SPNEGO dance two things remain: (1) getting IIS to proxy requests over to WebLogic and (2) getting WebLogic to trust IIS' say so on the user's identity. The former is address by the IIS WebLogic Plug-in. The latter is a simple Identity Asserter like the one I discussed back in January (I really need to put that code up somewhere on the Internets!).

Plusses: One checkbox to enable Kerberos in IIS
Minuses: You have to deploy Windows & IIS in front of every WebLogic server. The security issues I mention in my older post


OAM provides two relevant things - SSO across web sites and access control to those web sites. The former is all we're interested in here; when a user accesses the web server OAM will detect that they haven't authenticated yet and kick them into a process to do that. The latter allows you to decide who gets access to what parts of the protected web sites; it's not something we care about in this case but it can be very useful.

The upside to using OAM in this case is that you only need one or two IIS web servers somewhere in your environment to get Kerberos working. Each of the OAM WebGates plugged into your protected web servers will redirect users to one of those machines to figure out who the user is and then back to the protected web server. This works regardless of which flavor of web server you use - OHS, Apache, IIS, or Sun One. I've seen customers do this sort of thing with as little as one IIS server, but for redundancy you want a pair of IIS boxes somewhere in your environment and probably a second pair in a disaster recovery environment as well.

Plusses: Few Windows/IIS servers needed.
Minuses: Requires additional software (OAM WebGate) to be installed

In this particular customer's case they'd tried the first option already and had run into some issues. Because of those issues and because their requirements were still in flux I suggested that they try the second option (IIS doing Kerberos along with a username Identity Asserter). Your mileage may vary and you should probably ask a knowledgable person for advice before picking one of these options, but that's (part of) what we're here for.

I'm interested in what you think. Let me know in the comments!


  1. I can have both mentioned solution working, but
    my customer are unable to be satisfied:

    1. Use WebLogic's SPNEGO Identity Asserter to have WebLogic verify the Kerberos ticket

    2. Use IIS to do the Kerberos bits and then use a simple HTTP header Identity Asserter to get the identity into WebLogic

    customer want windows 7 workstation authenticate with weblogic only, but there's IIS7 sit between workstation and weblogic. It means workstation can not talk to weblogic directly, it have to go through IIS WLS Plugin.

    I've tested the windows 7 workstation can do authentication with weblogic successfully by using kerberos (SPNEGO), no matter what sort of encryption types(rc4-hmac, aes256-cts etc). But it is failed with error "checksum failed" if workstation is calling WLS through IIS. I noticed that the value for WWW-Authorization: Negotiate header are quite big compare to the one when calling WLS directly. the Java side is failed to do verification.

    it seems IIS had added something to the WWW-Authorization header.

    My question is that is it possible to do kerberos authentication with the below architecture:
    workstation -> IIS(WLS plugin only, no authentication -> Weblogic (do kerberos authentication)

  2. Because of the way that IIS integrates with the domain it's unlikely that you could get that to work.

    The problem is that the users will go to the KDC and ask for a service ticket to talk to HTTP/iisservername and the WLS server won't be able to validate that service ticket. Why? Well because when you install IIS it registers the *machine* account on which the IIS server is running with the Kerberos service principal HTTP/iiservername. You could try to remove that mapping manually and add a mapping for the WLS server, but the next time there's a patch to Windows it might get added back.

    Have you considered doing the authentication in IIS and then using mutual (i.e. two way) SSL between IIS and WLS to secure that channel? Will that meet your customer's security requirements?

  3. I am trying for some time now to get a SSO scenario working : SAP Portal -- IIS with SSO22KERBMAP and Weblogic plugin -- Weblogic with OBIEE 11g.
    The SSO22KerbMap ISAPI module is based on the Windows 2003 Kerberos constrained delegation model. The account the target application is running on must be trusted to authenticate for delegation to a specified Service Principal Name (SPN).

    I managed to get the simple scenario working :
    browser -- SPNEGO Weblogic OBIEE 11g.
    But with IIS in between it is not working and keeps on returning http 401.

    Does this mean that the Weblogic SPNEGO provider is not supporting constrained delegated trust (s4u2proxy)?
    With Windows applications (eg Sharepoint) trust can be delegated from the IIS to another IIS where Sharepoint is running.

    An example configuration with the Hyperion application un Weblogic 9 tells that such a configuration should be working : http://www.oracle.com/technetwork/middleware/bi-foundation/epm-kerberos-wp-128207.pdf
    A simulation with a simple SSO test application proves the opposite.

    Am I missing something or can anyone confirm my findings?

  4. In a previous comment I thought the Weblogic SPNEGO module was not supporting Kerberos (constraint) trust delegation.
    Having compared a direct request and one that passes via the Weblogic plugin, I see that with the Weblogic plugin no Kerberos negiotiation is done and so there is no Kerberos logging at all.It seems I over estimated the Weblogic plugin.
    Again, am I missing some thing?

    Weblogic Log (no kerberos)
    <30-jun-2011 13.58 u. CEST>
    <30-jun-2011 13.58 u. CEST>
    <30-jun-2011 13.58 u. CEST>

    Weblogic plugin log (no negotiatie)
    SSL is not being used
    resolveRequest: request '/assotest/' has not been forwarded.
    SSL is not configured for this connection
    Local Port of the socket is 4641
    Remote Host obi01 Remote Port 8001
    URL::connect SSLConn for reader is not set as it is NULL
    general list: created a new connection to 'obi01'/8001 for '/assotest/', Local port: 0
    WLS info in sendRequest: obi01:8001 recycled? 0
    Hdrs from client:[Cache-Control]=[no-cache]
    ... (some skipped)
    Hdrs from client:[Host]=[moss02.indaver.int:91]
    Hdrs from client:[User-Agent]=[Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2; WOW64; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET

    CLR 3.5.30729)]
    Hdrs from client:[UA-CPU]=[x86]
    URL::parseHeaders: Value of parsedHeaders = [0]
    URL::sendHeaders(): meth='GET' file='/assotest/' protocol='HTTP/1.1'
    Hdrs to WLS: [Cache-Control]=[no-cache]
    Hdrs to WLS: [Accept]=[*/*]
    Hdrs to WLS: [Accept-Encoding]=[gzip, deflate]
    Hdrs to WLS: [Accept-Language]=[nl-be]
    Hdrs to WLS: [Cookie]=[JSESSIONID=lGxLTMSGFv21p0JLpyYyP1cXYLDwz1QDhhpTkcL0GGMfhxKgnNvt!-1283377856]
    Hdrs to WLS: [Host]=[moss02.indaver.int:91]
    Hdrs to WLS: [User-Agent]=[Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2; WOW64; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR

    Hdrs to WLS: [UA-CPU]=[x86]
    Hdrs to WLS: [Connection]=[Keep-Alive]
    Hdrs to WLS: [WL-Proxy-Client-IP]=[]
    Hdrs to WLS: [Proxy-Client-IP]=[]
    Hdrs to WLS: [X-Forwarded-For]=[]
    Hdrs to WLS: [WL-Proxy-Client-Keysize]=[]
    Hdrs to WLS: [WL-Proxy-Client-Secretkeysize]=[]
    Hdrs to WLS: [X-WebLogic-KeepAliveSecs]=[30]
    Hdrs to WLS: [X-WebLogic-Force-JVMID]=[unset]
    Hdrs to WLS: [WL-Proxy-SSL]=[false]
    Reader::fill(): first=0 last=0 toRead=4096
    Reader::fill(): sysRecv returned 330
    URL::parseHeaders: CompleteStatusLine set to [HTTP/1.1 401 Unauthorized]
    URL::parseHeaders: StatusLine set to [401 Unauthorized]
    Hdrs from WLS:[Date]=[Thu, 30 Jun 2011 11:58:33 GMT]
    Hdrs from WLS:[Content-Length]=[1518]
    Hdrs from WLS:[Content-Type]=[text/html; charset=UTF-8]
    Hdrs from WLS:[WWW-Authenticate]=[Negotiate]
    Hdrs from WLS:[X-WebLogic-JVMID]=[-1014147543]
    Hdrs from WLS:[Set-Cookie]=[JSESSIONID=vZD8TMkJhtgTzc6HpQTN5tTrChtgSpC1fnGDpQ2Lvw17yCpQNg7L!-1014147543; path=/; HttpOnly]
    Hdrs from WLS:[X-Powered-By]=[Servlet/2.5 JSP/2.1]
    parsed all headers OK
    sendResponse() : uref->getStatus() = '401'
    Going to send headers to the client. Status :401 Unauthorized
    Hdrs to client: [Content-Length]=[1518]
    Hdrs to client:[Content-Type]=[text/html; charset=UTF-8]
    Hdrs to client:[WWW-Authenticate]=[Negotiate]
    for obi01/8001/8001, updating JVMID: -1014147543
    Hdrs to client:[Set-Cookie]=[JSESSIONID=vZD8TMkJhtgTzc6HpQTN5tTrChtgSpC1fnGDpQ2Lvw17yCpQNg7L!-1014147543; path=/; HttpOnly]
    Hdrs to client:[X-Powered-By]=[Servlet/2.5 JSP/2.1]
    Content Length = 1518
    Reader::fill(): first=0 last=0 toRead=4096
    Reader::fill(): sysRecv returned 1518
    canRecycle: conn=1 status=401 isKA=1 clen=1518 isCTE=0
    closeConn: URL.canRecycle() returns false, deleting URL 'obi01/8001'
    request [/assotest/] processed successfully ..................

  5. Your issue is not the WL Plug-in or even WebLogic. It's basically impossible to get IIS and WebLogic to trust the same Kerberos token sent by the browser to IIS and then through the WL Plug-in to WLS.

    If you have IIS doing the Kerberos "stuff" then all you need to do in WLS is trust IIS' say so on the user's identity. This is described above in "Use IIS to do the hard stuff"

    Perhaps I'm not following what you're trying to do?


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