geronimo-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Jan Bartel <>
Subject Re: [jetty-dev] Jetty Security refactoring for JASPI
Date Fri, 31 Oct 2008 07:42:58 GMT
Hi David,

No, I'm referring to this code:

ConstraintSecurityHandler.checkUserDataPermissions line 235 and 259.

It is doing a redirect there to get the request to come in again on
the right connector (either the confidential or integral port as appropriate).


David Jencks wrote:
> On Oct 30, 2008, at 10:54 PM, Jan Bartel wrote:
>> Hi David,
>> I'll reply to your reply in a later posting. For now, I just noticed
>> something odd in the ConstraintSecurityHandler. If
>> checkUserDataPermissions()
>> notices the request was received on the wrong connector (ie on http
>> instead of
>> https) and does a redirect, the AbstractSecurityHandler.handle()
>> method goes
>> ahead and subjects the request to JASPI authentication. It seems to me
>> that
>> at that point we want to stop processing the request altogether. It will
>> be the redirected request that we're interested in processing further
>> (either doing the auth or doing a redirect to a login form).
> I think you are referring to this code?
>                 if (!checkUserDataPermissions(pathInContext,
> base_request, base_response, constraintInfo))
>                 {
>                     if (!base_request.isHandled())
>                     {
>                         response.sendError(Response.SC_FORBIDDEN);
>                         base_request.setHandled(true);
>                     }
>                     return;
>                 }
> I think there's something odd here, but IIUC something other than what
> you see.
> This is not proposing a redirect, it is plainly denying the request. 
> I've been worrying about this because it prevents redirecting http
> requests to the equivalent https requests.  Until recently I didn't
> think it was possible to do this redirect using jacc permissions but I
> think there is a solution....
> If the actual request is denied and is http we could create a new
> request with the url converted to https and checkUserDataPermissions on
> it.... if that check succeeds we can redirect to the more secure url. 
> This is somewhat analogous to the way we determine if authentication is
> mandatory, namely by doing a web resource permission check with the
> unauthenticated user.
> I might also have missed what you are looking at...
> thanks
> david jencks
>> cheers
>> Jan
>> David Jencks wrote:
>>> 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 much...
>>>> 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
>>>>>> 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.
>>>>>>> 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
>>>>>>> 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
>>>>>>> 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
>>>>>>> soon
>>>>>>> to use the jetty specific interfaces directly.
>>>>>>> So.... lets follow a HttpServletRequest/Response pair on its
>>>>>>> through the security system...
>>>>>>> ... it arrives at AbstractSecurityHandler.handle.  This is a
>>>>>>> template
>>>>>>> method that runs through the following structure calling out
>>>>>>> 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
>>>>>>> not
>>>>>>> we can often delay authentication until a method relying on auth
>>>>>>> results
>>>>>>> is called (such as getUserPrincipal or isUserInRole).  Again
>>>>>>> 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
>>>>>>> case
>>>>>>> where the request would be allowed even without authentication),
>>>>>>> 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
>>>>>>> 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
>>>>>>> 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
>>>>>>> directly set in the request (possibly using lazy evaluation,
>>>>>>> code
>>>>>>> again in Request) or stuffed into a Principal implementation
via the
>>>>>>> UserRealm.  This really overloaded the idea of a Principal for
>>>>>>> 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
>>>>>>> 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
>>>>>>> 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
>>>>>>> JAAS.
>>>>>>> On the other hand the role handling is called by jetty or by
>>>>>>> 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)
>>>>>>> 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
>>>>>>> results into a ServerAuthResult object rather than modifying
>>>>>>> clientSubject directly and hiding user principal and group info
>>>>>>> some
>>>>>>> callback handers.  This lets ServerAuthentication support lazy
>>>>>>> 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
>>>>>>> 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
>>>>>>> system
>>>>>>> based on Callbacks.  The container (jetty) supplies the auth
>>>>>>> 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.
>>>>>>> meaning here is rather undefined but can be mapped to roles in
>>>>>>> way,
>>>>>>> such as by assuming the groups and roles are the same.
>>>>>>> The use of callbacks here still seems rather weird to me but
>>>>>>> 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
>>>>>>> part
>>>>>>> of the message exchange involves a request to j_security_check
>>>>>>> which is
>>>>>>> normally not a secured response.  Trying to evaluate auth for
>>>>>>> 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
>>>>>>> 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 | |
>>> ---------------------------------------------------------------------
>>> To unsubscribe from this list, please visit:
>> -- 
>> Jan Bartel, Webtide LLC | |
> ---------------------------------------------------------------------
> To unsubscribe from this list, please visit:

Jan Bartel, Webtide LLC | |

View raw message