geronimo-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From David Jencks <>
Subject Re: [jetty-dev] Jetty Security refactoring for JASPI
Date Thu, 30 Oct 2008 07:39:16 GMT
Hi Jan,

On Oct 29, 2008, at 7:37 PM, Jan Bartel wrote:

> Hi David,
> I'm still snatching time to tiptoe further around the jaspi branch.
> A couple of thoughts to run by you:
> 1. UserIdentity and LoginService classnames. These are quasi analogous
>   to UserPrincipal and UserRealm (although the behaviour has been  
> refactored).
>   I'm wondering whether it might not be a good idea to retain the old
>   classnames, just so it might be easier for jetty users/developers
>   to ease into understanding the new security structures?

I'm not sure that keeping the old names would help anyone understand  
the new code, I rather think it would be confusing.  I'd really rather  
not call UserIdentity a Principal since it isn't a Principal and  
depending on the security handler implementation can contain rather  
different things.  The main point of introducing it was that in jetty  
integrations (Geronimo and from distant memory JBoss) the  
UserPrincipal was ridiculously overloaded to contain incredible  
amounts of non-principal information associated with the user's  
identity.  I think that instead it makes sense to have an object that  
supplies the UserPrincipal, plus whatever else the security system  
needs.  I don't have strong objection to calling the LoginService  
UserRealm but I think its going to be confusing and less informative  
since it doesn't have the non-login-service methods any more.

> 1a. Actually thinking about this, it will probably be quite  
> important for
>   Jetty users to be able to make a smooth transition over to a jaspi- 
> based
>   implementation. Do you think we can retain a UserRealm and a  
> UserPrincipal
>   with all their methods intact, but just "blend in" the jaspi-ness  
> with
>   some extra methods and some changed implementations of the  
> existing apis?

Maybe.  I think the new interfaces are a lot clearer and more  
descriptive for embedding jetty that the old ones.  I could look into  
writing adapters from UserIdentity to UserPrincipal and LoginService  
to UserRealm but I'm not entirely sure it will work.  In particular  
I'm not at all sure the non login-service methods on UserRealm could  
plausibly be called.

> 2. We allow a UserRealm to be explicitly set on a WebAppContext (well,
>   strictly speaking its  
> WebAppContext.getSecurityHandler().setUserRealm(UserRealm)).
>   I couldn't see specific support for that, only getting a list of
>   LoginServices from the Server instance. Should be easy enough to
>   put in though?

I'm not sure how my code is different, except the LoginService is  
final and set in the constructor of ServletCallbackHandler, around  
line 1042 of WebXmlConfiguration.  I don't recall changing this code  

> 3. With the JAAS stuff, which has its own set of callbacks it
>   uses to obtain info, we used a DefaultCallbackHandler to plug in
>   the right info, such as credentials, passwords, usernames and
>   also extra request parameters from the login. I notice you're using
>   an anonymous CallbackHandler instead to pass into the JAAS  
> LoginContext.
>   Is it possible to use the DefaultCallbackHandler instead? It  
> supports
>   a couple more callback types that some LoginModule implementations  
> may
>   depend on.

I could misunderstand the DefaultCallbackHandler but I think that the  
extensions to a user-password callback handler all involve extracting  
credentials from the request.  In the jaspi architecture this is the  
function of the auth module, not the password validation service.  A  
login module that fishes directly in the request ought to be  
refactored into a plain login module that just validates the  
credentials and an auth module that extracts the credentials from the  
message.  Despite all the weirdness in jaspi I think this is a good  
idea and worth enforcing.

I guess someone who really really wanted to preserve their login  
module could write a subclass of LoginCallback that dealt with request  
parameters, and a JAASLoginService subclass.  This would be made  
easier by factoring out the CallbackHandler creation in  
JAASLoginService into a protected method.   Looks like I left out some  
exception handling there too :-(  I'd rather not encourage this however.

> 4. Minor thing - is there a lot of value in the RunAsToken marker  
> interface
>   as opposed to just having a String? The roles and role mappings are
>   themselves just Strings, so I was wondering what the utility is?

This is an embedding thing also.  It's pretty unclear what run-as is  
actually supposed to mean and how things like supplying the identity  
for a web service client or other remote call is supposed to work. (If  
the web service is supposed to be called as the user, rather than the  
server's identity, and you are in a run-as role, what credentials does  
this run-as-role identity supply????)  In Geronimo we represent the  
run-as role by a Subject obtained by logging into a security realm.   
So, the geronimo run-as token has this Subject in it.  We might want  
to store a UserIdentity there instead..... anyway I don't think  
constraining the representation of the run-as identity is wise.

BTW remember that the current auth modules implementing BASIC/DIGEST/ 
FORM auth are more or less temporary until we more or less agree on  
the main interfaces, at which time I plan to rewrite them in more  
jetty-friendly form (also after apachecon :-)

Many thanks!
david jencks

> best regards
> Jan
> David Jencks wrote:
>> On Oct 16, 2008, at 11:59 PM, Jan Bartel wrote:
>>> Hi David,
>>> Firstly, let me genuflect in recognition of your extraordinary  
>>> efforts
>>> for a) reading the spec b) being able to make heads or tails of it  
>>> c)
>>> coming up with an implementation based on it!
>> :-D
>>> I'm surpressing the urge to have a bit of rant at yet another jcp  
>>> spec
>>> that is at the same time heavy on the verbiage and light on
>>> comprehensibility. Your email was way more informative
>>> than what 29 people managed to produce in the spec.
>>> Anyway, looking at the code in the jetty-7-jaspi branch, and I admit
>>> that so far I've only just had a cursory nosey around, where would
>>> we integrate the JAAS side of things? Implement a JAASLoginService?
>> see in modules/plus/jetty-plus
>> Not sure if it  is ideal, it's pretty much a simple modification of  
>> the
>> former JAASUserRealm
>>> I'll have a deeper look at the code and get back to you with more
>>> informed comments. This mail is to re-assure you that your post
>>> hasn't fallen into the void and that we are looking forward to
>>> integrating this into jetty-7 trunk!
>> The main thing to remember might be that the current  
>> implementations of
>> built-in security (FORM, BASIC, DIGEST etc) are in jaspi "modules"  
>> only
>> until we agree on the jetty api at which point I was thinking to  
>> convert
>> them back into more jetty specific code.  Of course if you decide you
>> really like jaspi.... :-)
>>> Jan
>>> PS I love this code-comment in ServletCallbackHandler:
>>> * Idiot class required by jaspi stupidity @#*($)#@&^)$@#&*$@
>> Several parts of the jaspi spec look to me as if they are sort of  
>> stuck
>> on at the end when someone realized it was incomplete, and the  
>> heavy use
>> of CallbackHandler for two way communication between the jaspi  
>> modules
>> and the container strikes me as one such point.
>> thanks
>> david jencks
>>> :)
>>> David Jencks wrote:
>>>> Greg and Jan were kind enough to create a branch for me to play  
>>>> around
>>>> with a JASPI (Java Authentication Service Provider Interface)
>>>> integration with jetty and its getting to a point where I'm  
>>>> willing to
>>>> talk about it.
>>>> Code is at
>>>> JASPI attempts to provide a uniform framework for messaging  
>>>> systems,
>>>> both client and server side, to plug in message authentication.   
>>>> On the
>>>> client you can add auth info to a request and validate auth info  
>>>> on a
>>>> response.  On the server you can validate auth info on a request  
>>>> and add
>>>> auth info to a response.  The auth code can conduct arbitrary  
>>>> message
>>>> exchanges to negotiate what info is needed and transmit the  
>>>> info.  I've
>>>> been working on the server side auth for jetty.
>>>> The actual spec jaspi interfaces are not 100% ideal for http and  
>>>> don't
>>>> allow stuff like lazy authentication for unsecured resources so  
>>>> I've
>>>> come up with interfaces similar in spirit to the jaspi ones.
>>>> I've also tried to rework the implementation so it is more  
>>>> friendly to
>>>> integration with other app servers with their own ideas about  
>>>> security
>>>> frameworks such as geronimo and in particular make jacc  
>>>> implementations
>>>> easier. I expect these changes will also simplify integration  
>>>> with e.g.
>>>> jboss and glassfish but I haven't seriously tried to verify this.
>>>> Currently all the authentication code (replacing the *Authenticator
>>>> classes) is implemented in terms of jaspi but I plan to change  
>>>> this soon
>>>> to use the jetty specific interfaces directly.
>>>> So.... lets follow a HttpServletRequest/Response pair on its voyage
>>>> through the security system...
>>>> ... it arrives at AbstractSecurityHandler.handle.  This is a  
>>>> template
>>>> method that runs through the following structure calling out to
>>>> subclasses and the authentication system:
>>>> 1. calls checkUserDataPermissions(pathInContext, base_request,
>>>> base_response, constraintInfo).  This checks the user data  
>>>> constraints,
>>>> basically that the request arrived over the right kind of  
>>>> connection
>>>> (http/https).  Two obvious implementations of this are the existing
>>>> jetty constraint based implementation or one based on JACC.
>>>> 2. calls isAuthMandatory(base_request, base_response,  
>>>> constraintInfo) to
>>>> determine if the request actually needs authentication.  If it  
>>>> does not
>>>> we can often delay authentication until a method relying on auth  
>>>> results
>>>> is called (such as getUserPrincipal or isUserInRole).  Again this  
>>>> can be
>>>> implemented using constraints or JACC.
>>>> 3. packs the request, response, and authManditory into a
>>>> JettyMessageInfo holder object which can also pass various auth  
>>>> info in
>>>> a map.
>>>> 4. delegates the authentication to the jaspi-like ServerAuthResult
>>>> authResult = serverAuthentication.validateRequest(messageInfo);
>>>> assuming we are not doing lazy auth, this will extract the  
>>>> credentials
>>>> from the request (possibly conducing a multi-message exchange  
>>>> with the
>>>> client to request the credentials) and validate them.
>>>> Validation can use a LoginService possibly provided to the
>>>> ServerAuthentication which could be JAAS, Hash, JDBC, etc etc.
>>>> Lazy auth results in returning a lazy result that only attempts
>>>> authentication when info is actually needed.  In this case no  
>>>> message
>>>> exchange with the client is possible.
>>>> <<<<<<<<<<<<<<<<<<<<
>>>> 5. Assuming that authentication succeeded (this includes the lazy  
>>>> case
>>>> where the request would be allowed even without authentication),  
>>>> we wrap
>>>> up the result in an identity delegate:
>>>>        UserIdentity userIdentity = newUserIdentity(authResult);
>>>>        base_request.setUserIdentity(userIdentity);
>>>> The UserIdentity is the delegate for run-as role implementation and
>>>> actually answering auth questions from the application program.   
>>>> This
>>>> allows app servers to handle run-as roles however they want.
>>>> 6. Assuming authentication is mandatory, now that we know the  
>>>> user, we
>>>> can find out if they are in the appropriate roles:
>>>> checkWebResourcePermissions(pathInContext, base_request,  
>>>> base_response,
>>>> constraintInfo, userIdentity)
>>>> 7. On success, we can actually handle the request:
>>>> getHandler().handle(pathInContext, messageInfo.getRequestMessage(),
>>>> messageInfo.getResponseMessage(), dispatch);
>>>> 8. Assuming no exceptions were thrown, we can now secure the  
>>>> response
>>>> (normally a no-op for http):
>>>> serverAuthentication.secureResponse(messageInfo, authResult);
>>>> -------------------------------------------
>>>> JASPI implementations
>>>> I wrote a fairly complete jaspi framework implementation for  
>>>> geronimo
>>>> (rather than the bits actually needed for http which I wrote for  
>>>> jetty)
>>>> and have a nearly-untested openid implementation.   This  
>>>> (theoretically)
>>>> lets you openid-enable your app by supplying an appropriate login  
>>>> page
>>>> and useing the openid auth module.
>>>> Theres also a glassfish implementation that I haven't looked at and
>>>> someone wrote a SPNEGO auth module that works with it.
>>>> --------------------------------------------
>>>> How does this differ from what's there now?
>>>> SecurityHandler:  AbstractSecurityHandler now just has the basic
>>>> workflow described about and delegates all actual work to either
>>>> subclasses (for authorization decisions and object creation) or the
>>>> authentication delegate.  This makes it easy to plug in alternate
>>>> implementations such as a JACC implementation for an EE server.
>>>> Authentication results and run-as roles:  Formerly these were  
>>>> either
>>>> directly set in the request (possibly using lazy evaluation, with  
>>>> code
>>>> again in Request) or stuffed into a Principal implementation via  
>>>> the
>>>> UserRealm.  This really overloaded the idea of a Principal for no
>>>> apparent reason and made integration into app servers slightly
>>>> convoluted.  This is replaced with a UserIdentity interface  
>>>> providing
>>>> separate access to the auth results (user principal) and role  
>>>> handling
>>>> (isUserInRole, and run-as handling).  Subclasses of
>>>> AbstractSecurityHandler can provide their own implementations of  
>>>> this
>>>> interface.  These typically delegate to implementations of
>>>> ServerAuthResult, which can handle lazy authentication if  
>>>> necessary.
>>>> UserRealm IMO glues together a lot of unrelated functions,  
>>>> primarily the
>>>> role handling code now in UserIdentity and the credential  
>>>> validation now
>>>> in LoginService.  Credential validation may not even be needed by  
>>>> the
>>>> server (e.g. openid).  If needed it's called from something that
>>>> extracts credentials from the request.  Implementations are going  
>>>> to do
>>>> something like look up the user in a file or table or delegate to  
>>>> JAAS.
>>>> On the other hand the role handling is called by jetty or by the
>>>> application and the implementation is done by the app server  
>>>> (jetty or
>>>> e.g. geronimo).  Aside from being related somehow to security,  
>>>> these are
>>>> totally unrelated concerns.
>>>> --------------------------------------------------
>>>> How does ServerAuthentication and LoginService relate to JASPI?
>>>> The JASPI interface similar to ServerAuthentication is
>>>> ServerAuthContext:
>>>>   void cleanSubject(MessageInfo messageInfo, Subject subject)  
>>>> throws
>>>> AuthException;
>>>>   AuthStatus secureResponse(MessageInfo messageInfo, Subject
>>>> serviceSubject) throws AuthException;
>>>>   AuthStatus validateRequest(MessageInfo messageInfo, Subject
>>>> clientSubject, Subject serviceSubject) throws AuthException;
>>>> The main difference is that ServerAuthentication packages all the
>>>> results into a ServerAuthResult object rather than modifying the
>>>> clientSubject directly and hiding user principal and group info  
>>>> in some
>>>> callback handers.  This lets ServerAuthentication support lazy  
>>>> auth.
>>>> As far as configuration goes. you get a ServerAuthContext by  
>>>> calling a
>>>> whole lotta methods on some other stuff.  or.... you can just  
>>>> create one
>>>> and stuff it into an adapter, JaspiServerAuthentication.   
>>>> Probably we
>>>> want to implement the built in auth methods as direct
>>>> ServerAuthentication implementations rather than the current
>>>> ServerAuthModule implementations (a ServerAuthContext is supposed  
>>>> to
>>>> delegate to one or more ServerAuthModules, which have the same
>>>> interface).
>>>> LoginService is a pretty straightforward way of asking for password
>>>> validation and getting some info back.  JASPI has a peculiar IMO  
>>>> system
>>>> based on Callbacks.  The container (jetty) supplies the auth  
>>>> context
>>>> with a CallbackHandler that enables bi-directional communication.
>>>> Callbacks providing services to the auth module:
>>>> PasswordValidationCallback: this lets the auth module ask for  
>>>> password
>>>> validation: this is the closest to LoginService.
>>>> CertStoreCallback, PrivateKeyCallback, SecretKeyCallback, and
>>>> TrustStoreCallback all let the auth module ask for certificate
>>>> services.  AFAICT these are mostly for securing response  
>>>> messages, which
>>>> is typically not done for http.
>>>> Callbacks letting the auth module pass info to the server:
>>>> CallerPrincipalCallback: supplies the caller principal so
>>>> getCallerPrincipal can return something.
>>>> GroupPrincipalCallback supplies "groups" the user may be in.  The
>>>> meaning here is rather undefined but can be mapped to roles in  
>>>> some way,
>>>> such as by assuming the groups and roles are the same.
>>>> The use of callbacks here still seems rather weird to me but may  
>>>> make
>>>> more sense in the context of other messaging systems: jaspi is  
>>>> supposed
>>>> to be applicable to all sorts of messaging, including ejb calls,  
>>>> jms,
>>>> web services, etc etc.
>>>> I've put the caller principal and groups into the ServerAuthResult
>>>> object where they can be accessed directly (although possibly  
>>>> determined
>>>> lazily).
>>>> --------------------------------------------------------------
>>>> Comments...
>>>> Right now it looks to me as if form auth needs to be non-lazy  
>>>> since part
>>>> of the message exchange involves a request to j_security_check  
>>>> which is
>>>> normally not a secured response.  Trying to evaluate auth for this
>>>> lazily doesn't work... you never get back to the original request.
>>>> I don't see how this implementation could be significantly  
>>>> simplified or
>>>> sped up.... I'm certainly willing to look at problems.
>>>> I've been discussing JACC with Greg for a long time now.  The  
>>>> only thing
>>>> I can see that is possible with constraint implementations that  
>>>> is not
>>>> possible with jacc is redirecting an http request to the  
>>>> "equivalent"
>>>> https request if a user data constraint is violated.  I'm curious  
>>>> about
>>>> whether this is something people want to do or usually set up.
>>>> Many thanks,
>>>> david jencks
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe from this list, please visit:
>>> -- 
>>> Jan Bartel, Webtide LLC | |
>>> ---------------------------------------------------------------------
>>> To unsubscribe from this list, please visit:
>> ---------------------------------------------------------------------
>> To unsubscribe from this list, please visit:
> -- 
> Jan Bartel, Webtide LLC | |

View raw message