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 <sberyoz...@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 <sberyoz...@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 >> <sberyoz...@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 <dval...@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:sberyoz...@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 >>>> dk...@apache.org >>>> http://dankulp.com/blog >>>> >>> >>> >> >