[Freeipa-devel] session authentication URI issues

Simo Sorce simo at redhat.com
Thu Dec 22 20:25:10 UTC 2011


On Wed, 2011-12-21 at 14:07 -0500, John Dennis wrote:
> Introduction
> ============
> 
> On our last conference call I explained there were some lingering
> issues on our proposed session based authentication. It was hard to
> summarize the issues in a few sentences so I promised a write-up, here
> it is.
> 
> In addition to reviewing the issues below I will point out I am not an
> Apache guru, therefore it is possible I may have drawn an incorrect
> conclusion or failed to see a possible solution that an Apache expert
> would be aware of, please keep that in mind as you read the material
> and offer constructive corrections where appropriate. Of course
> general comments/questions are sought and welcomed.
>  
> 
> Overview
> ========
> 
> This describes how we currently authenticate and how we plan to
> improve authentication performance. First some definitions.
> 
> There are 4 major players:
> 
>   1. client
>   2. mod_auth_kerb (in Apache process)
>   3. wsgi handler (in IPA wsgi python process)
>   4. ds (directory server)

You have a major flaw right here.
We have 2 kind of clients.
The WebUI and the CLI commands.

The WebUI uses /ipa/ui and /ipa/json
The CLI uses only /ipa/xmlrpc

In your whole discussion below you should rethink /ipa/rpc as /ipa/json
because it looks to me you are only considering the WebUI client (that's
just fine).

> There are several resources:
> 
>   1. /ipa/ui (unprotected)
>   2. /ipa/xmlrpc (protected)
>   3. /ipa/json (protected)
>   4. ds (protected, wsgi acts as proxy)
> 
> Both /ipa/xmlrpc and /ipa/json are RPC URI's and are dispatched by our
> wsgi handler, both are nearly identical for this discussion so to
> simplify the discussion let's just use /ipa/rpc to mean any protected
> RPC resource.
> 
> Current Model
> =============
> 
> This describes how things work in our current system.
> 
>   1. Client requests /ipa/ui, this is unprotected, is static and
>      contains no sensitive information. Apache replies with html and
>      javascript. The javascript requests /ipa/rpc.
> 
>   2. Client sends post to /ipa/rpc.
> 
>   3. mod_auth_kerb is configured to protect /ipa/rpc, replies 401
>      authenticate negotiate.
> 
>   4. Client resends with credentials
> 
>   5. mod_auth_kerb validates credentials
> 
>      a. if invalid replies 403 access denied (stops here)
> 
>      b. if valid creates temporary ccache, adds KRB5CCNAME to request
>         headers 
> 
>   6. Request passed to wsgi handler
> 
>      a. validates request, KRB5CCNAME must be present, referrer, etc.
> 
>      b. ccache saved and used to bind to ds
> 
>      c. routes to specified RPC handler.
> 
>   7. wsgi handler replies to client
> 
> Proposed new session based optimization
> =======================================
> 
> The round trip negotiate and credential validation in steps 3,4,5 is
> expensive. This can be avoided if we can cache the client
> credentials. With client sessions we can store the client credentials
> in the session bound to the client.
> 
> A few notes about the session implementation.
> 
>   * based on session cookies, cookies must be enabled
> 
>   * session cookie is secure, only passed on secure connections, only
>     passed to our URL resource, never visible to client javascript
>     etc.
> 
>   * session cookie has a session id which is used by wsgi handler to
>     retrieve client session data from shared multi-process cache.
> 
> Changes to Apache's resource protection
> ---------------------------------------
> 
>   * /ipa/rpc is no longer protected by mod_auth_kerb. This is
>     necessary to avoid the negotiate expense in steps 3,4,5
>     above. Instead the /ipa/rpc resource will be protected in our wsgi
>     handler via the session cookie.
> 
>   * A new protected URI is introduced, /ipa/login. This resource
>     does no serve any data, it is used exclusively for authentication.
> 
> The new sequence is:
> 
>   1. Client requests /ipa/ui, this is unprotected. Apache replies with
>      html and javascript. The javascript requests /ipa/rpc.
> 
>   2. Client sends post to /ipa/rpc, which is unprotected.
> 
>   3. wsgi handler obtains session data from session cookie.
> 
>      a. if ccache is present in session data and is valid
> 
>         - request is further validated
> 
>         - ccache is established for bind to ds
> 
>         - request is routed to RPC handler
> 
>         - wsgi handler eventually replies to client
> 
>      b. if ccache is not present or not valid processing continues ...
> 
>   4. wsgi handler sends temporary redirect to protected /ipa/login
> 
>   5. client sends request to /ipa/login
> 
>   6. mod_auth_kerb replies 401 negotiate on /ipa/login
> 
>   7. client sends credentials to /ipa/login
> 
>   8. mod_auth_kerb validates credentials
> 
>      a. if valid
> 
>         - mod_auth_kerb permits access to /ipa/login. wsgi handler is
>           invoked and does the following:
>           
>           * establishes session for client
> 
>           * retrieves the ccache from KRB5CCNAME and stores it
> 
>           * sends temporary redirect back to /ipa/ui.
> 
>      a. if invalid
> 
>         - mod_auth_kerb sends 403 access denied (processing stops)
> 
>   9. client now requests /ipa/ipc again due to redirect from step 8
>      and includes session cookie. Processing repeats starting at step
>      3 and since the session data now contains a valid ccache step 3a
>      executes, a successful reply is sent to client.
> 
> Note: Web clients can start at the /ipa/login URI or the /ipa/ui URI,
> either one will work the same.

All fine so far.

> Problems to be solved
> =====================
> 
> We have added one new URI, /ipa/login which is essentially
> invisible. For web clients with cookies enabled nothing has changed
> other than better performance. However if cookies are disabled or if
> web clients such as curl or our command line tools are used to access
> the /ipa/rpc resource a problem occurs.

Only because you conflated /ipa/json and /ipa/xmlrpc, treat them as
separate things and it will be easier.

> The /ipa/rpc resource is no longer protected by Kerberos, it's
> protected
> by session data, access can only be granted by exchanging session data
> obtained through a sequence of request/reply interactions that need to
> follow redirects.

We can leave /ipa/xmlrpc mod_auth_kerb protected (while /ipa/json will
be unprotected) if we are not ready to make changes to the CLI tools.

> Ideally we would like access to the /ipa/rpc resource to be
> transparently accessible no matter if you're using sessions or
> straight Kerberos authentication. But this is impossible. Why?
> 
> The key to understanding the problem is the location where the various
> steps occur are distinct and do not interact with one another. Rather
> it is a series of linear sequential steps with no branching
> control. Let's examine this in more detail.
> 
>   1. mod_auth_kerb protection is on a file system resource, not a web
>      URI. This is because many URI's may map to a file system resource
>      (uniquely identified by a URL).
> 
>   2. authentication in Apache occurs after any translations on the
>      incoming URI, thus aliases and rewrites are fully processed to
>      obtain a file system resource.
> 
>   3. Once a file system resource is determined Apache then asks the
>      question is this file system resource protected, and if so checks
>      access and deny rules and invokes authentication. 
> 
>   4. The application of authentication to a file system resource is
>      never conditional, the authentication requirement is established
>      when Apache initializes and configures itself. The resource is
>      either protected or it's not, period.
> 
>   5. If our wsgi handler file system resource is protected by
>      mod_auth_kerb and we only will be invoked after the entire
>      negotiate process has been completed and succeeds. Thus any logic
>      in our wsgi handler cannot influence the authentication performed
>      by mod_auth_kerb because our wsgi handler handler runs only after
>      the entire mod_auth_kerb authentication has succeeded.
> 
> Point 5 above is critical to understand, the /ipa/rpc resource is
> either Kerberos protected or it's not. You can't have the situation
> where /ipa/rpc is not Kerberos protected if a valid ccache is in the
> session data but is Kerberos protected otherwise.

Can we have a symlink and have /ipa/json point to the actual wsgi
resource and /ipa/xmlrpc point to the symlink ?
Would this allow mod_auth_kerb to be configured in different ways for
the 2 ?

If not we'll have to change our CLI tools at the same time we make the
session work.
Is there a problem for curl to follow redirects ?

> Can we just have non session based clients point to /ipa/login?
> ---------------------------------------------------------------
> 
> At the moment this is not clear to me. The role of /ipa/login is to
> obtain credentials and store them in a client session cache and then
> redirect back the UI.
> 
> If we want /ipa/login to process RPC requests instead of setting up
> session data and redirecting then /ipa/login needs to know whether the
> request was the result of a failed authentication redirect or as an
> original request. It's possible there may be information in the
> request header (such as a referer) that could be used to distinguish
> between the two cases and to take conditional action (note this is
> occurring in the wsgi handler).
> 
> But what's the point? It's no longer transparently the same /ipa/rpc
> URI. The client need to know to use a different URI to access the RPC
> interface. It can't be the /ipa/rpc URI because of point 5 above.
> 
> Can mod_rewrite determine which authentication to use?
> ------------------------------------------------------
> 
> Is it possible to utilize mod_rewrite to examine the incoming request
> and direct it to either a Kerberos protected resource or a session
> protected resource depending on the contents of the request?
> 
> Doubtful. To decide which authentication to perform it is necessary to
> know if a session cookie is available. mod_rewrite give you access to
> the request headers but very limited abilty to parse them, it could be
> difficult to robustly inspect the cookie header components and
> conditionally operate on them.
> 
> mod_rewrite also has the abilility to call out to an external process,
> but it appears as only the URI is passed, not full information about
> the request, such as the headers.
> 
> It might be possible to construct something with mod_rewrite but it's
> not immediately obvious it can be done or be done robustly. Maybe this
> should be investigated further (any mod_rewrite gurus want to chime
> in?).
> 
> A possible simple solution
> --------------------------
> 
> Since a non session based client *must* know to use a different URI
> why overload the /ipa/login URI?
> 
> We would establish another URI specifically for Kerberos protected RPC
> resources, for example /ipa/krb/rpc. This would be used by curl and/or
> our command line tools exactly like /ipa/rpc is used today. The only
> change is a different URI.

Why can't we just keep /ipa/xmlrpc ? Why do you mix /ipa/json
and /ipa/xmlrpc and call them the same and then propose to split them
when they are separate from the start ?

> For web browsers the javascript would decide which RPC URI to use
> depending on whether cookies are enabled or not. For cookie enabled
> browsers /ipa/rpc would be used, when cookies are disabled
> /ipa/krb/rpc would be used instead.
> 
We can have different URIs once we change the CLI, to maintain
compatibility with old tools. But it would be the other way
around. /ipa/xmlrpc would be krb protected by default and then we
add /ipa/session/xmlrpc which is instead the session base one.

Please let me know what I am missing :)

Simo.

-- 
Simo Sorce * Red Hat, Inc * New York




More information about the Freeipa-devel mailing list