You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cxf.apache.org by Sergey Beryozkin <sb...@gmail.com> on 2010/05/04 19:16:58 UTC

Re: Using WS-Security UsernameToken to authenticate users and populate SecurityContexts

I'm going to merge [1]

into 2.2.8-SNAPSHOT. Note that for a java-first case I've renamed
AbstractWSS4JSecurityContextProvidingInterceptor to
AbstractUsernameTokenAuthenticatingInterceptor (and this is still a bit too
long, will likely remain tomorrow to
AbstractUsernameAuthenticatingInterceptor), for it to reflect better what
its goal is; for a policy-first case [1] does not even introduce any new
interceptors but just makes it possible for users to extend
UsernameTokenInterceptor, when only UT is involved...

The only bit I'm not 100% happy about is that users would need to indicate
(in a policy first case), through the use of a bus property, that a custom
interceptor has to be registered instead. I guess the policy engine can be
extended somehow later so that users configure a policy engine instead...

cheers, Sergey

[1] http://svn.apache.org/viewvc?rev=936521&view=rev<http://svn.apache.org/viewvc?rev=936521&view=rev>

On Wed, Apr 21, 2010 at 10:47 PM, Sergey Beryozkin <sb...@gmail.com>wrote:

> I added a system test for a policy first case and refactored few bits along
> the way, as well as closed [1] as 'Wont fix', at least for now.
>
> I've just updated UsernameTokenInterceptor[1] so that a (WSS4J) principal
> can be created directly if a message property disabling the validation of
> passwords has been set.
>
> This property can be set as a jaxws contextual property in which case
> interceptors further in the chain will be able to get the (unauthenticated)
> Principal, validate it, and set a SecurityContext as needed.
>
> Another approach used in the system test is to write a custom
> interceptor[3] extending UsernameTokenInterceptor and disable the validation
> from there. This custom interceptor is currently being registered by setting
> a bus property, see [4]. Note that a jaxws endpoint adds
> SimpleAuthorizationInterceptor only and has no callbacks registered.
>
> See [5] for more details.
>
> It looks quite reasonable to me at the moment, perhaps there could be a
> simpler way to register custom interceptors.
>
> Dan, you've mentioned the fact you were planning to refactor some of the
> policy interceptors so that WSS4JInterceptor is not used for UsernameToken
> processing at all. I'd appreciate if you could look into this refactoring
> yourself, there could be some subtleties there I'm not aware of. Also,
> personally I'd prefer registering a noop processor with WSS4J rather adding
> a flag to WSS4J, perhaps this noop processor can be used for handling other
> types of tokens, using an approach similar to the one taken by
> UsernameTokenInterceptor, unless yourself, David V, others have something
> else in mind...
>
> cheers, Sergey
>
> [1] https://issues.apache.org/jira/browse/WSS-229
> [2]
> http://svn.apache.org/repos/asf/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/UsernameTokenInterceptor.java
> [3]
> http://svn.apache.org/repos/asf/cxf/trunk/systests/ws-specs/src/test/java/org/apache/cxf/systest/ws/wssec10/server/CustomUsernameTokenInterceptor.java
> [4]
> http://svn.apache.org/repos/asf/cxf/trunk/systests/ws-specs/src/test/java/org/apache/cxf/systest/ws/wssec10/server/server_restricted_authorized.xml
> [5] http://svn.apache.org/viewvc?rev=936521&view=rev
>
>
>
> On Mon, Apr 19, 2010 at 1:46 PM, Sergey Beryozkin <sb...@gmail.com>wrote:
>
>> Hi
>>
>> I've added an initial patch for addressing a policy-first case, see [1].
>> It's a patch because it depends on another one I submitted to WSS4J [2].
>> Both patches need more work (tests, etc) but I'd just like to initiate a
>> discussion/review.
>>
>> The idea behind [1] is quite similar to the one used in supporting a
>> java-first case, where a custom interceptor extends an
>> AbstractWSS4JSecurityContextPr
>> oviding interceptor. But is is much simpler in [1] where
>> UsernameTokenProcessor may be optionally extended and its createSubject
>> method be overridden. Provided [2] gets applied then a subclass will just
>> have a property set disabling the (WSS4J) validation of passwords and will
>> do its own validation in createSubject method.
>>
>> This is really all what will be needed in simple cases, where a
>> DefaultSecurityContext will do, but optionally, createSecurityContext  can
>> be overridden too.
>>
>> A user would need to set a bus property
>> "org.apache.cxf.ws.security.usernametoken.interceptor" referincing a custom
>> interceptor which will indicate to the WSSecurityPolicyLoader that a custom
>> UsernameTokenProcessor subclass will need to be loaded.
>>
>> Similar approach can be employed for handling other types of tokens.
>>
>> cheers, Sergey
>>
>> [1] https://issues.apache.org/jira/browse/CXF-2754
>> [2] https://issues.apache.org/jira/browse/WSS-229
>>
>>
>> On Mon, Apr 19, 2010 at 1:43 PM, Sergey Beryozkin <sb...@gmail.com>wrote:
>>
>>> Just realized I did not CC tp dev when replying to Dan the other day :
>>>
>>> Hi Dan
>>>
>>>
>>> On Fri, Apr 9, 2010 at 2:50 PM, Daniel Kulp <dk...@apache.org> wrote:
>>>
>>>>
>>>> My main "concern" with the implementation of this is that it's done as a
>>>> direct subclass of the WSS4JInInterceptor and thus not really usable by
>>>> the
>>>> policy based endpoints as those interceptors subclass WSS4JInInterceptor
>>>> as
>>>> well.
>>>>
>>>> I think the better approach may be to add a flag to wss4j (I can help
>>>> commit
>>>> changes there if needed) to have it not do any UserName token processing
>>>> at
>>>> all.   (aside:  this may be doable without changes to wss4j by
>>>> registering our
>>>> own "do nothing processor")    Then, have another interceptor that runs
>>>> after
>>>> the WSS4JInInterceptor that would actually handle the UsernameToken and
>>>> verify
>>>> anything it needs and such.
>>>>
>>>
>>> This sounds like a very good idea, I agree the proposed approach won't do
>>> for the cases where policies drive the
>>> creation of interceptors.
>>>
>>> Having said that, I think the abstract utility interceptor extending
>>> WSS4JInInterceptor
>>> may still be used in cases where users start from manually configuring
>>> jaxws endpoints. In these cases they'd need to
>>> list up to 3 interceptors (the one which extends
>>> AbstractWSS4JSecuriyContextInterceptor, the authorizing interceptor if the
>>> authorization is needed plus may be a SAAJ one) but otherwise, when say a
>>> clear text password has been encrypted, they'd still need to specify
>>> WSS4JInInterceptor (with a flag disabling UsernameToken checks) plus
>>> UsernameTokenInterceptor, etc.
>>>
>>> At the moment AbstractWSS4JSecuriyContextInterceptor is a bit complicated
>>> due to the fact it blocks the WSS4J digest checks and thus also creates a
>>> security engine per every request, but it all will be gone in due time...
>>>
>>>
>>>>
>>>> To be honest, I WANT to do this for the Policy based stuff anyway.
>>>> There is
>>>> currently some duplicated code between the
>>>> PolicyBasedWSS4JIinInterceptor and
>>>> the new UsernameTokenInterceptor that could be eliminated by having the
>>>> PolicyBasedWSS4JIinInterceptor not do UsernameTokens at all and delegate
>>>> that
>>>> completely to the UsernameTokenInterceptor.
>>>>
>>>
>>> What I will do is I will experiment with the test you added (thanks :-))
>>> and see how UsernameTokenInterceptor can be refactored
>>> so that a subclass can get an easy access to password, nonce, etc. I
>>> think I will need to come up with a contextual property so that a custom
>>> UsernameTokenInterceptor can be installed if needed. Or may be
>>> UsernameTokenInterceptor can store the details in a message to be later
>>> retrieved and processed for creating SecurityContext - but I'm not sure
>>> about it just yet.
>>>
>>>
>>>>
>>>> Basically, it would be good if the WSS4JIn* stuff just handled the
>>>> encryption/signature stuff and then let the authorization validations
>>>> stuff to
>>>> later interceptors.   That would include things like key validation
>>>> checking
>>>> and stuff as well.  Probably SAML token validation as well.
>>>>
>>>>
>>> sounds good
>>>
>>> cheers, Sergey
>>>
>>> On Fri, Apr 9, 2010 at 2:50 PM, Daniel Kulp <dk...@apache.org> wrote:
>>>
>>>>
>>>> My main "concern" with the implementation of this is that it's done as a
>>>> direct subclass of the WSS4JInInterceptor and thus not really usable by
>>>> the
>>>> policy based endpoints as those interceptors subclass WSS4JInInterceptor
>>>> as
>>>> well.
>>>>
>>>> I think the better approach may be to add a flag to wss4j (I can help
>>>> commit
>>>> changes there if needed) to have it not do any UserName token processing
>>>> at
>>>> all.   (aside:  this may be doable without changes to wss4j by
>>>> registering our
>>>> own "do nothing processor")    Then, have another interceptor that runs
>>>> after
>>>> the WSS4JInInterceptor that would actually handle the UsernameToken and
>>>> verify
>>>> anything it needs and such.
>>>>
>>>> To be honest, I WANT to do this for the Policy based stuff anyway.
>>>> There is
>>>> currently some duplicated code between the
>>>> PolicyBasedWSS4JIinInterceptor and
>>>> the new UsernameTokenInterceptor that could be eliminated by having the
>>>> PolicyBasedWSS4JIinInterceptor not do UsernameTokens at all and delegate
>>>> that
>>>> completely to the UsernameTokenInterceptor.
>>>>
>>>> Basically, it would be good if the WSS4JIn* stuff just handled the
>>>> encryption/signature stuff and then let the authorization validations
>>>> stuff to
>>>> later interceptors.   That would include things like key validation
>>>> checking
>>>> and stuff as well.  Probably SAML token validation as well.
>>>>
>>>> Dan
>>>>
>>>>
>>>> On Thursday 08 April 2010 12:09:24 pm Sergey Beryozkin wrote:
>>>> > Hi David
>>>> >
>>>> > thanks for the comments...
>>>> >
>>>> > On Wed, Apr 7, 2010 at 9:41 PM, David Valeri <dv...@apache.org>
>>>> wrote:
>>>> > > Sergey,
>>>> > >
>>>> > > I think this type of functionality would be very useful to a number
>>>> of
>>>> > > folks.  I have built two similar capabilities for clients very
>>>> recently
>>>> > > using CXF and Spring Security.  Based on the code provided below, I
>>>> have
>>>> > > several points that I would like to see addressed in a solution.
>>>> > >
>>>> > > 1) Architecture to support more than just UsernameTokens.  I have
>>>> worked
>>>> > > with systems that need to authenticate a user using UsernameTokens,
>>>> > > BinarySecurityTokens, SAML Assertions, and a combination of more
>>>> than one
>>>> > > of
>>>> > > these at a time.
>>>> >
>>>> > Supporting UsernameTokens is the initial requirement. At the moment I
>>>> do
>>>> > not even know how BinarySecurityTokens or SAML Assertions are
>>>> > processed/validated in CXF or WSS4J.
>>>> >
>>>> > > For the most part, WSS4J simply validates the structural
>>>> > > details of security.  That is, signature validity, trust chaining of
>>>> > > digital
>>>> > > certificates, etc.  As Glen pointed out with his reference to
>>>> > > https://issues.apache.org/jira/browse/WSS-183, WSS4J sometimes
>>>> performs
>>>> > > its
>>>> > > own password checking (authentication).  Unfortunately, WSS4J
>>>> doesn't
>>>> > > provide hooks for authenticating other forms of credentials that I
>>>> have
>>>> > > listed above (I don't consider trust to be equivalent to
>>>> authentication).
>>>> > > It would be best if the authentication interface supported multiple
>>>> > > credential types and allowed for authentication to be performed in a
>>>> > > single location in the same manner every time (not sometimes in the
>>>> > > WSS4J callback and sometimes in another interceptor for non-UT based
>>>> > > credentials).
>>>> >
>>>> > Makes sense. Assuming it is WSS4J which validates (the structure of)
>>>> > BinarySecurityTokens then
>>>>  AbstractWSS4JSecurityContextProvidingInterceptor
>>>> > can also implement a processor for BinarySecurityTokens and delegate
>>>> to
>>>> > subclass to authenticate and setup a subject. Some extra methods will
>>>> need
>>>> > to be added, to be optionally overridden.
>>>> >
>>>> > If it is not only WSS4J which is involved then perhaps another option
>>>> is to
>>>> > store (from WSS4J callback handler, etc) relevant details such
>>>> username
>>>> > token details, etc to be acted upon by other interceptors.
>>>> >
>>>> > > That
>>>> > > last bit there means disabling WSS4J's password authentication since
>>>> it
>>>> > > gets
>>>> > > in the way of doing it later in our own interceptor.
>>>> >
>>>> > AbstractWSS4JSecurityContextProvidingInterceptor does it now by
>>>> > implementing a simplified UsernameTokenProcessor
>>>> >
>>>> > > 2) Allow for end-user flexibility in choosing the credentials they
>>>> want
>>>> > > to authenticate.  For instance, each user is going to have their own
>>>> > > security profiles and authentication requirements.  For instance, a
>>>> > > message contains a UT for a portal user and a digital signature from
>>>> the
>>>> > > portal (I know using
>>>> > > a SAML Assertion would be better here, but people still do it this
>>>> way).
>>>> > > Each organization will have different requirements as to which
>>>> > > credentials get authenticated and what needs to end up in the
>>>> security
>>>> > > context.
>>>> >
>>>> > I suppose AbstractWSS4JSecurityContextProvidingInterceptor subclasses
>>>> > should be able to do it, for username tokens and other tokens later
>>>> on.
>>>> >
>>>> > > 3) Decouple the authentication interface from WSS4J.  What is passed
>>>> in
>>>> > > needs to be abstracted enough that it can work with other
>>>> WS-Security
>>>> > > libraries as well.
>>>> >
>>>> > the only WSS4J class which is leaked at the moment is
>>>> WSSecurityException.
>>>> > Perhaps we can come up later on with a different more generic approach
>>>> > which does not depend on WSS4J at all. As Dan indicated, in some cases
>>>> > WSS4JInInterceptor is not even used, so that case will need to be
>>>> > addressed. Experimenting wuth binary tokens might help with
>>>> identifying
>>>> > another solution.
>>>> >
>>>> > > 4) It would be nice to be able to perform authorization using
>>>> something
>>>> > > like
>>>> > > Spring Security at the service operation level.  With a POJO or
>>>> JAX-WS
>>>> > > based
>>>> > > service, one can just use Spring Security's method interceptor to
>>>> provide
>>>> > > such security; however, in situations where one only has a WSDL
>>>> based
>>>> > > service or a provider style service, a method interceptor can't be
>>>> used.
>>>> > >
>>>> > >  It
>>>> > >
>>>> > > would be nice to provide a hook into Spring Security to allow
>>>> end-users
>>>> > > to specify role based authorization policy based on a combination of
>>>> > > interface,
>>>> > > instance, and operation names.  It seems like your
>>>> > > AbstractAuthorizingInterceptor and SimpleAuthorizingInterceptor are
>>>> > > looking in this direction, but I think it would be best if we can
>>>> stand
>>>> > > on the shoulders of the Spring Security giant as much as possible so
>>>> > > that we can take advantage of their rich authorization manager,
>>>> voter,
>>>> > > XML
>>>> > > configuration
>>>> > > capabilities.
>>>> >
>>>> > Not sure what to say here yet. But I think non-Spring users should be
>>>> taken
>>>> > care of too. Or when simpler cases are dealt with then perhaps there's
>>>> no
>>>> > need to bring in Spring security. Perhaps the utility authorization
>>>> > interceptors should just not be used when Spring Security is preferred
>>>> ?
>>>> >
>>>> > > 5) Try not to leave the ServiceMix CXF-BC out in the cold.  The
>>>> CXF-BC
>>>> > > currently has a limited capability to select the credentials to
>>>> > > authenticate
>>>> > > and would benefit from 1 and 2 above.  The CXF-BC ultimately
>>>> delegates
>>>> > > authentication to the JBI container through a ServiceMix components
>>>> > > authentication service abstraction of JAAS.  Whatever solution we
>>>> have
>>>> > > for 1
>>>> > > and 2 would help out the component if the ServiceMix authentication
>>>> > > service abstraction could be wired up in lieu of whatever we provide
>>>> out
>>>> > > of the box.
>>>> >
>>>> > I'm not planning to contribute to ServiceMix. I agree though that an
>>>> ideal
>>>> > solution will meet multiple requirements
>>>> >
>>>> > thanks, Sergey
>>>> >
>>>> > > -----Original Message-----
>>>> > > From: Sergey Beryozkin [mailto:sberyozkin@gmail.com]
>>>> > > Sent: Wednesday, April 07, 2010 10:11 AM
>>>> > > To: dev@cxf.apache.org
>>>> > > Subject: Using WS-Security UsernameToken to authenticate users and
>>>> > > populate SecurityContexts
>>>> > >
>>>> > > Hi
>>>> > >
>>>> > > I've been looking recently at extending the CXF WS-Security
>>>> component
>>>> > > such that a current UsernameToken could be used by custom
>>>> interceptors
>>>> > > to authenticate a user with the external security systems and, if
>>>> > > possible, provide enough information for CXF to populate a
>>>> > > SecurityContext [1] to be used later on for
>>>> > > authorization decisions.
>>>> > >
>>>> > > Here is the approach I've taken so far.
>>>> > > A custom interceptor extends
>>>> > > AbstractWSS4JSecurityContextProvidingInterceptor [2] and the only
>>>> method
>>>> > > it overrides is
>>>> > >
>>>> > > abstract Subject createSubject(String name, String password, boolean
>>>> > > isDigest,
>>>> > >
>>>> > >                                    String nonce,
>>>> > >                                    String created) throws
>>>> > >
>>>> > > WSSecurityException;
>>>> > >
>>>> > >
>>>> > > For example, see [3].
>>>> > >
>>>> > > The idea here is that a custom interceptor interfaces whichever way
>>>> it
>>>> > > needs
>>>> > > to with the external system and populates a Subject following this
>>>> simple
>>>> > > rule : first Subject principal is the current user (identified by a
>>>> > > 'name' argument), followed by one or more Groups this user is a
>>>> member
>>>> > > of. AbstractWSS4JSecurityContextProvidingInterceptor will use this
>>>> > > Subject to provide a functional SecurityContext instance.
>>>> > >
>>>> > > This is the first part, next is how to utilize a SecurityContext and
>>>> get
>>>> > > the
>>>> > > expected roles associated one way or the other with a current method
>>>> to
>>>> > > be invoked. There's a number of usual options available here,
>>>> perhaps
>>>> > > even SpringSecurity can be used now that SecurityContext is
>>>> available,
>>>> > > or application code or other custom CXF interceptor can check the
>>>> known
>>>> > > roles against SecurityContext.
>>>> > >
>>>> > > I've also added AbstractAuthorizingInInterceptor interceptor which
>>>> custom
>>>> > > interceptors can override and return a list of expected roles given
>>>> a
>>>> > > (service) Method to be invoked upon,
>>>> AbstractAuthorizingInInterceptor
>>>> > > will then ask available SecurityContext to match the roles; one
>>>> concrete
>>>> > > implementation is SimpleAuthorizingInterceptor[5], it can be
>>>> injected
>>>> > > with a
>>>> > > method specific or class (applying to all methods) roles. Another
>>>> > > implementation which I will likely add later on will be injected
>>>> with a
>>>> > > name
>>>> > > of annotation such as RolesAlloved and it will introspect a method
>>>> and
>>>> > > its class.
>>>> > >
>>>> > > Note that I haven't looked into the case when a policy runtimes adds
>>>> the
>>>> > > interceptors yet (as opposed to interceptors being configured form
>>>> > > Spring/programmatically). I think an optional contextual property
>>>> will
>>>> > > need to be setup in such cases for users be able to indicate that
>>>> say an
>>>> > > interceptor such as [3] has to be used as opposed to
>>>> WSS4JInInterceptor,
>>>> > > etc.
>>>> > >
>>>> > > I'm going to validate this approach with JBoss CXF. If you have any
>>>> > > comments
>>>> > > then please let me know.
>>>> > >
>>>> > > I think we may have a simpler alternative eventually to the way
>>>> > > authorization decisions are made. [1]-[3] is specific to
>>>> ws-security, but
>>>> > > [4]-[5] is not
>>>> > >
>>>> > > cheers, Sergey
>>>> > >
>>>> > > [1] https://issues.apache.org/jira/browse/CXF-2754
>>>> > > [2]
>>>> > >
>>>> > >
>>>> http://svn.apache.org/repos/asf/cxf/trunk/rt/ws/security/src/main/java/or
>>>> > > g/a
>>>> > >
>>>> > >
>>>> pache/cxf/ws/security/wss4j/AbstractWSS4JSecurityContextProvidingIntercep
>>>> > > tor<
>>>> http://svn.apache.org/repos/asf/cxf/trunk/rt/ws/security/src/main/jav
>>>> > >
>>>> a/org/a%0Apache/cxf/ws/security/wss4j/AbstractWSS4JSecurityContextProvidi
>>>> > > ngInterceptor> .java
>>>> > > [3]
>>>> > >
>>>> > >
>>>> http://svn.apache.org/repos/asf/cxf/trunk/rt/ws/security/src/test/java/or
>>>> > > g/a
>>>> > >
>>>> pache/cxf/ws/security/wss4j/SimpleSubjectCreatingInterceptor.java<http:/
>>>> > > /
>>>> svn.apache.org/repos/asf/cxf/trunk/rt/ws/security/src/test/java/org/a%0A
>>>> > > pache/cxf/ws/security/wss4j/SimpleSubjectCreatingInterceptor.java>
>>>> [4]
>>>> > >
>>>> > >
>>>> http://svn.apache.org/repos/asf/cxf/trunk/rt/core/src/main/java/org/apach
>>>> > > e/c
>>>> > > xf/interceptor/security/AbstractAuthorizingInInterceptor.java<
>>>> http://svn
>>>> > > .
>>>> apache.org/repos/asf/cxf/trunk/rt/core/src/main/java/org/apache/c%0Axf/i
>>>> > > nterceptor/security/AbstractAuthorizingInInterceptor.java> [5]
>>>> > >
>>>> > >
>>>> http://svn.apache.org/repos/asf/cxf/trunk/rt/core/src/main/java/org/apach
>>>> > > e/c
>>>> > > xf/interceptor/security/SimpleAuthorizingInterceptor.java<
>>>> http://svn.apa
>>>> > >
>>>> che.org/repos/asf/cxf/trunk/rt/core/src/main/java/org/apache/c%0Axf/inter
>>>> > > ceptor/security/SimpleAuthorizingInterceptor.java>
>>>>
>>>> --
>>>> Daniel Kulp
>>>> dkulp@apache.org
>>>> http://dankulp.com/blog
>>>>
>>>
>>>
>>
>